mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-09 19:06:14 +00:00
ios: sheet with detents
This commit is contained in:
@@ -46,6 +46,13 @@ struct ChatListView: View {
|
||||
}
|
||||
}
|
||||
|
||||
var isUserPickerSheetPresented: Binding<Bool> {
|
||||
Binding(
|
||||
get: { activeUserPickerSheet != nil },
|
||||
set: { if !$0 { activeUserPickerSheet = nil } }
|
||||
)
|
||||
}
|
||||
|
||||
private var viewBody: some View {
|
||||
ZStack(alignment: oneHandUI ? .bottomLeading : .topLeading) {
|
||||
NavStackCompat(
|
||||
@@ -58,8 +65,9 @@ struct ChatListView: View {
|
||||
destination: chatView
|
||||
) { chatListView }
|
||||
}
|
||||
.sheet(item: $activeUserPickerSheet) { sheet in
|
||||
if let currentUser = chatModel.currentUser {
|
||||
.sheetWithDetents(isPresented: isUserPickerSheetPresented) {
|
||||
if let sheet = activeUserPickerSheet, let currentUser = chatModel.currentUser {
|
||||
Group {
|
||||
switch sheet {
|
||||
case .address:
|
||||
NavigationView {
|
||||
@@ -95,10 +103,14 @@ struct ChatListView: View {
|
||||
activeSheet: $activeUserPickerSheet
|
||||
)
|
||||
}
|
||||
}
|
||||
.environmentObject(ChatModel.shared)
|
||||
.environmentObject(AppTheme.shared)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var chatListView: some View {
|
||||
let tm = ToolbarMaterial.material(toolbarMaterial)
|
||||
return withToolbar(tm) {
|
||||
|
||||
80
apps/ios/Shared/Views/Helpers/SheetWithDetents.swift
Normal file
80
apps/ios/Shared/Views/Helpers/SheetWithDetents.swift
Normal file
@@ -0,0 +1,80 @@
|
||||
import SwiftUI
|
||||
|
||||
extension View {
|
||||
@ViewBuilder
|
||||
func sheetWithDetents<Content: View>(
|
||||
isPresented: Binding<Bool>,
|
||||
detents: [UISheetPresentationController.Detent] = [.medium(), .large()],
|
||||
@ViewBuilder content: @escaping () -> Content
|
||||
) -> some View {
|
||||
if #available(iOS 16, *) {
|
||||
sheet(isPresented: isPresented, content: content)
|
||||
.presentationDetents(
|
||||
Set(detents.compactMap { presentationDetent(detent:$0) })
|
||||
)
|
||||
} else {
|
||||
ZStack {
|
||||
SheetPresenter(
|
||||
isPresented: isPresented,
|
||||
detents: detents,
|
||||
content: content()
|
||||
)
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 16.0, *)
|
||||
private func presentationDetent(detent: UISheetPresentationController.Detent) -> PresentationDetent? {
|
||||
let map: [UISheetPresentationController.Detent.Identifier: PresentationDetent] = [
|
||||
.medium: .medium,
|
||||
.large: .large
|
||||
]
|
||||
return map[detent.identifier]
|
||||
}
|
||||
|
||||
/// An transparent view which is added to SwfttUI view hierarchy an presents a UIKit sheet with detents
|
||||
private struct SheetPresenter<Content: View>: UIViewRepresentable {
|
||||
@Binding var isPresented: Bool
|
||||
let detents: [UISheetPresentationController.Detent]
|
||||
let content: Content
|
||||
|
||||
func makeUIView(context: Context) -> UIView { UIView() }
|
||||
|
||||
func updateUIView(_ uiView: UIView, context: Context) {
|
||||
let hc = UIHostingController(rootView: content)
|
||||
if let spc = hc.presentationController as? UISheetPresentationController {
|
||||
spc.detents = detents
|
||||
spc.prefersGrabberVisible = true
|
||||
spc.prefersScrollingExpandsWhenScrolledToEdge = false
|
||||
spc.largestUndimmedDetentIdentifier = .medium
|
||||
}
|
||||
hc.presentationController?.delegate = context.coordinator
|
||||
if let root = uiView.window?.rootViewController {
|
||||
if isPresented {
|
||||
if root.presentedViewController != nil {
|
||||
// Simultaneous sheets are not allowed - dismiss the previous one
|
||||
root.dismiss(animated: true) { root.present(hc, animated: true) }
|
||||
} else {
|
||||
root.present(hc, animated: true)
|
||||
}
|
||||
} else {
|
||||
root.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator { Coordinator(isPresented: $isPresented) }
|
||||
|
||||
class Coordinator: NSObject, UISheetPresentationControllerDelegate {
|
||||
@Binding var isPresented: Bool
|
||||
|
||||
init(isPresented: Binding<Bool>) { self._isPresented = isPresented }
|
||||
|
||||
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
|
||||
isPresented = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@
|
||||
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = CE38A29B2C3FCD72005ED185 /* SwiftyGif */; };
|
||||
CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7548092C622630009579B7 /* SwipeLabel.swift */; };
|
||||
CE984D4B2C36C5D500E3AEFF /* ChatItemClipShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */; };
|
||||
CEB7E06F2C8779C800BC270C /* SheetWithDetents.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB7E06E2C8779C800BC270C /* SheetWithDetents.swift */; };
|
||||
CEDE70222C48FD9500233B1F /* SEChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDE70212C48FD9500233B1F /* SEChatState.swift */; };
|
||||
CEE723AA2C3BD3D70009AE93 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */; };
|
||||
CEE723B12C3BD3D70009AE93 /* SimpleX SE.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
@@ -537,6 +538,7 @@
|
||||
CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorAlert.swift; sourceTree = "<group>"; };
|
||||
CE7548092C622630009579B7 /* SwipeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeLabel.swift; sourceTree = "<group>"; };
|
||||
CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemClipShape.swift; sourceTree = "<group>"; };
|
||||
CEB7E06E2C8779C800BC270C /* SheetWithDetents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetWithDetents.swift; sourceTree = "<group>"; };
|
||||
CEDE70212C48FD9500233B1F /* SEChatState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEChatState.swift; sourceTree = "<group>"; };
|
||||
CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX SE.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -789,6 +791,7 @@
|
||||
8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */,
|
||||
CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */,
|
||||
CE7548092C622630009579B7 /* SwipeLabel.swift */,
|
||||
CEB7E06E2C8779C800BC270C /* SheetWithDetents.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
@@ -1431,6 +1434,7 @@
|
||||
647F090E288EA27B00644C40 /* GroupMemberInfoView.swift in Sources */,
|
||||
646BB38E283FDB6D001CE359 /* LocalAuthenticationUtils.swift in Sources */,
|
||||
8C74C3EA2C1B90AF00039E77 /* ThemeManager.swift in Sources */,
|
||||
CEB7E06F2C8779C800BC270C /* SheetWithDetents.swift in Sources */,
|
||||
5C7505A227B65FDB00BE3227 /* CIMetaView.swift in Sources */,
|
||||
5C35CFC827B2782E00FB6C6D /* BGManager.swift in Sources */,
|
||||
5CB634B129E5EFEA0066AD6B /* PasscodeView.swift in Sources */,
|
||||
|
||||
Reference in New Issue
Block a user