kasy-cli 1.10.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/kasy.js +25 -4
- package/lib/commands/check.js +40 -50
- package/lib/commands/deploy.js +25 -25
- package/lib/commands/splash.js +220 -0
- package/lib/scaffold/CHANGELOG.json +9 -0
- package/lib/scaffold/backends/api/patch/lib/main.dart +29 -10
- package/lib/scaffold/backends/supabase/patch/lib/main.dart +29 -10
- package/lib/scaffold/features/README.md +15 -139
- package/lib/scaffold/shared/generator-utils.js +16 -15
- package/lib/utils/i18n.js +292 -43
- package/package.json +2 -2
- package/templates/firebase/android/app/src/main/res/drawable-hdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-hdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-mdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-mdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night/background.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night/launch_background.xml +9 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-v21/background.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-v21/launch_background.xml +9 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/values-night-v31/styles.xml +2 -1
- package/templates/firebase/android/app/src/main/res/values-v31/styles.xml +1 -0
- package/templates/firebase/assets/images/splash_logo_dark.png +0 -0
- package/templates/firebase/assets/images/splash_logo_light.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json +9 -8
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +33 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png +0 -0
- package/templates/firebase/ios/Runner/Base.lproj/LaunchScreen.storyboard +1 -1
- package/templates/firebase/lib/core/initializer/onstart_widget.dart +7 -1
- package/templates/firebase/lib/core/theme/providers/theme_provider.dart +48 -24
- package/templates/firebase/lib/features/onboarding/ui/components/onboarding_features.dart +4 -0
- package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +1 -0
- package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_feature.dart +13 -0
- package/templates/firebase/lib/features/settings/settings_page.dart +158 -18
- package/templates/firebase/lib/i18n/en.i18n.json +6 -2
- package/templates/firebase/lib/i18n/es.i18n.json +6 -2
- package/templates/firebase/lib/i18n/pt.i18n.json +6 -2
- package/templates/firebase/lib/main.dart +29 -10
- package/templates/firebase/pubspec.yaml +4 -5
- package/templates/firebase/test/core/data/repositories/user_repository_test.dart +1 -1
- package/templates/firebase/web/index.html +47 -39
- package/templates/firebase/web/splash/img/dark-1x.png +0 -0
- package/templates/firebase/web/splash/img/dark-2x.png +0 -0
- package/templates/firebase/web/splash/img/dark-3x.png +0 -0
- package/templates/firebase/web/splash/img/dark-4x.png +0 -0
- package/templates/firebase/web/splash/img/light-1x.png +0 -0
- package/templates/firebase/web/splash/img/light-2x.png +0 -0
- package/templates/firebase/web/splash/img/light-3x.png +0 -0
- package/templates/firebase/web/splash/img/light-4x.png +0 -0
- package/lib/scaffold/features/analytics/lib/core/data/api/analytics_api.dart +0 -124
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.es.md +0 -35
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.md +0 -35
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.pt.md +0 -35
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.es.md +0 -12
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.md +0 -12
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.pt.md +0 -12
- package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.es.md +0 -17
- package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.md +0 -17
- package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.pt.md +0 -17
- package/lib/scaffold/features/ci/.github/dependabot.yml +0 -16
- package/lib/scaffold/features/ci/.github/workflows/app.yml +0 -20
- package/lib/scaffold/features/ci/.gitlab/templates/deploy.yaml +0 -14
- package/lib/scaffold/features/ci/.gitlab/templates/dropbox.yaml +0 -19
- package/lib/scaffold/features/ci/.gitlab/templates/flutter.yaml +0 -163
- package/lib/scaffold/features/ci/.gitlab/templates/mailgun.yaml +0 -28
- package/lib/scaffold/features/ci/.gitlab-ci.yml +0 -37
- package/lib/scaffold/features/ci/codemagic.yaml +0 -157
- package/lib/scaffold/features/facebook/lib/core/data/api/tracking_api.dart +0 -111
- package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_request_entity.dart +0 -27
- package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_vote_entity.dart +0 -27
- package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_request_api.dart +0 -50
- package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_vote_api.dart +0 -79
- package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feature_requests.dart +0 -48
- package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feedback_state.dart +0 -42
- package/lib/scaffold/features/feedback/lib/features/feedbacks/providers/feedback_page_notifier.dart +0 -147
- package/lib/scaffold/features/feedback/lib/features/feedbacks/repositories/feature_request_repository.dart +0 -95
- package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/component/add_feature_form.dart +0 -199
- package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/feedback_page.dart +0 -175
- package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/add_feature_button.dart +0 -76
- package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/feature_card.dart +0 -279
- package/lib/scaffold/features/ios-release/.kasy/apple.env.example +0 -8
- package/lib/scaffold/features/ios-release/.kasy/codemagic.env.example +0 -7
- package/lib/scaffold/features/ios-release/docs/codemagic-release.en.md +0 -50
- package/lib/scaffold/features/ios-release/docs/codemagic-release.es.md +0 -50
- package/lib/scaffold/features/ios-release/docs/codemagic-release.pt.md +0 -50
- package/lib/scaffold/features/ios-release/docs/ios-release.en.md +0 -41
- package/lib/scaffold/features/ios-release/docs/ios-release.es.md +0 -41
- package/lib/scaffold/features/ios-release/docs/ios-release.pt.md +0 -41
- package/lib/scaffold/features/ios-release/scripts/bump-ios-version.js +0 -38
- package/lib/scaffold/features/ios-release/scripts/release-ios.sh +0 -137
- package/lib/scaffold/features/llm_chat/lib/features/llm_chat/llm_chat_page.dart +0 -301
- package/lib/scaffold/features/local_notifications/lib/features/local_reminder/providers/reminder_notifier.dart +0 -81
- package/lib/scaffold/features/local_notifications/lib/features/local_reminder/repositories/reminder_preferences.dart +0 -76
- package/lib/scaffold/features/local_notifications/lib/features/local_reminder/ui/reminder_page.dart +0 -282
- package/lib/scaffold/features/onboarding/lib/features/onboarding/api/entities/user_info_entity.dart +0 -24
- package/lib/scaffold/features/onboarding/lib/features/onboarding/api/user_infos_api.dart +0 -71
- package/lib/scaffold/features/onboarding/lib/features/onboarding/models/user_info.dart +0 -92
- package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_model.dart +0 -15
- package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_provider.dart +0 -78
- package/lib/scaffold/features/onboarding/lib/features/onboarding/repositories/user_infos_repository.dart +0 -29
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/animations/page_transitions.dart +0 -30
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_att_setup.dart +0 -66
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_features.dart +0 -72
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_loader.dart +0 -92
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_notifications_setup.dart +0 -73
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_questions.dart +0 -89
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/onboarding_page.dart +0 -94
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_background.dart +0 -80
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_feature.dart +0 -139
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +0 -110
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_progress.dart +0 -84
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +0 -173
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_reassurance.dart +0 -45
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_sticky_footer.dart +0 -77
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +0 -392
- package/lib/scaffold/features/revenuecat/lib/core/data/api/tracking_api.dart +0 -116
- package/lib/scaffold/features/revenuecat/lib/core/data/models/subscription.dart +0 -322
- package/lib/scaffold/features/revenuecat/lib/core/home_widgets/home_widget_background_task.dart +0 -41
- package/lib/scaffold/features/revenuecat/lib/core/states/user_state_notifier.dart +0 -305
- package/templates/firebase/assets/images/splashscreen.png +0 -0
package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json
CHANGED
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
"images" : [
|
|
3
3
|
{
|
|
4
4
|
"filename" : "background.png",
|
|
5
|
-
"idiom" : "universal"
|
|
6
|
-
"scale" : "1x"
|
|
5
|
+
"idiom" : "universal"
|
|
7
6
|
},
|
|
8
7
|
{
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
"appearances" : [
|
|
9
|
+
{
|
|
10
|
+
"appearance" : "luminosity",
|
|
11
|
+
"value" : "dark"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"filename" : "darkbackground.png",
|
|
15
|
+
"idiom" : "universal"
|
|
15
16
|
}
|
|
16
17
|
],
|
|
17
18
|
"info" : {
|
package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png
ADDED
|
Binary file
|
|
@@ -5,15 +5,48 @@
|
|
|
5
5
|
"idiom" : "universal",
|
|
6
6
|
"scale" : "1x"
|
|
7
7
|
},
|
|
8
|
+
{
|
|
9
|
+
"appearances" : [
|
|
10
|
+
{
|
|
11
|
+
"appearance" : "luminosity",
|
|
12
|
+
"value" : "dark"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"filename" : "LaunchImageDark.png",
|
|
16
|
+
"idiom" : "universal",
|
|
17
|
+
"scale" : "1x"
|
|
18
|
+
},
|
|
8
19
|
{
|
|
9
20
|
"filename" : "LaunchImage@2x.png",
|
|
10
21
|
"idiom" : "universal",
|
|
11
22
|
"scale" : "2x"
|
|
12
23
|
},
|
|
24
|
+
{
|
|
25
|
+
"appearances" : [
|
|
26
|
+
{
|
|
27
|
+
"appearance" : "luminosity",
|
|
28
|
+
"value" : "dark"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"filename" : "LaunchImageDark@2x.png",
|
|
32
|
+
"idiom" : "universal",
|
|
33
|
+
"scale" : "2x"
|
|
34
|
+
},
|
|
13
35
|
{
|
|
14
36
|
"filename" : "LaunchImage@3x.png",
|
|
15
37
|
"idiom" : "universal",
|
|
16
38
|
"scale" : "3x"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"appearances" : [
|
|
42
|
+
{
|
|
43
|
+
"appearance" : "luminosity",
|
|
44
|
+
"value" : "dark"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"filename" : "LaunchImageDark@3x.png",
|
|
48
|
+
"idiom" : "universal",
|
|
49
|
+
"scale" : "3x"
|
|
17
50
|
}
|
|
18
51
|
],
|
|
19
52
|
"info" : {
|
|
Binary file
|
package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
CHANGED
|
Binary file
|
package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
CHANGED
|
Binary file
|
package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png
ADDED
|
Binary file
|
package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png
ADDED
|
Binary file
|
package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png
ADDED
|
Binary file
|
|
@@ -64,7 +64,13 @@ class _InitializerState extends ConsumerState<Initializer> {
|
|
|
64
64
|
Sentry.captureException(e, stackTrace: s);
|
|
65
65
|
ref.read(onStartProvider.notifier).notifyError(e.toString());
|
|
66
66
|
} finally {
|
|
67
|
-
|
|
67
|
+
// Defer splash removal until after the next frame is painted so the
|
|
68
|
+
// onReady widget renders under the splash before it disappears.
|
|
69
|
+
// Without this, the splash is removed before the new frame paints,
|
|
70
|
+
// briefly revealing the onLoading widget (visible flash).
|
|
71
|
+
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
72
|
+
FlutterNativeSplash.remove();
|
|
73
|
+
});
|
|
68
74
|
}
|
|
69
75
|
});
|
|
70
76
|
}
|
|
@@ -17,13 +17,8 @@ class ThemeProvider extends InheritedNotifier<AppTheme> {
|
|
|
17
17
|
|
|
18
18
|
@override
|
|
19
19
|
bool updateShouldNotify(covariant InheritedNotifier<AppTheme> oldWidget) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// keeep the same theme when switching between light and dark mode while hot reloading
|
|
23
|
-
notifier!.mode = oldWidget.notifier!.mode;
|
|
24
|
-
notifier!.setSystemBarColor();
|
|
25
|
-
}
|
|
26
|
-
return false;
|
|
20
|
+
return oldWidget.notifier != notifier ||
|
|
21
|
+
oldWidget.notifier?.mode != notifier?.mode;
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
static AppTheme of(BuildContext context) =>
|
|
@@ -37,7 +32,7 @@ class ThemeProvider extends InheritedNotifier<AppTheme> {
|
|
|
37
32
|
///
|
|
38
33
|
/// Defining a theme for light and dark should only change the colors
|
|
39
34
|
/// not redefining everything. (see ./docs/theme.md)
|
|
40
|
-
class AppTheme with ChangeNotifier {
|
|
35
|
+
class AppTheme with ChangeNotifier, WidgetsBindingObserver {
|
|
41
36
|
final KasyTheme? lightTheme;
|
|
42
37
|
final KasyTheme? darkTheme;
|
|
43
38
|
final SharedPreferences sharedPreferences;
|
|
@@ -50,6 +45,7 @@ class AppTheme with ChangeNotifier {
|
|
|
50
45
|
this.darkTheme,
|
|
51
46
|
}) {
|
|
52
47
|
mode = _loadFromPrefs();
|
|
48
|
+
WidgetsBinding.instance.addObserver(this);
|
|
53
49
|
setSystemBarColor();
|
|
54
50
|
}
|
|
55
51
|
|
|
@@ -135,25 +131,55 @@ class AppTheme with ChangeNotifier {
|
|
|
135
131
|
);
|
|
136
132
|
}
|
|
137
133
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
134
|
+
@override
|
|
135
|
+
void didChangePlatformBrightness() {
|
|
136
|
+
super.didChangePlatformBrightness();
|
|
137
|
+
if (mode == ThemeMode.system) {
|
|
138
|
+
setSystemBarColor();
|
|
139
|
+
notifyListeners();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@override
|
|
144
|
+
void dispose() {
|
|
145
|
+
WidgetsBinding.instance.removeObserver(this);
|
|
146
|
+
super.dispose();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/// Resolves [mode] to either light or dark by reading the system brightness
|
|
150
|
+
/// when [mode] is [ThemeMode.system].
|
|
151
|
+
ThemeMode get effectiveMode {
|
|
152
|
+
if (mode != ThemeMode.system) return mode;
|
|
153
|
+
final brightness =
|
|
154
|
+
WidgetsBinding.instance.platformDispatcher.platformBrightness;
|
|
155
|
+
return brightness == Brightness.dark ? ThemeMode.dark : ThemeMode.light;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/// Set the theme mode and persist the preference.
|
|
159
|
+
void setMode(ThemeMode newMode) {
|
|
160
|
+
if (mode == newMode) return;
|
|
161
|
+
mode = newMode;
|
|
142
162
|
_saveInPrefs(mode);
|
|
143
|
-
notifyListeners();
|
|
144
163
|
setSystemBarColor();
|
|
164
|
+
notifyListeners();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/// Toggle between light and dark based on the effective (visible) mode.
|
|
168
|
+
/// If the user is in system mode, this picks the opposite of the
|
|
169
|
+
/// currently displayed brightness and switches out of system mode.
|
|
170
|
+
void toggle() {
|
|
171
|
+
final next =
|
|
172
|
+
effectiveMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light;
|
|
173
|
+
setMode(next);
|
|
145
174
|
}
|
|
146
175
|
|
|
147
176
|
void setSystemBarColor() {
|
|
177
|
+
final isLight = effectiveMode == ThemeMode.light;
|
|
148
178
|
SystemChrome.setSystemUIOverlayStyle(
|
|
149
179
|
SystemUiOverlayStyle(
|
|
150
180
|
statusBarColor: Colors.transparent,
|
|
151
|
-
statusBarBrightness:
|
|
152
|
-
|
|
153
|
-
statusBarIconBrightness:
|
|
154
|
-
mode == ThemeMode.light ? Brightness.dark : Brightness.light,
|
|
155
|
-
// statusBarColor: Colors.black, // color for android
|
|
156
|
-
// statusBarBrightness: Brightness.light, // for ios Dark = white status
|
|
181
|
+
statusBarBrightness: isLight ? Brightness.light : Brightness.dark,
|
|
182
|
+
statusBarIconBrightness: isLight ? Brightness.dark : Brightness.light,
|
|
157
183
|
),
|
|
158
184
|
);
|
|
159
185
|
}
|
|
@@ -189,11 +215,7 @@ class AppTheme with ChangeNotifier {
|
|
|
189
215
|
ThemeData get darkThemeData => darkTheme!.data.materialTheme;
|
|
190
216
|
|
|
191
217
|
KasyTheme get current {
|
|
192
|
-
|
|
193
|
-
return lightTheme!;
|
|
194
|
-
} else {
|
|
195
|
-
return darkTheme!;
|
|
196
|
-
}
|
|
218
|
+
return effectiveMode == ThemeMode.dark ? darkTheme! : lightTheme!;
|
|
197
219
|
}
|
|
198
220
|
|
|
199
221
|
ThemeMode _loadFromPrefs() {
|
|
@@ -202,6 +224,8 @@ class AppTheme with ChangeNotifier {
|
|
|
202
224
|
return ThemeMode.dark;
|
|
203
225
|
} else if (themeMode == ThemeMode.light.name) {
|
|
204
226
|
return ThemeMode.light;
|
|
227
|
+
} else if (themeMode == ThemeMode.system.name) {
|
|
228
|
+
return ThemeMode.system;
|
|
205
229
|
}
|
|
206
230
|
return mode;
|
|
207
231
|
}
|
|
@@ -5,11 +5,13 @@ import 'package:kasy_kit/i18n/translations.g.dart';
|
|
|
5
5
|
class OnboardingFeatureOne extends StatelessWidget {
|
|
6
6
|
final String nextRoute;
|
|
7
7
|
final VoidCallback? onSkip;
|
|
8
|
+
final VoidCallback? onLogin;
|
|
8
9
|
|
|
9
10
|
const OnboardingFeatureOne({
|
|
10
11
|
super.key,
|
|
11
12
|
required this.nextRoute,
|
|
12
13
|
this.onSkip,
|
|
14
|
+
this.onLogin,
|
|
13
15
|
});
|
|
14
16
|
|
|
15
17
|
@override
|
|
@@ -25,6 +27,8 @@ class OnboardingFeatureOne extends StatelessWidget {
|
|
|
25
27
|
progress: 0.1,
|
|
26
28
|
onSkip: onSkip,
|
|
27
29
|
skipLabel: translations.skip,
|
|
30
|
+
onSecondary: onLogin,
|
|
31
|
+
secondaryLabel: onLogin != null ? translations.login : null,
|
|
28
32
|
);
|
|
29
33
|
}
|
|
30
34
|
}
|
|
@@ -20,6 +20,8 @@ class OnboardingStep extends StatelessWidget {
|
|
|
20
20
|
final bool withBg;
|
|
21
21
|
final VoidCallback? onSkip;
|
|
22
22
|
final String? skipLabel;
|
|
23
|
+
final VoidCallback? onSecondary;
|
|
24
|
+
final String? secondaryLabel;
|
|
23
25
|
|
|
24
26
|
const OnboardingStep({
|
|
25
27
|
super.key,
|
|
@@ -35,6 +37,8 @@ class OnboardingStep extends StatelessWidget {
|
|
|
35
37
|
this.image,
|
|
36
38
|
this.onSkip,
|
|
37
39
|
this.skipLabel,
|
|
40
|
+
this.onSecondary,
|
|
41
|
+
this.secondaryLabel,
|
|
38
42
|
});
|
|
39
43
|
|
|
40
44
|
@override
|
|
@@ -128,6 +132,15 @@ class OnboardingStep extends StatelessWidget {
|
|
|
128
132
|
}
|
|
129
133
|
},
|
|
130
134
|
),
|
|
135
|
+
if (onSecondary != null && secondaryLabel != null) ...[
|
|
136
|
+
const SizedBox(height: KasySpacing.xs),
|
|
137
|
+
KasyButton(
|
|
138
|
+
label: secondaryLabel!,
|
|
139
|
+
variant: KasyButtonVariant.link,
|
|
140
|
+
expand: true,
|
|
141
|
+
onPressed: onSecondary,
|
|
142
|
+
),
|
|
143
|
+
],
|
|
131
144
|
],
|
|
132
145
|
);
|
|
133
146
|
|
|
@@ -426,35 +426,175 @@ class HapticFeedbackSwitcher extends ConsumerWidget {
|
|
|
426
426
|
}
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
-
class ThemeSwitcher extends
|
|
429
|
+
class ThemeSwitcher extends StatelessWidget {
|
|
430
430
|
const ThemeSwitcher({super.key});
|
|
431
431
|
|
|
432
|
+
IconData _iconFor(ThemeMode mode) {
|
|
433
|
+
switch (mode) {
|
|
434
|
+
case ThemeMode.system:
|
|
435
|
+
return KasyIcons.phoneAndroid;
|
|
436
|
+
case ThemeMode.dark:
|
|
437
|
+
return KasyIcons.darkMode;
|
|
438
|
+
case ThemeMode.light:
|
|
439
|
+
return KasyIcons.lightMode;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
432
443
|
@override
|
|
433
|
-
|
|
444
|
+
Widget build(BuildContext context) {
|
|
445
|
+
final tr = context.t.settings;
|
|
446
|
+
final theme = ThemeProvider.of(context);
|
|
447
|
+
final options = <({ThemeMode mode, IconData icon, String label})>[
|
|
448
|
+
(
|
|
449
|
+
mode: ThemeMode.system,
|
|
450
|
+
icon: KasyIcons.phoneAndroid,
|
|
451
|
+
label: tr.theme_option_system,
|
|
452
|
+
),
|
|
453
|
+
(
|
|
454
|
+
mode: ThemeMode.light,
|
|
455
|
+
icon: KasyIcons.lightMode,
|
|
456
|
+
label: tr.theme_option_light,
|
|
457
|
+
),
|
|
458
|
+
(
|
|
459
|
+
mode: ThemeMode.dark,
|
|
460
|
+
icon: KasyIcons.darkMode,
|
|
461
|
+
label: tr.theme_option_dark,
|
|
462
|
+
),
|
|
463
|
+
];
|
|
464
|
+
return Padding(
|
|
465
|
+
padding: const EdgeInsets.symmetric(vertical: KasySpacing.sm),
|
|
466
|
+
child: Column(
|
|
467
|
+
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
468
|
+
children: [
|
|
469
|
+
Row(
|
|
470
|
+
children: [
|
|
471
|
+
Icon(
|
|
472
|
+
_iconFor(theme.mode),
|
|
473
|
+
size: 21,
|
|
474
|
+
color: context.colors.onSurface,
|
|
475
|
+
),
|
|
476
|
+
const SizedBox(width: KasySpacing.sm),
|
|
477
|
+
Expanded(
|
|
478
|
+
child: Text(
|
|
479
|
+
tr.theme_title,
|
|
480
|
+
style: context.textTheme.titleMedium?.copyWith(
|
|
481
|
+
color: context.colors.onSurface,
|
|
482
|
+
),
|
|
483
|
+
),
|
|
484
|
+
),
|
|
485
|
+
],
|
|
486
|
+
),
|
|
487
|
+
const SizedBox(height: KasySpacing.sm),
|
|
488
|
+
_ThemeModeSegmented(
|
|
489
|
+
current: theme.mode,
|
|
490
|
+
options: options,
|
|
491
|
+
onChanged: theme.setMode,
|
|
492
|
+
),
|
|
493
|
+
],
|
|
494
|
+
),
|
|
495
|
+
);
|
|
496
|
+
}
|
|
434
497
|
}
|
|
435
498
|
|
|
436
|
-
class
|
|
437
|
-
|
|
499
|
+
class _ThemeModeSegmented extends StatelessWidget {
|
|
500
|
+
const _ThemeModeSegmented({
|
|
501
|
+
required this.current,
|
|
502
|
+
required this.options,
|
|
503
|
+
required this.onChanged,
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
final ThemeMode current;
|
|
507
|
+
final List<({ThemeMode mode, IconData icon, String label})> options;
|
|
508
|
+
final ValueChanged<ThemeMode> onChanged;
|
|
438
509
|
|
|
439
510
|
@override
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
511
|
+
Widget build(BuildContext context) {
|
|
512
|
+
final trackColor = context.colors.onSurface.withValues(alpha: 0.06);
|
|
513
|
+
return Container(
|
|
514
|
+
padding: const EdgeInsets.all(3),
|
|
515
|
+
decoration: BoxDecoration(
|
|
516
|
+
color: trackColor,
|
|
517
|
+
borderRadius: BorderRadius.circular(10),
|
|
518
|
+
),
|
|
519
|
+
child: Row(
|
|
520
|
+
children: [
|
|
521
|
+
for (final opt in options)
|
|
522
|
+
Expanded(
|
|
523
|
+
child: _ThemeModeSegment(
|
|
524
|
+
icon: opt.icon,
|
|
525
|
+
label: opt.label,
|
|
526
|
+
selected: current == opt.mode,
|
|
527
|
+
onTap: () => onChanged(opt.mode),
|
|
528
|
+
),
|
|
529
|
+
),
|
|
530
|
+
],
|
|
531
|
+
),
|
|
532
|
+
);
|
|
446
533
|
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
class _ThemeModeSegment extends StatelessWidget {
|
|
537
|
+
const _ThemeModeSegment({
|
|
538
|
+
required this.icon,
|
|
539
|
+
required this.label,
|
|
540
|
+
required this.selected,
|
|
541
|
+
required this.onTap,
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
final IconData icon;
|
|
545
|
+
final String label;
|
|
546
|
+
final bool selected;
|
|
547
|
+
final VoidCallback onTap;
|
|
447
548
|
|
|
448
549
|
@override
|
|
449
550
|
Widget build(BuildContext context) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
551
|
+
final selectedBg = context.colors.surface;
|
|
552
|
+
final selectedFg = context.colors.onSurface;
|
|
553
|
+
final unselectedFg = context.colors.muted;
|
|
554
|
+
return Semantics(
|
|
555
|
+
button: true,
|
|
556
|
+
selected: selected,
|
|
557
|
+
label: label,
|
|
558
|
+
child: GestureDetector(
|
|
559
|
+
onTap: onTap,
|
|
560
|
+
behavior: HitTestBehavior.opaque,
|
|
561
|
+
child: AnimatedContainer(
|
|
562
|
+
duration: const Duration(milliseconds: 160),
|
|
563
|
+
curve: Curves.easeOut,
|
|
564
|
+
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
565
|
+
decoration: BoxDecoration(
|
|
566
|
+
color: selected ? selectedBg : Colors.transparent,
|
|
567
|
+
borderRadius: BorderRadius.circular(8),
|
|
568
|
+
boxShadow: selected
|
|
569
|
+
? [
|
|
570
|
+
BoxShadow(
|
|
571
|
+
color: Colors.black.withValues(alpha: 0.06),
|
|
572
|
+
blurRadius: 4,
|
|
573
|
+
offset: const Offset(0, 1),
|
|
574
|
+
),
|
|
575
|
+
]
|
|
576
|
+
: const [],
|
|
577
|
+
),
|
|
578
|
+
child: Column(
|
|
579
|
+
mainAxisSize: MainAxisSize.min,
|
|
580
|
+
children: [
|
|
581
|
+
Icon(
|
|
582
|
+
icon,
|
|
583
|
+
size: 18,
|
|
584
|
+
color: selected ? selectedFg : unselectedFg,
|
|
585
|
+
),
|
|
586
|
+
const SizedBox(height: 2),
|
|
587
|
+
Text(
|
|
588
|
+
label,
|
|
589
|
+
style: context.textTheme.labelSmall?.copyWith(
|
|
590
|
+
color: selected ? selectedFg : unselectedFg,
|
|
591
|
+
fontWeight: selected ? FontWeight.w600 : FontWeight.w500,
|
|
592
|
+
),
|
|
593
|
+
),
|
|
594
|
+
],
|
|
595
|
+
),
|
|
596
|
+
),
|
|
597
|
+
),
|
|
458
598
|
);
|
|
459
599
|
}
|
|
460
600
|
}
|
|
@@ -175,7 +175,8 @@
|
|
|
175
175
|
"title": "Subscriptions module",
|
|
176
176
|
"description": "Manage subscriptions with premade paywalls",
|
|
177
177
|
"action": "Continue",
|
|
178
|
-
"skip": "Skip"
|
|
178
|
+
"skip": "Skip",
|
|
179
|
+
"login": "Already have an account? Log in"
|
|
179
180
|
},
|
|
180
181
|
"feature_2": {
|
|
181
182
|
"title": "Authentication module",
|
|
@@ -321,7 +322,10 @@
|
|
|
321
322
|
"cancel": "Cancel"
|
|
322
323
|
},
|
|
323
324
|
"language_title": "Languages",
|
|
324
|
-
"theme_title": "
|
|
325
|
+
"theme_title": "Theme",
|
|
326
|
+
"theme_option_system": "System",
|
|
327
|
+
"theme_option_light": "Light",
|
|
328
|
+
"theme_option_dark": "Dark",
|
|
325
329
|
"haptic_feedback_title": "Haptic feedback",
|
|
326
330
|
"section_preferences_label": "PREFERENCES",
|
|
327
331
|
"section_security_label": "SECURITY",
|
|
@@ -175,7 +175,8 @@
|
|
|
175
175
|
"title": "Módulo de suscripciones",
|
|
176
176
|
"description": "Gestiona suscripciones con paywalls listos para usar",
|
|
177
177
|
"action": "Continuar",
|
|
178
|
-
"skip": "Omitir"
|
|
178
|
+
"skip": "Omitir",
|
|
179
|
+
"login": "¿Ya tienes cuenta? Iniciar sesión"
|
|
179
180
|
},
|
|
180
181
|
"feature_2": {
|
|
181
182
|
"title": "Módulo de autenticación",
|
|
@@ -321,7 +322,10 @@
|
|
|
321
322
|
"cancel": "Cancelar"
|
|
322
323
|
},
|
|
323
324
|
"language_title": "Idiomas",
|
|
324
|
-
"theme_title": "
|
|
325
|
+
"theme_title": "Tema",
|
|
326
|
+
"theme_option_system": "Sistema",
|
|
327
|
+
"theme_option_light": "Claro",
|
|
328
|
+
"theme_option_dark": "Oscuro",
|
|
325
329
|
"haptic_feedback_title": "Feedback háptico",
|
|
326
330
|
"section_preferences_label": "PREFERENCIAS",
|
|
327
331
|
"section_security_label": "SEGURIDAD",
|
|
@@ -175,7 +175,8 @@
|
|
|
175
175
|
"title": "Módulo de assinaturas",
|
|
176
176
|
"description": "Gerencie assinaturas com paywalls prontos para usar",
|
|
177
177
|
"action": "Continuar",
|
|
178
|
-
"skip": "Pular"
|
|
178
|
+
"skip": "Pular",
|
|
179
|
+
"login": "Já tem conta? Entrar"
|
|
179
180
|
},
|
|
180
181
|
"feature_2": {
|
|
181
182
|
"title": "Módulo de autenticação",
|
|
@@ -321,7 +322,10 @@
|
|
|
321
322
|
"cancel": "Cancelar"
|
|
322
323
|
},
|
|
323
324
|
"language_title": "Idiomas",
|
|
324
|
-
"theme_title": "
|
|
325
|
+
"theme_title": "Tema",
|
|
326
|
+
"theme_option_system": "Sistema",
|
|
327
|
+
"theme_option_light": "Claro",
|
|
328
|
+
"theme_option_dark": "Escuro",
|
|
325
329
|
"haptic_feedback_title": "Feedback háptico",
|
|
326
330
|
"section_preferences_label": "PREFERÊNCIAS",
|
|
327
331
|
"section_security_label": "SEGURANÇA",
|
|
@@ -115,28 +115,47 @@ void run(SharedPreferences prefs) => runApp(
|
|
|
115
115
|
// mode: ThemeMode.dark,
|
|
116
116
|
// ),
|
|
117
117
|
// See ./docs/theme.md for more details
|
|
118
|
-
class MyApp extends
|
|
118
|
+
class MyApp extends ConsumerStatefulWidget {
|
|
119
119
|
final SharedPreferences sharedPreferences;
|
|
120
120
|
|
|
121
121
|
const MyApp({super.key, required this.sharedPreferences});
|
|
122
122
|
|
|
123
|
+
@override
|
|
124
|
+
ConsumerState<MyApp> createState() => _MyAppState();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
class _MyAppState extends ConsumerState<MyApp> {
|
|
128
|
+
late final AppTheme _appTheme;
|
|
129
|
+
|
|
130
|
+
@override
|
|
131
|
+
void initState() {
|
|
132
|
+
super.initState();
|
|
133
|
+
_appTheme = AppTheme.uniform(
|
|
134
|
+
sharedPreferences: widget.sharedPreferences,
|
|
135
|
+
themeFactory: const UniversalThemeFactory(),
|
|
136
|
+
lightColors: KasyColors.light(),
|
|
137
|
+
darkColors: KasyColors.dark(),
|
|
138
|
+
textTheme: KasyTextTheme.build(),
|
|
139
|
+
defaultMode: ThemeMode.system,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@override
|
|
144
|
+
void dispose() {
|
|
145
|
+
_appTheme.dispose();
|
|
146
|
+
super.dispose();
|
|
147
|
+
}
|
|
148
|
+
|
|
123
149
|
// This widget is the root of your application.
|
|
124
150
|
@override
|
|
125
|
-
Widget build(BuildContext context
|
|
151
|
+
Widget build(BuildContext context) {
|
|
126
152
|
ErrorWidget.builder = (FlutterErrorDetails details) {
|
|
127
153
|
return AppErrorWidget(error: details);
|
|
128
154
|
};
|
|
129
155
|
final goRouter = ref.watch(goRouterProvider);
|
|
130
156
|
|
|
131
157
|
return ThemeProvider(
|
|
132
|
-
notifier:
|
|
133
|
-
sharedPreferences: sharedPreferences,
|
|
134
|
-
themeFactory: const UniversalThemeFactory(),
|
|
135
|
-
lightColors: KasyColors.light(),
|
|
136
|
-
darkColors: KasyColors.dark(),
|
|
137
|
-
textTheme: KasyTextTheme.build(),
|
|
138
|
-
defaultMode: ThemeMode.light,
|
|
139
|
-
),
|
|
158
|
+
notifier: _appTheme,
|
|
140
159
|
child: Builder(
|
|
141
160
|
builder: (context) {
|
|
142
161
|
return WebDevicePreview.wrap(
|
|
@@ -134,16 +134,15 @@ flutter_native_splash:
|
|
|
134
134
|
color: "#FFFFFF"
|
|
135
135
|
color_dark: "#000000"
|
|
136
136
|
fullscreen: true
|
|
137
|
-
preserve: true
|
|
138
137
|
ios: true
|
|
139
138
|
android: true
|
|
140
|
-
image: assets/images/
|
|
141
|
-
image_dark: assets/images/
|
|
139
|
+
image: assets/images/splash_logo_light.png
|
|
140
|
+
image_dark: assets/images/splash_logo_dark.png
|
|
142
141
|
android_12:
|
|
143
142
|
color: "#FFFFFF"
|
|
144
143
|
color_dark: "#000000"
|
|
145
|
-
image: assets/images/
|
|
146
|
-
image_dark: assets/images/
|
|
144
|
+
image: assets/images/splash_logo_light.png
|
|
145
|
+
image_dark: assets/images/splash_logo_dark.png
|
|
147
146
|
|
|
148
147
|
# To add assets to your application, add an assets section, like this:
|
|
149
148
|
# assets:
|
|
@@ -30,7 +30,7 @@ void main() {
|
|
|
30
30
|
await tester.runAsync(() async {
|
|
31
31
|
final userRepository = await init();
|
|
32
32
|
|
|
33
|
-
final file = await rootBundle.load('assets/images/
|
|
33
|
+
final file = await rootBundle.load('assets/images/splash_logo_light.png');
|
|
34
34
|
final bytes = file.buffer.asUint8List();
|
|
35
35
|
// if you want to create an XFile from bytes
|
|
36
36
|
// final xfile = XFile.fromData(bytes);
|