2323// SOFTWARE.
2424//
2525
26- struct Menu {
27- let infoList : InfoList
28- private( set) var child : Child
26+ import Foundation
2927
30- enum Child {
28+ struct Menu : Component {
29+ private let infoList : InfoList
30+ private var child : Child
31+
32+ private enum Child {
3133 case none
3234 case info( Info )
3335 case displayOptions( DisplayOptions )
@@ -54,6 +56,8 @@ struct Menu {
5456 child = . info( info)
5557 }
5658
59+ // MARK: View
60+
5761 func viewModel( digitGroupSize: Int ) -> ViewModel {
5862 return ViewModel ( infoList: infoList. viewModel, child: child. viewModel ( digitGroupSize: digitGroupSize) )
5963 }
@@ -69,34 +73,123 @@ struct Menu {
6973 }
7074 }
7175
76+ // MARK: Update
77+
78+ enum Action {
79+ case dismissInfo
80+ case dismissDisplayOptions
81+
82+ case infoListEffect( InfoList . Effect )
83+ case infoEffect( Info . Effect )
84+ case displayOptionsEffect( DisplayOptions . Effect )
85+ }
86+
87+ enum Effect {
88+ case dismissMenu
89+ case showErrorMessage( String )
90+ case showSuccessMessage( String )
91+ case openURL( URL )
92+ case setDigitGroupSize( Int )
93+ }
94+
95+ mutating func update( with action: Action ) throws -> Effect ? {
96+ switch action {
97+ case . dismissInfo:
98+ try dismissInfo ( )
99+ return nil
100+
101+ case . dismissDisplayOptions:
102+ try dismissDisplayOptions ( )
103+ return nil
104+
105+ case . infoListEffect( let effect) :
106+ return try handleInfoListEffect ( effect)
107+
108+ case . infoEffect( let effect) :
109+ return handleInfoEffect ( effect)
110+
111+ case . displayOptionsEffect( let effect) :
112+ return handleDisplayOptionsEffect ( effect)
113+ }
114+ }
115+
116+ private mutating func handleInfoListEffect( _ effect: InfoList . Effect ) throws -> Effect ? {
117+ switch effect {
118+ case . showDisplayOptions:
119+ try showDisplayOptions ( )
120+ return nil
121+
122+ case . showBackupInfo:
123+ let backupInfo : Info
124+ do {
125+ backupInfo = try Info . backupInfo ( )
126+ } catch {
127+ return . showErrorMessage( " Failed to load backup info. " )
128+ }
129+ try showInfo ( backupInfo)
130+ return nil
131+
132+ case . showLicenseInfo:
133+ let licenseInfo : Info
134+ do {
135+ licenseInfo = try Info . licenseInfo ( )
136+ } catch {
137+ return . showErrorMessage( " Failed to load acknowledgements. " )
138+ }
139+ try showInfo ( licenseInfo)
140+ return nil
141+
142+ case . done:
143+ return . dismissMenu
144+ }
145+ }
146+
147+ private mutating func handleInfoEffect( _ effect: Info . Effect ) -> Effect ? {
148+ switch effect {
149+ case . done:
150+ return . dismissMenu
151+ case let . openURL( url) :
152+ return . openURL( url)
153+ }
154+ }
155+
156+ private mutating func handleDisplayOptionsEffect( _ effect: DisplayOptions . Effect ) -> Effect ? {
157+ switch effect {
158+ case . done:
159+ return . dismissMenu
160+ case let . setDigitGroupSize( digitGroupSize) :
161+ return . setDigitGroupSize( digitGroupSize)
162+ }
163+ }
164+
72165 // MARK: -
73166
74- enum Error : Swift . Error {
167+ private enum Error : Swift . Error {
75168 case badChildState
76169 }
77170
78- mutating func showInfo( _ info: Info ) throws {
171+ private mutating func showInfo( _ info: Info ) throws {
79172 guard case . none = child else {
80173 throw Error . badChildState
81174 }
82175 child = . info( info)
83176 }
84177
85- mutating func dismissInfo( ) throws {
178+ private mutating func dismissInfo( ) throws {
86179 guard case . info = child else {
87180 throw Error . badChildState
88181 }
89182 child = . none
90183 }
91184
92- mutating func showDisplayOptions( ) throws {
185+ private mutating func showDisplayOptions( ) throws {
93186 guard case . none = child else {
94187 throw Error . badChildState
95188 }
96189 child = . displayOptions( DisplayOptions ( ) )
97190 }
98191
99- mutating func dismissDisplayOptions( ) throws {
192+ private mutating func dismissDisplayOptions( ) throws {
100193 guard case . displayOptions = child else {
101194 throw Error . badChildState
102195 }
0 commit comments