1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.jetpackcamera.settings
17 
18 import com.google.jetpackcamera.settings.DisabledRationale.DeviceUnsupportedRationale
19 import com.google.jetpackcamera.settings.DisabledRationale.LensUnsupportedRationale
20 import com.google.jetpackcamera.settings.model.AspectRatio
21 import com.google.jetpackcamera.settings.model.CaptureMode
22 import com.google.jetpackcamera.settings.model.DEFAULT_CAMERA_APP_SETTINGS
23 import com.google.jetpackcamera.settings.model.DarkMode
24 import com.google.jetpackcamera.settings.model.FlashMode
25 import com.google.jetpackcamera.settings.model.LensFacing
26 import com.google.jetpackcamera.settings.model.Stabilization
27 import com.google.jetpackcamera.settings.ui.DEVICE_UNSUPPORTED_TAG
28 import com.google.jetpackcamera.settings.ui.FPS_UNSUPPORTED_TAG
29 import com.google.jetpackcamera.settings.ui.LENS_UNSUPPORTED_TAG
30 import com.google.jetpackcamera.settings.ui.STABILIZATION_UNSUPPORTED_TAG
31 
32 /**
33  * Defines the current state of the [SettingsScreen].
34  */
35 sealed interface SettingsUiState {
36     data object Disabled : SettingsUiState
37     data class Enabled(
38         val aspectRatioUiState: AspectRatioUiState,
39         val captureModeUiState: CaptureModeUiState,
40         val darkModeUiState: DarkModeUiState,
41         val flashUiState: FlashUiState,
42         val fpsUiState: FpsUiState,
43         val lensFlipUiState: FlipLensUiState,
44         val stabilizationUiState: StabilizationUiState
45     ) : SettingsUiState
46 }
47 
48 /** State for the individual options on Popup dialog settings */
49 sealed interface SingleSelectableState {
50     data object Selectable : SingleSelectableState
51     data class Disabled(val disabledRationale: DisabledRationale) : SingleSelectableState
52 }
53 
54 /** Contains information on why a setting is disabled */
55 // TODO(b/360921588): Display information on UI regarding disabled rationale
56 sealed interface DisabledRationale {
57     val affectedSettingNameResId: Int
58     val reasonTextResId: Int
59     val testTag: String
60 
61     /**
62      * Text will be [affectedSettingNameResId] is [R.string.device_unsupported]
63      */
64     data class DeviceUnsupportedRationale(override val affectedSettingNameResId: Int) :
65         DisabledRationale {
66         override val reasonTextResId: Int = R.string.device_unsupported
67         override val testTag = DEVICE_UNSUPPORTED_TAG
68     }
69 
70     data class FpsUnsupportedRationale(
71         override val affectedSettingNameResId: Int,
72         val currentFps: Int
73     ) : DisabledRationale {
74         override val reasonTextResId: Int = R.string.fps_unsupported
75         override val testTag = FPS_UNSUPPORTED_TAG
76     }
77 
78     data class StabilizationUnsupportedRationale(override val affectedSettingNameResId: Int) :
79         DisabledRationale {
80         override val reasonTextResId = R.string.stabilization_unsupported
81         override val testTag = STABILIZATION_UNSUPPORTED_TAG
82     }
83 
84     sealed interface LensUnsupportedRationale : DisabledRationale {
85         data class FrontLensUnsupportedRationale(override val affectedSettingNameResId: Int) :
86             LensUnsupportedRationale {
87             override val reasonTextResId: Int = R.string.front_lens_unsupported
88             override val testTag = LENS_UNSUPPORTED_TAG
89         }
90 
91         data class RearLensUnsupportedRationale(override val affectedSettingNameResId: Int) :
92             LensUnsupportedRationale {
93             override val reasonTextResId: Int = R.string.rear_lens_unsupported
94             override val testTag = LENS_UNSUPPORTED_TAG
95         }
96     }
97 }
98 
getLensUnsupportedRationalenull99 fun getLensUnsupportedRationale(
100     lensFacing: LensFacing,
101     affectedSettingNameResId: Int
102 ): LensUnsupportedRationale {
103     return when (lensFacing) {
104         LensFacing.BACK -> LensUnsupportedRationale.RearLensUnsupportedRationale(
105             affectedSettingNameResId
106         )
107 
108         LensFacing.FRONT -> LensUnsupportedRationale.FrontLensUnsupportedRationale(
109             affectedSettingNameResId
110         )
111     }
112 }
113 
114 /* Settings that currently have constraints **/
115 
116 sealed interface FpsUiState {
117     data class Enabled(
118         val currentSelection: Int,
119         val fpsAutoState: SingleSelectableState,
120         val fpsFifteenState: SingleSelectableState,
121         val fpsThirtyState: SingleSelectableState,
122         val fpsSixtyState: SingleSelectableState,
123         // Contains text like "Selected FPS only supported by rear lens"
124         val additionalContext: String = ""
125     ) : FpsUiState
126 
127     // FPS selection completely disabled. Cannot open dialog.
128     data class Disabled(val disabledRationale: DisabledRationale) : FpsUiState
129 }
130 
131 sealed interface FlipLensUiState {
132     val currentLensFacing: LensFacing
133 
134     data class Enabled(
135         override val currentLensFacing: LensFacing
136     ) : FlipLensUiState
137 
138     data class Disabled(
139         override val currentLensFacing: LensFacing,
140         val disabledRationale: DisabledRationale
141     ) : FlipLensUiState
142 }
143 
144 sealed interface StabilizationUiState {
145     data class Enabled(
146         val currentPreviewStabilization: Stabilization,
147         val currentVideoStabilization: Stabilization,
148         val stabilizationOnState: SingleSelectableState,
149         val stabilizationHighQualityState: SingleSelectableState,
150         // Contains text like "Selected stabilization mode only supported by rear lens"
151         val additionalContext: String = ""
152     ) : StabilizationUiState
153 
154     // Stabilization selection completely disabled. Cannot open dialog.
155     data class Disabled(val disabledRationale: DisabledRationale) : StabilizationUiState
156 }
157 
158 /* Settings that don't currently depend on constraints */
159 
160 // this could be constrained w/ a check to see if a torch is available?
161 sealed interface FlashUiState {
162     data class Enabled(
163         val currentFlashMode: FlashMode,
164         val additionalContext: String = ""
165     ) : FlashUiState
166 }
167 
168 sealed interface AspectRatioUiState {
169     data class Enabled(
170         val currentAspectRatio: AspectRatio,
171         val additionalContext: String = ""
172     ) : AspectRatioUiState
173 }
174 
175 sealed interface CaptureModeUiState {
176     data class Enabled(
177         val currentCaptureMode: CaptureMode,
178         val additionalContext: String = ""
179     ) : CaptureModeUiState
180 }
181 
182 sealed interface DarkModeUiState {
183     data class Enabled(
184         val currentDarkMode: DarkMode,
185         val additionalContext: String = ""
186     ) : DarkModeUiState
187 }
188 
189 /**
190  * Settings Ui State for testing, based on Typical System Constraints.
191  * @see[com.google.jetpackcamera.settings.model.SystemConstraints]
192  */
193 val TYPICAL_SETTINGS_UISTATE = SettingsUiState.Enabled(
194     aspectRatioUiState = AspectRatioUiState.Enabled(DEFAULT_CAMERA_APP_SETTINGS.aspectRatio),
195     captureModeUiState = CaptureModeUiState.Enabled(DEFAULT_CAMERA_APP_SETTINGS.captureMode),
196     darkModeUiState = DarkModeUiState.Enabled(DEFAULT_CAMERA_APP_SETTINGS.darkMode),
197     flashUiState =
198     FlashUiState.Enabled(currentFlashMode = DEFAULT_CAMERA_APP_SETTINGS.flashMode),
199     fpsUiState = FpsUiState.Enabled(
200         currentSelection = DEFAULT_CAMERA_APP_SETTINGS.targetFrameRate,
201         fpsAutoState = SingleSelectableState.Selectable,
202         fpsFifteenState = SingleSelectableState.Selectable,
203         fpsThirtyState = SingleSelectableState.Selectable,
204         fpsSixtyState = SingleSelectableState.Disabled(
205             DeviceUnsupportedRationale(R.string.fps_rationale_prefix)
206         )
207     ),
208     lensFlipUiState = FlipLensUiState.Enabled(DEFAULT_CAMERA_APP_SETTINGS.cameraLensFacing),
209     stabilizationUiState =
210     StabilizationUiState.Disabled(
211         DeviceUnsupportedRationale(R.string.stabilization_rationale_prefix)
212     )
213 )
214