From 249bcb881fce332fcbb980efbea7ab3d08ab70e1 Mon Sep 17 00:00:00 2001 From: Alfonso Grillo Date: Tue, 13 Jun 2023 14:02:38 +0200 Subject: [PATCH] Add search modifiers (#1070) --- ElementX.xcodeproj/project.pbxproj | 4 ++ ElementX/Sources/Other/SwiftUI/Search.swift | 57 +++++++++++++++++++ .../View/InviteUsersScreen.swift | 2 + .../View/StartChatScreen.swift | 2 + 4 files changed, 65 insertions(+) create mode 100644 ElementX/Sources/Other/SwiftUI/Search.swift diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index f7d2b01c5..342e362a3 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -246,6 +246,7 @@ 65EDA77363BEDC40CDE43B43 /* InvitesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42ADEA322D2089391E049535 /* InvitesScreen.swift */; }; 661A664C6EDF856B05519206 /* FilePreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F562E2CBA002E8E1B6545C38 /* FilePreviewScreen.swift */; }; 663E198678778F7426A9B27D /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FAFE1C2149E6AC8156ED2B /* Collection.swift */; }; + 67160204A8D362BB7D4AD259 /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E16574C6F7F9FA1015A8C /* Search.swift */; }; 67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; 67D6E0700A9C1E676F6231F8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = AD544C0FA48DFFB080920061 /* Collections */; }; 68184EF36396424FE19A727D /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; }; @@ -957,6 +958,7 @@ 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = ""; }; 6861FE915C7B5466E6962BBA /* StartChatScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreen.swift; sourceTree = ""; }; 69219A908D7C22E6EE6689AE /* UserNotificationCenterSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterSpy.swift; sourceTree = ""; }; + 693E16574C6F7F9FA1015A8C /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = ""; }; 69B63F817FE305548DB4B512 /* RoomMembersListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListViewModelTests.swift; sourceTree = ""; }; 69D42EE0102D2857933625DD /* CreateRoomViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModelTests.swift; sourceTree = ""; }; 6A4C9547BBFEEF30AA11329B /* TimelineItemStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemStatusView.swift; sourceTree = ""; }; @@ -1406,6 +1408,7 @@ 052CC920F473C10B509F9FC1 /* SwiftUI */ = { isa = PBXGroup; children = ( + 693E16574C6F7F9FA1015A8C /* Search.swift */, E2DA161C142B7AB8CC40F752 /* Animation */, 595B8797ED6A7489ABDCE384 /* ErrorHandling */, 1BC3028DDD0C27AE5318FEDC /* Form Styles */, @@ -4083,6 +4086,7 @@ D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */, 0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */, 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */, + 67160204A8D362BB7D4AD259 /* Search.swift in Sources */, 339BC18777912E1989F2F17D /* Section.swift in Sources */, 14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */, 49F2E7DD8CAACE09CEECE3E6 /* SeparatorRoomTimelineView.swift in Sources */, diff --git a/ElementX/Sources/Other/SwiftUI/Search.swift b/ElementX/Sources/Other/SwiftUI/Search.swift new file mode 100644 index 000000000..b1f239c4f --- /dev/null +++ b/ElementX/Sources/Other/SwiftUI/Search.swift @@ -0,0 +1,57 @@ +// +// Copyright 2023 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +extension View { + /// Disable the interactive dismiss while the search is on. + /// - Note: the modifier needs to be called before the `searchable` modifier to work properly + func disableInteractiveDismissOnSearch() -> some View { + modifier(InteractiveDismissSearchModifier()) + } + + /// Dismiss search when the view is disappearing. It helps to restore correct state on pop into a NavigationStack + /// - Note: the modifier needs to be called before the `searchable` modifier to work properly + func dismissSearchOnDisappear() -> some View { + modifier(DismissSearchOnDisappear()) + } +} + +private struct InteractiveDismissSearchModifier: ViewModifier { + @Environment(\.isSearching) private var isSearching + + func body(content: Content) -> some View { + if isSearching { + content.interactiveDismissDisabled() + } else { + content + } + } +} + +private struct DismissSearchOnDisappear: ViewModifier { + @Environment(\.isSearching) private var isSearching + @Environment(\.dismissSearch) private var dismissSearch + + func body(content: Content) -> some View { + content + .onDisappear { + if isSearching { + dismissSearch() + } + } + } +} diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift index a42c58d66..71229b039 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift @@ -31,6 +31,8 @@ struct InviteUsersScreen: View { nextButton } } + .disableInteractiveDismissOnSearch() + .dismissSearchOnDisappear() .searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always), prompt: L10n.commonSearchForSomeone) .introspectSearchController { searchViewController in searchViewController.hidesNavigationBarDuringPresentation = false diff --git a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift index 3566b23e2..261a4e821 100644 --- a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift +++ b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift @@ -37,6 +37,8 @@ struct StartChatScreen: View { closeButton } } + .disableInteractiveDismissOnSearch() + .dismissSearchOnDisappear() .searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always), prompt: L10n.commonSearchForSomeone) .compoundSearchField() .alert(item: $context.alertInfo) { $0.alert }