@@ -24,6 +24,7 @@ import QMSFeature
2424import SettingsFeature
2525import NotificationsFeature
2626import DeveloperFeature
27+ import ToastClient
2728import AlertToast
2829import SFSafeSymbols
2930import SharedUI
@@ -48,27 +49,34 @@ public struct AppView: View {
4849 WithPerceptionTracking {
4950 ZStack ( alignment: . bottom) {
5051 TabView ( selection: $store. selectedTab) {
51- ArticlesListTab ( )
52- FavoritesTab ( )
53- ForumTab ( )
54- ProfileTab ( )
52+ StackTabView ( store: store. scope ( state: \. articlesTab, action: \. articlesTab) )
53+ . tag ( AppTab . articles)
54+
55+ StackTabView ( store: store. scope ( state: \. favoritesTab, action: \. favoritesTab) )
56+ . tag ( AppTab . favorites)
57+
58+ StackTabView ( store: store. scope ( state: \. forumTab, action: \. forumTab) )
59+ . tag ( AppTab . forum)
60+
61+ StackTabView ( store: store. scope ( state: \. profileTab, action: \. profileTab) )
62+ . tag ( AppTab . profile)
5563 }
5664
5765 Group {
58- if store. isShowingTabBar {
66+ if store. showTabBar {
5967 PDATabView ( )
6068 . transition ( . move( edge: . bottom) )
6169 }
6270 }
6371 // Animation on whole ZStack breaks safeareainset for next screens
64- . animation ( . default, value: store. isShowingTabBar )
72+ . animation ( . default, value: store. showTabBar )
6573
66- if store. showToast {
67- Toast ( )
74+ if let toast = store. toastMessage {
75+ Toast ( toast )
6876 . ignoresSafeArea ( . keyboard, edges: . bottom)
6977 }
7078 }
71- . animation ( . default, value: store. showToast )
79+ . animation ( . default, value: store. toastMessage )
7280 . ignoresSafeArea ( . keyboard, edges: . bottom)
7381 . preferredColorScheme ( store. appSettings. appColorScheme. asColorScheme)
7482 . fullScreenCover ( item: $store. scope ( state: \. auth, action: \. auth) ) { store in
@@ -86,155 +94,6 @@ public struct AppView: View {
8694 }
8795 }
8896
89- // MARK: - Articles List Tab
90-
91- @ViewBuilder
92- private func ArticlesListTab( ) -> some View {
93- NavigationStack (
94- path: $store. scope ( state: \. articlesPath, action: \. articlesPath)
95- ) {
96- ArticlesListScreen ( store: store. scope ( state: \. articlesList, action: \. articlesList) )
97- . tracking ( for: ArticlesListScreen . self)
98- } destination: { store in
99- WithPerceptionTracking {
100- switch store. case {
101- case let . article( store) :
102- ArticleScreen ( store: store)
103- . tracking ( for: ArticleScreen . self, [ " id " : store. articlePreview. id] )
104-
105- case let . profile( store) :
106- ProfileScreen ( store: store)
107- . tracking ( for: ProfileScreen . self, [ " id " : store. userId ?? 0 ] )
108-
109- case let . settingsPath( path) :
110- SettingsPath ( path)
111- }
112- }
113- }
114- . tag ( AppTab . articlesList)
115- . toolbar ( store. isShowingTabBar ? . visible : . hidden, for: . tabBar)
116- }
117-
118- // MARK: - Favorites Tab
119- @ViewBuilder
120- private func FavoritesTab( ) -> some View {
121- NavigationStack (
122- path: $store. scope ( state: \. favoritesRootPath, action: \. favoritesRootPath)
123- ) {
124- FavoritesRootScreen ( store: store. scope ( state: \. favoritesRoot, action: \. favoritesRoot) )
125- . tracking ( for: FavoritesRootScreen . self)
126- } destination: { store in
127- switch store. case {
128- case let . forumPath( path) :
129- ForumPath ( path)
130-
131- case let . settingsPath( path) :
132- SettingsPath ( path)
133- }
134- }
135- . tag ( AppTab . favorites)
136- . toolbar ( store. isShowingTabBar ? . visible : . hidden, for: . tabBar)
137- }
138-
139- // MARK: - Forum Tab
140-
141- @ViewBuilder
142- private func ForumTab( ) -> some View {
143- NavigationStack (
144- path: $store. scope ( state: \. forumPath, action: \. forumPath)
145- ) {
146- ForumsListScreen ( store: store. scope ( state: \. forumsList, action: \. forumsList) )
147- . tracking ( for: ForumsListScreen . self)
148- } destination: { store in
149- ForumPath ( store)
150- }
151- . tag ( AppTab . forum)
152- . toolbar ( store. isShowingTabBar ? . visible : . hidden, for: . tabBar)
153- }
154-
155- // MARK: - Profile Tab
156-
157- @ViewBuilder
158- private func ProfileTab( ) -> some View {
159- NavigationStack (
160- path: $store. scope ( state: \. profilePath, action: \. profilePath)
161- ) {
162- ProfileScreen ( store: store. scope ( state: \. profile, action: \. profile) )
163- . tracking ( for: ProfileScreen . self)
164- } destination: { store in
165- switch store. case {
166- case let . history( store) :
167- HistoryScreen ( store: store)
168- . tracking ( for: HistoryScreen . self)
169- case let . qmsPath( path) :
170- QMSPath ( path)
171- case let . settingsPath( path) :
172- SettingsPath ( path)
173- }
174- }
175- . tag ( AppTab . profile)
176- . toolbar ( store. isShowingTabBar ? . visible : . hidden, for: . tabBar)
177- }
178-
179- // MARK: - QMS Path
180-
181- @ViewBuilder
182- private func QMSPath( _ store: StoreOf < AppFeature . QMSPath . Body > ) -> some View {
183- switch store. case {
184- case let . qmsList( store) :
185- QMSListScreen ( store: store)
186- . tracking ( for: QMSListScreen . self)
187- case let . qms( store) :
188- QMSScreen ( store: store)
189- . tracking ( for: QMSScreen . self)
190- }
191- }
192-
193- // MARK: - Forum Path
194-
195- @ViewBuilder
196- private func ForumPath( _ store: StoreOf < AppFeature . ForumPath . Body > ) -> some View {
197- WithPerceptionTracking {
198- switch store. case {
199- case let . forum( store) :
200- ForumScreen ( store: store)
201- . tracking ( for: ForumScreen . self, [ " id " : store. forumId] )
202-
203- case let . topic( store) :
204- TopicScreen ( store: store)
205- . tracking ( for: TopicScreen . self, [ " id " : store. topicId] )
206-
207- case let . profile( store) :
208- ProfileScreen ( store: store)
209- . tracking ( for: ProfileScreen . self, [ " id " : store. userId ?? 0 ] )
210-
211- case let . announcement( store) :
212- AnnouncementScreen ( store: store)
213- . tracking ( for: AnnouncementScreen . self, [ " id " : store. announcementId] )
214-
215- case let . settingsPath( path) :
216- SettingsPath ( path)
217- }
218- }
219- }
220-
221- // MARK: - Settings Path
222-
223- @ViewBuilder
224- private func SettingsPath( _ store: StoreOf < AppFeature . SettingsPath . Body > ) -> some View {
225- switch store. case {
226- case let . settings( store) :
227- SettingsScreen ( store: store)
228- . tracking ( for: SettingsScreen . self)
229- case let . developer( store) :
230- DeveloperScreen ( store: store)
231- . tracking ( for: DeveloperScreen . self)
232- case let . notifications( store) :
233- NotificationsScreen ( store: store)
234- . tracking ( for: NotificationsScreen . self)
235- }
236- }
237-
23897 // MARK: - PDA Tab View
23998
24099 @ViewBuilder
@@ -287,15 +146,15 @@ public struct AppView: View {
287146 @State private var duration = 5
288147
289148 @ViewBuilder
290- private func Toast( ) -> some View {
149+ private func Toast( _ toast : ToastMessage ) -> some View {
291150 HStack ( spacing: 0 ) {
292- Image ( systemSymbol: store . toast. isError ? . xmarkCircleFill : . checkmarkCircleFill)
151+ Image ( systemSymbol: toast. isError ? . xmarkCircleFill : . checkmarkCircleFill)
293152 . font ( . body)
294- . foregroundStyle ( store . toast. isError ? Color ( . Main. red) : tintColor)
153+ . foregroundStyle ( toast. isError ? Color ( . Main. red) : tintColor)
295154 . frame ( width: 32 , height: 32 )
296155
297156 if isExpanded {
298- Text ( store . toast. message , bundle: store . localizationBundle )
157+ Text ( toast. description , bundle: . toast )
299158 . font ( . caption)
300159 . foregroundStyle ( Color ( . Labels. primary) )
301160 . padding ( . trailing, 12 )
@@ -329,6 +188,15 @@ public struct AppView: View {
329188 }
330189}
331190
191+ // MARK: - UINC edge swipe enable
192+
193+ extension UINavigationController {
194+ override open func viewDidLoad( ) {
195+ super. viewDidLoad ( )
196+ interactivePopGestureRecognizer? . delegate = nil
197+ }
198+ }
199+
332200// MARK: - Model Extensions
333201
334202extension AppTintColor {
0 commit comments