ios: sheet with detents

This commit is contained in:
Levitating Pineapple
2024-09-03 20:46:00 +03:00
parent 8e31b45be8
commit 331f9ef216
3 changed files with 98 additions and 2 deletions

View File

@@ -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) {

View 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
}
}
}

View File

@@ -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 */,