@@ -13,34 +13,79 @@ struct DetailView: View {
13
13
let url : String
14
14
let animated : Bool
15
15
@State var isAnimating : Bool = true
16
+ @State var lastScaleValue : CGFloat = 1.0
17
+ @State var scale : CGFloat = 1.0
18
+ @Environment ( \. presentationMode) var presentationMode
16
19
17
20
var body : some View {
18
21
VStack {
19
22
#if os(iOS) || os(tvOS)
20
23
if animated {
21
- contentView ( )
24
+ zoomView ( )
22
25
. navigationBarItems ( trailing: Button ( isAnimating ? " Stop " : " Start " ) {
23
26
self . isAnimating. toggle ( )
24
27
} )
25
28
} else {
26
- contentView ( )
29
+ zoomView ( )
27
30
}
28
31
#endif
29
32
#if os(macOS) || os(watchOS)
30
33
if animated {
31
- contentView ( )
34
+ zoomView ( )
32
35
. contextMenu {
33
36
Button ( isAnimating ? " Stop " : " Start " ) {
34
37
self . isAnimating. toggle ( )
35
38
}
36
39
}
37
40
} else {
38
- contentView ( )
41
+ zoomView ( )
39
42
}
40
43
#endif
41
44
}
42
45
}
43
46
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
+
44
89
func contentView( ) -> some View {
45
90
HStack {
46
91
if animated {
0 commit comments