@@ -13,34 +13,79 @@ struct DetailView: View {
1313 let url : String
1414 let animated : Bool
1515 @State var isAnimating : Bool = true
16+ @State var lastScaleValue : CGFloat = 1.0
17+ @State var scale : CGFloat = 1.0
18+ @Environment ( \. presentationMode) var presentationMode
1619
1720 var body : some View {
1821 VStack {
1922 #if os(iOS) || os(tvOS)
2023 if animated {
21- contentView ( )
24+ zoomView ( )
2225 . navigationBarItems ( trailing: Button ( isAnimating ? " Stop " : " Start " ) {
2326 self . isAnimating. toggle ( )
2427 } )
2528 } else {
26- contentView ( )
29+ zoomView ( )
2730 }
2831 #endif
2932 #if os(macOS) || os(watchOS)
3033 if animated {
31- contentView ( )
34+ zoomView ( )
3235 . contextMenu {
3336 Button ( isAnimating ? " Stop " : " Start " ) {
3437 self . isAnimating. toggle ( )
3538 }
3639 }
3740 } else {
38- contentView ( )
41+ zoomView ( )
3942 }
4043 #endif
4144 }
4245 }
4346
47+ func zoomView( ) -> some View {
48+ #if os(macOS) || os(iOS)
49+ return contentView ( )
50+ . scaleEffect ( self . scale)
51+ . gesture ( MagnificationGesture ( minimumScaleDelta: 0.1 ) . onChanged { value in
52+ let delta = value / self . lastScaleValue
53+ self . lastScaleValue = value
54+ let newScale = self . scale * delta
55+ self . scale = min ( max ( newScale, 0.5 ) , 2 )
56+ } . onEnded { value in
57+ self . lastScaleValue = 1.0
58+ } )
59+ #endif
60+ #if os(tvOS)
61+ return contentView ( )
62+ . scaleEffect ( self . scale)
63+ . focusable ( true )
64+ . onPlayPauseCommand {
65+ switch self . scale {
66+ case 1 :
67+ self . scale = 2
68+ case 2 :
69+ self . scale = 1
70+ default : break
71+ }
72+ }
73+ #endif
74+ #if os(watchOS)
75+ return contentView ( )
76+ // SwiftUI's bug workaround (watchOS 6.1)
77+ // If use `.focusable(true)` here, after pop the Detail view, the Content view's List does not get focus again
78+ // After some debug, I found that the pipeline to change focus becomes:
79+ // Detail Pop (resign focus) -> Content Appear (List view become focus) -> Detail Disappear (become focus again) -> End
80+ // Even you use `onDisappear`, it's too late because `.focusable` is called firstly
81+ // Sadly, Content view's List focus is managed by SwiftUI (a UICollectionView actually), call `focusable` on Content view does nothing as well
82+ // So, here we must use environment or binding, to not become focus during pop :)
83+ . focusable ( self . presentationMode. wrappedValue. isPresented)
84+ . scaleEffect ( self . scale)
85+ . digitalCrownRotation ( $scale, from: 0.5 , through: 2 , by: 0.1 , sensitivity: . low, isHapticFeedbackEnabled: false )
86+ #endif
87+ }
88+
4489 func contentView( ) -> some View {
4590 HStack {
4691 if animated {
0 commit comments