diff --git a/lib/main.dart b/lib/main.dart index 60026022f..71604381a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -188,33 +188,8 @@ void main() async { await MainDB.instance.initMainDB(); ThemeService.instance.init(MainDB.instance); - // install default themes - if (!(await ThemeService.instance.verifyInstalled(themeId: "light"))) { - Logging.instance.log( - "Installing default light theme...", - level: LogLevel.Info, - ); - final lightZip = await rootBundle.load("assets/default_themes/light.zip"); - await ThemeService.instance - .install(themeArchiveData: lightZip.buffer.asUint8List()); - Logging.instance.log( - "Installing default light theme... finished", - level: LogLevel.Info, - ); - } - if (!(await ThemeService.instance.verifyInstalled(themeId: "dark"))) { - Logging.instance.log( - "Installing default dark theme... ", - level: LogLevel.Info, - ); - final darkZip = await rootBundle.load("assets/default_themes/dark.zip"); - await ThemeService.instance - .install(themeArchiveData: darkZip.buffer.asUint8List()); - Logging.instance.log( - "Installing default dark theme... finished", - level: LogLevel.Info, - ); - } + // check and update or install default themes + await ThemeService.instance.checkDefaultThemesOnStartup(); runApp(const ProviderScope(child: MyApp())); } diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart index 1b7fc0415..b363108c7 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart @@ -225,14 +225,14 @@ class _IncognitoInstalledThemesState extends ConsumerState<IncognitoInstalledThemes> { late final StreamSubscription<void> _subscription; - List<Tuple2<String, String>> installedThemeIdNames = []; + List<Tuple3<String, String, int?>> installedThemeIdNames = []; void _updateInstalledList() { installedThemeIdNames = ref .read(pThemeService) .installedThemes .where((e) => e.themeId != "light" && e.themeId != "dark") - .map((e) => Tuple2(e.themeId, e.name)) + .map((e) => Tuple3(e.themeId, e.name, e.version)) .toList(); } @@ -274,6 +274,7 @@ class _IncognitoInstalledThemesState data: StackThemeMetaData( name: e.item2, id: e.item1, + version: e.item3 ?? 1, sha256: "", size: "", previewImageUrl: "", diff --git a/lib/pages_desktop_specific/settings/settings_menu/appearance_settings/appearance_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/appearance_settings/appearance_settings.dart index 4c500eaf7..a005028b1 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/appearance_settings/appearance_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/appearance_settings/appearance_settings.dart @@ -118,44 +118,6 @@ class _AppearanceOptionSettings ], ), ), - // const Padding( - // padding: EdgeInsets.all(10.0), - // child: Divider( - // thickness: 0.5, - // ), - // ), - // Padding( - // padding: const EdgeInsets.all(10.0), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Text( - // "System brightness", - // style: STextStyles.desktopTextExtraSmall(context) - // .copyWith( - // color: Theme.of(context) - // .extension<StackColors>()! - // .textDark), - // textAlign: TextAlign.left, - // ), - // SizedBox( - // height: 20, - // width: 40, - // child: DraggableSwitchButton( - // isOn: ref.watch( - // prefsChangeNotifierProvider.select( - // (value) => value.enableSystemBrightness), - // ), - // onValueChanged: (newValue) { - // ref - // .read(prefsChangeNotifierProvider) - // .enableSystemBrightness = newValue; - // }, - // ), - // ) - // ], - // ), - // ), const Padding( padding: EdgeInsets.all(10.0), child: Divider( diff --git a/lib/themes/theme_service.dart b/lib/themes/theme_service.dart index 2f3d5e6fb..e130daba8 100644 --- a/lib/themes/theme_service.dart +++ b/lib/themes/theme_service.dart @@ -1,9 +1,9 @@ import 'dart:convert'; import 'dart:io'; -import 'dart:typed_data'; import 'package:archive/archive_io.dart'; import 'package:crypto/crypto.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:http/http.dart'; import 'package:isar/isar.dart'; @@ -17,6 +17,7 @@ final pThemeService = Provider<ThemeService>((ref) { }); class ThemeService { + static const _currentDefaultThemeVersion = 2; ThemeService._(); static ThemeService? _instance; static ThemeService get instance => _instance ??= ThemeService._(); @@ -92,6 +93,70 @@ class ThemeService { } } + Future<void> checkDefaultThemesOnStartup() async { + // install default themes + if (!(await ThemeService.instance.verifyInstalled(themeId: "light"))) { + Logging.instance.log( + "Installing default light theme...", + level: LogLevel.Info, + ); + final lightZip = await rootBundle.load("assets/default_themes/light.zip"); + await ThemeService.instance + .install(themeArchiveData: lightZip.buffer.asUint8List()); + Logging.instance.log( + "Installing default light theme... finished", + level: LogLevel.Info, + ); + } else { + // check installed version + final theme = ThemeService.instance.getTheme(themeId: "light"); + if ((theme?.version ?? 1) < _currentDefaultThemeVersion) { + Logging.instance.log( + "Updating default light theme...", + level: LogLevel.Info, + ); + final lightZip = + await rootBundle.load("assets/default_themes/light.zip"); + await ThemeService.instance + .install(themeArchiveData: lightZip.buffer.asUint8List()); + Logging.instance.log( + "Updating default light theme... finished", + level: LogLevel.Info, + ); + } + } + + if (!(await ThemeService.instance.verifyInstalled(themeId: "dark"))) { + Logging.instance.log( + "Installing default dark theme... ", + level: LogLevel.Info, + ); + final darkZip = await rootBundle.load("assets/default_themes/dark.zip"); + await ThemeService.instance + .install(themeArchiveData: darkZip.buffer.asUint8List()); + Logging.instance.log( + "Installing default dark theme... finished", + level: LogLevel.Info, + ); + } else { + // check installed version + final theme = ThemeService.instance.getTheme(themeId: "dark"); + if ((theme?.version ?? 1) < _currentDefaultThemeVersion) { + Logging.instance.log( + "Updating default dark theme...", + level: LogLevel.Info, + ); + final darkZip = await rootBundle.load("assets/default_themes/dark.zip"); + await ThemeService.instance + .install(themeArchiveData: darkZip.buffer.asUint8List()); + Logging.instance.log( + "Updating default dark theme... finished", + level: LogLevel.Info, + ); + } + } + } + // TODO more thorough check/verification of theme Future<bool> verifyInstalled({required String themeId}) async { final dbHasTheme = @@ -175,6 +240,7 @@ class ThemeService { class StackThemeMetaData { final String name; final String id; + final int version; final String sha256; final String size; final String previewImageUrl; @@ -182,6 +248,7 @@ class StackThemeMetaData { StackThemeMetaData({ required this.name, required this.id, + required this.version, required this.sha256, required this.size, required this.previewImageUrl, @@ -192,6 +259,7 @@ class StackThemeMetaData { return StackThemeMetaData( name: map["name"] as String, id: map["id"] as String, + version: map["version"] as int? ?? 1, sha256: map["sha256"] as String, size: map["size"] as String, previewImageUrl: map["previewImageUrl"] as String, @@ -210,6 +278,7 @@ class StackThemeMetaData { return "$runtimeType(" "name: $name, " "id: $id, " + "version: $version, " "sha256: $sha256, " "size: $size, " "previewImageUrl: $previewImageUrl"