@@ -13,14 +13,22 @@ struct ContentView {
1313 @Environment ( \. horizontalSizeClass) private var hSizeClass
1414 @Binding var servers : Resolvers
1515 @Binding var usedID : String ?
16- @State private var isEnabled = false
16+ @State private var isActivated = false
1717 @State private var selection : Int ?
1818 @State private var isAlertPresented = false
1919 @State private var alertTitle = " "
2020 @State private var alertMessage = " "
2121 @State private var isGuidePresented = false
2222 @State private var isRestoring = false
2323
24+ private var navigationBarTitleDisplayMode : NavigationBarItem . TitleDisplayMode {
25+ if #available( iOS 26 , * ) {
26+ . inline
27+ } else {
28+ . automatic
29+ }
30+ }
31+
2432 private func addNewDoTServer( ) {
2533 self . servers. append (
2634 . init(
@@ -78,7 +86,7 @@ struct ContentView {
7886 logger. error ( " \( err. localizedDescription) " )
7987 self . alert ( " Load Error " , err. localizedDescription)
8088 } else {
81- self . isEnabled = manager. isEnabled
89+ self . isActivated = manager. isEnabled
8290 }
8391 }
8492 #endif
@@ -168,7 +176,6 @@ extension ContentView: View {
168176 private var modernBody : some View {
169177 NavigationSplitView {
170178 List ( selection: self . $selection) {
171- NavigationLink ( " Instructions " , value: - 1 )
172179 Section ( " Servers " ) {
173180 ForEach ( 0 ..< self . servers. count, id: \. self) { i in
174181 NavigationLink ( value: i) {
@@ -180,20 +187,29 @@ extension ContentView: View {
180187 }
181188 }
182189 . navigationTitle ( Bundle . main. displayName!)
183- . toolbar { self . toolbarContent }
190+ . navigationBarTitleDisplayMode ( self . navigationBarTitleDisplayMode)
191+ . toolbar {
192+ if #available( iOS 26 , * ) {
193+ ToolbarItem ( placement: . subtitle) {
194+ self . statusIndicator
195+ . foregroundStyle ( . secondary)
196+ }
197+ }
198+ self . toolbarContent
199+ }
184200 . alert ( self . alertTitle, isPresented: self . $isAlertPresented) {
185201 } message: {
186202 Text ( self . alertMessage)
187203 }
188204 } detail: {
189- if self . selection == - 1 {
190- HowToActivateView ( )
191- } else if let i = self . selection {
205+ if let i = self . selection, i >= 0 {
192206 NavigationStack {
193207 self . detailView ( at: i)
208+ . navigationBarTitleDisplayMode ( self . navigationBarTitleDisplayMode)
194209 }
195- } else if !self . isEnabled {
210+ } else if !self . isActivated {
196211 HowToActivateView ( )
212+ . navigationBarTitleDisplayMode ( self . navigationBarTitleDisplayMode)
197213 } else {
198214 Text ( " Select a server on the sidebar " )
199215 . navigationBarHidden ( true )
@@ -226,20 +242,6 @@ extension ContentView: View {
226242 private var legacyBody : some View {
227243 NavigationView {
228244 List {
229- if self . hSizeClass == . compact {
230- NavigationLink (
231- " Instructions " ,
232- tag: - 1 ,
233- selection: self . $selection
234- ) {
235- HowToActivateView ( )
236- }
237- } else {
238- // Workaround for iOS 15
239- Button ( " Instructions " ) {
240- self . selection = - 1
241- }
242- }
243245 Section ( " Servers " ) {
244246 ForEach ( 0 ..< self . servers. count, id: \. self) { i in
245247 if self . hSizeClass == . compact {
@@ -271,11 +273,9 @@ extension ContentView: View {
271273 Text ( self . alertMessage)
272274 }
273275
274- if self . selection == - 1 {
275- HowToActivateView ( )
276- } else if let i = self . selection {
276+ if let i = self . selection, i >= 0 {
277277 self . detailView ( at: i)
278- } else if !self . isEnabled {
278+ } else if !self . isActivated {
279279 HowToActivateView ( )
280280 } else {
281281 Text ( " Select a server on the sidebar " )
@@ -308,56 +308,51 @@ extension ContentView: View {
308308
309309 @ToolbarContentBuilder private var toolbarContent : some ToolbarContent {
310310 ToolbarItem ( placement: . topBarLeading) {
311- Menu ( " Add " , systemImage: " plus " ) {
312- Button ( " DNS-over-TLS " , action: self . addNewDoTServer)
313- Button ( " DNS-over-HTTPS " , action: self . addNewDoHServer)
314- Button ( " Restore from Presets " ) {
315- self . isRestoring = true
316- }
317- }
318- . sheet ( isPresented: self . $isRestoring) {
319- RestorationView ( onAdd: self . restoreFromPresets)
311+ if #available( iOS 26 , * ) {
312+ EditButton ( )
313+ } else {
314+ self . addMenu
320315 }
321316 }
322317 ToolbarItem ( placement: . topBarTrailing) {
323- EditButton ( )
318+ if #available( iOS 26 , * ) {
319+ self . addMenu
320+ } else {
321+ EditButton ( )
322+ }
324323 }
325324 ToolbarItem ( placement: . status) {
326- VStack ( spacing: 0 ) {
327- HStack {
328- Circle ( )
329- . frame ( width: 10 , height: 10 )
330- . foregroundStyle ( self . isEnabled ? . green : . secondary)
331- Text ( self . isEnabled ? " Active " : " Inactive " )
332- }
333- if !self . isEnabled {
334- Button ( " How to Activate " , systemImage: " questionmark.circle " ) {
335- self . isGuidePresented = true
336- }
337- . labelStyle ( . titleAndIcon)
338- . font ( . caption)
339- . sheet ( isPresented: self . $isGuidePresented) {
340- NavigationView {
341- HowToActivateView ( )
342- . safeAreaInset ( edge: . bottom) {
343- Button ( " Dismiss " ) {
344- self . isGuidePresented = false
345- }
346- . buttonStyle ( . borderedProminent)
347- . controlSize ( . large)
348- . hoverEffect ( )
349- . padding ( )
350- . frame ( maxWidth: . infinity)
351- . background ( Color ( . systemBackground) )
352- }
353- }
354- . navigationViewStyle ( . stack)
355- }
356- }
325+ if #available( iOS 26 , * ) {
326+ } else {
327+ self . statusIndicator
357328 }
358329 }
359330 }
360331
332+ private var addMenu : some View {
333+ Menu ( " Add " , systemImage: " plus " ) {
334+ Button ( " DNS-over-TLS " , action: self . addNewDoTServer)
335+ Button ( " DNS-over-HTTPS " , action: self . addNewDoHServer)
336+ Button ( " Restore from Presets " ) {
337+ self . isRestoring = true
338+ }
339+ }
340+ . sheet ( isPresented: self . $isRestoring) {
341+ RestorationView ( onAdd: self . restoreFromPresets)
342+ }
343+ }
344+
345+ private var statusIndicator : some View {
346+ Label {
347+ Text ( self . isActivated ? " Active " : " Inactive " )
348+ } icon: {
349+ Circle ( )
350+ . fill ( self . isActivated ? . green : . secondary)
351+ . frame ( width: 10 , height: 10 )
352+ }
353+ . labelStyle ( . titleAndIcon)
354+ }
355+
361356 private func sidebarRow( at i: Int ) -> some View {
362357 HStack {
363358 VStack ( alignment: . leading) {
@@ -367,6 +362,10 @@ extension ContentView: View {
367362 }
368363 if self . usedID == self . servers [ i] . id. uuidString {
369364 Spacer ( )
365+ if !self . isActivated {
366+ Image ( systemName: " exclamationmark.triangle " )
367+ . foregroundStyle ( . red)
368+ }
370369 Image ( systemName: " checkmark " )
371370 }
372371 }
@@ -375,7 +374,7 @@ extension ContentView: View {
375374 private func detailView( at i: Int ) -> some View {
376375 DetailView (
377376 server: self . $servers [ i] ,
378- isOn : . init(
377+ isSelected : . init(
379378 get: {
380379 self . usedID == self . servers [ i] . id. uuidString
381380 } ,
@@ -386,7 +385,8 @@ extension ContentView: View {
386385 self . removeSettings ( )
387386 }
388387 }
389- )
388+ ) ,
389+ isActivated: self . $isActivated
390390 )
391391 }
392392}
0 commit comments