ios: new message sheet detents (#4639)

* ios: new message sheet detents

* animation

* use isActive

* fix sheet rendering

* minor

* increase onTap area

* cleanup

* cleanup

* refactor, dont allow reducing sheet once opened

---------

Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com>
This commit is contained in:
Evgeny
2024-08-10 22:18:49 +01:00
committed by GitHub
parent c90b71120f
commit 110839627f
@@ -61,18 +61,39 @@ struct NewChatSheet: View {
@State private var searchShowingSimplexLink = false
@State private var searchChatFilteredBySimplexLink: String? = nil
@Binding var alert: SomeAlert?
// Sheet height management
@State private var isAddContactActive = false
@State private var isScanPasteLinkActive = false
@State private var isLargeSheet = false
@State private var allowSmallSheet = true
@AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true
var body: some View {
NavigationView {
viewBody()
let showArchive = !filterContactTypes(chats: chatModel.chats, contactTypes: [.chatDeleted]).isEmpty
let v = NavigationView {
viewBody(showArchive)
.navigationTitle("New message")
.navigationBarTitleDisplayMode(.large)
.navigationBarHidden(searchMode)
.modifier(ThemedBackground(grouped: true))
}
if #available(iOS 16.0, *), oneHandUI {
let sheetHeight: CGFloat = showArchive ? 575 : 500
v.presentationDetents(
allowSmallSheet ? [.height(sheetHeight), .large] : [.large],
selection: Binding(
get: { isLargeSheet || !allowSmallSheet ? .large : .height(sheetHeight) },
set: { isLargeSheet = $0 == .large }
)
)
} else {
v
}
}
@ViewBuilder private func viewBody() -> some View {
@ViewBuilder private func viewBody(_ showArchive: Bool) -> some View {
List {
HStack {
ContactsListSearchBar(
@@ -90,21 +111,25 @@ struct NewChatSheet: View {
if (searchText.isEmpty) {
Section {
NavigationLink {
NavigationLink(isActive: $isAddContactActive) {
NewChatView(selection: .invite, parentAlert: $alert)
.navigationTitle("New chat")
.modifier(ThemedBackground(grouped: true))
.navigationBarTitleDisplayMode(.large)
} label: {
Label("Add contact", systemImage: "link.badge.plus")
navigateOnTap(Label("Add contact", systemImage: "link.badge.plus")) {
isAddContactActive = true
}
}
NavigationLink {
NavigationLink(isActive: $isScanPasteLinkActive) {
NewChatView(selection: .connect, showQRCodeScanner: true, parentAlert: $alert)
.navigationTitle("New chat")
.modifier(ThemedBackground(grouped: true))
.navigationBarTitleDisplayMode(.large)
} label: {
Label("Scan / Paste link", systemImage: "qrcode")
navigateOnTap(Label("Scan / Paste link", systemImage: "qrcode")) {
isScanPasteLinkActive = true
}
}
NavigationLink {
AddGroupView()
@@ -116,7 +141,7 @@ struct NewChatSheet: View {
}
}
if (!filterContactTypes(chats: chatModel.chats, contactTypes: [.chatDeleted]).isEmpty) {
if (showArchive) {
Section {
NavigationLink {
DeletedChats()
@@ -140,6 +165,22 @@ struct NewChatSheet: View {
}
}
/// Extends label's tap area to match `.insetGrouped` list row insets
private func navigateOnTap<L: View>(_ label: L, setActive: @escaping () -> Void) -> some View {
label
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.leading, 16).padding(.vertical, 8).padding(.trailing, 32)
.contentShape(Rectangle())
.onTapGesture {
isLargeSheet = true
DispatchQueue.main.async {
allowSmallSheet = false
setActive()
}
}
.padding(.leading, -16).padding(.vertical, -8).padding(.trailing, -32)
}
func newChatActionButton<Content : View>(_ icon: String, color: Color/* = .secondary*/, content: @escaping () -> Content) -> some View {
ZStack(alignment: .leading) {
Image(systemName: icon)