diff --git a/filcnaplo/lib/database/init.dart b/filcnaplo/lib/database/init.dart index 1d0fe2a..d384229 100644 --- a/filcnaplo/lib/database/init.dart +++ b/filcnaplo/lib/database/init.dart @@ -35,6 +35,8 @@ const settingsDB = DatabaseStruct("settings", { "renamed_teachers_italics": int, "live_activity_color": String, "welcome_message": String, "app_icon": String, + // paints + "current_theme_id": String, "current_theme_display_name": String, "current_theme_creator": String, }); // DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING // YOU'VE BEEN WARNED!!! diff --git a/filcnaplo/lib/models/settings.dart b/filcnaplo/lib/models/settings.dart index 31201eb..d488b00 100644 --- a/filcnaplo/lib/models/settings.dart +++ b/filcnaplo/lib/models/settings.dart @@ -79,6 +79,10 @@ class SettingsProvider extends ChangeNotifier { Color _liveActivityColor; String _welcomeMessage; String _appIcon; + // current theme + String _currentThemeId; + String _currentThemeDisplayName; + String _currentThemeCreator; SettingsProvider({ DatabaseProvider? database, @@ -127,6 +131,9 @@ class SettingsProvider extends ChangeNotifier { required Color liveActivityColor, required String welcomeMessage, required String appIcon, + required String currentThemeId, + required String currentThemeDisplayName, + required String currentThemeCreator, }) : _database = database, _language = language, _startPage = startPage, @@ -172,7 +179,10 @@ class SettingsProvider extends ChangeNotifier { _renamedTeachersItalics = renameTeachersItalics, _liveActivityColor = liveActivityColor, _welcomeMessage = welcomeMessage, - _appIcon = appIcon; + _appIcon = appIcon, + _currentThemeId = currentThemeId, + _currentThemeDisplayName = currentThemeDisplayName, + _currentThemeCreator = currentThemeCreator; factory SettingsProvider.fromMap(Map map, {required DatabaseProvider database}) { @@ -238,6 +248,9 @@ class SettingsProvider extends ChangeNotifier { liveActivityColor: Color(map["live_activity_color"]), welcomeMessage: map["welcome_message"], appIcon: map["app_icon"], + currentThemeId: map['current_theme_id'], + currentThemeDisplayName: map['current_theme_display_name'], + currentThemeCreator: map['current_theme_creator'], ); } @@ -291,6 +304,9 @@ class SettingsProvider extends ChangeNotifier { "live_activity_color": _liveActivityColor.value, "welcome_message": _welcomeMessage, "app_icon": _appIcon, + "current_theme_id": _currentThemeId, + "current_theme_display_name": _currentThemeDisplayName, + "current_theme_creator": _currentThemeCreator, }; } @@ -348,6 +364,9 @@ class SettingsProvider extends ChangeNotifier { liveActivityColor: const Color(0xFF676767), welcomeMessage: '', appIcon: 'refilc_default', + currentThemeId: '', + currentThemeDisplayName: '', + currentThemeCreator: 'reFilc', ); } @@ -400,6 +419,9 @@ class SettingsProvider extends ChangeNotifier { Color get liveActivityColor => _liveActivityColor; String get welcomeMessage => _welcomeMessage; String get appIcon => _appIcon; + String get currentThemeId => _currentThemeId; + String get currentThemeDisplayName => _currentThemeDisplayName; + String get currentThemeCreator => _currentThemeCreator; Future update({ bool store = true, @@ -448,6 +470,9 @@ class SettingsProvider extends ChangeNotifier { Color? liveActivityColor, String? welcomeMessage, String? appIcon, + String? currentThemeId, + String? currentThemeDisplayName, + String? currentThemeCreator, }) async { if (language != null && language != _language) _language = language; if (startPage != null && startPage != _startPage) _startPage = startPage; @@ -578,6 +603,17 @@ class SettingsProvider extends ChangeNotifier { if (appIcon != null && appIcon != _appIcon) { _appIcon = appIcon; } + if (currentThemeId != null && currentThemeId != _currentThemeId) { + _currentThemeId = currentThemeId; + } + if (currentThemeDisplayName != null && + currentThemeDisplayName != _currentThemeDisplayName) { + _currentThemeDisplayName = currentThemeDisplayName; + } + if (currentThemeCreator != null && + currentThemeCreator != _currentThemeCreator) { + _currentThemeCreator = currentThemeCreator; + } // store or not if (store) await _database?.store.storeSettings(this); notifyListeners(); diff --git a/filcnaplo_kreta_api/lib/providers/share_provider.dart b/filcnaplo_kreta_api/lib/providers/share_provider.dart index ba55417..9d19b8f 100644 --- a/filcnaplo_kreta_api/lib/providers/share_provider.dart +++ b/filcnaplo_kreta_api/lib/providers/share_provider.dart @@ -22,7 +22,8 @@ class ShareProvider extends ChangeNotifier { Future shareCurrentTheme(BuildContext context, {bool isPublic = false, bool shareNick = true, - required SharedGradeColors gradeColors}) async { + required SharedGradeColors gradeColors, + String displayName = ''}) async { final SettingsProvider settings = Provider.of(context, listen: false); @@ -30,6 +31,7 @@ class ShareProvider extends ChangeNotifier { 'public_id': const Uuid().v4(), 'is_public': isPublic, 'nickname': shareNick ? _user.nickname : 'Anonymous', + 'display_name': displayName, 'background_color': (settings.customBackgroundColor ?? SettingsProvider.defaultSettings().customBackgroundColor) ?.value, diff --git a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart b/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart index 9070a43..b786906 100755 --- a/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart +++ b/filcnaplo_mobile_ui/lib/screens/settings/settings_screen.i18n.dart @@ -88,6 +88,10 @@ extension SettingsLocalization on String { "dl_paint": "Redeemed", "public_paint": "Public Paints", "no_pub_paint": "No Public Paints", + "enter_id": "Enter Paint ID", + "paint_id": "Paint ID...", + "set_as_current": "Set as current", + "share_subj_theme": "Share Theme", }, "hu_hu": { "personal_details": "Személyes információk", @@ -174,6 +178,10 @@ extension SettingsLocalization on String { "dl_paint": "Beszerzett", "public_paint": "Nyilvános témák", "no_pub_paint": "Nincsenek nyilvános festékek", + "enter_id": "Azonosító megadása", + "paint_id": "Téma azonosító...", + "set_as_current": "Beállítás jelenleginek", + "share_subj_theme": "Téma Megosztás", }, "de_de": { "personal_details": "Persönliche Angaben", @@ -260,6 +268,10 @@ extension SettingsLocalization on String { "dl_paint": "Eingelöst", "public_paint": "Öffentliche Themen", "no_pub_paint": "Keine öffentlichen Anstriche", + "enter_id": "Themen-ID eingeben", + "paint_id": "Themen-ID...", + "set_as_current": "Als aktuell einstellen", + "share_subj_theme": "Thema Teilen", }, }; diff --git a/filcnaplo_mobile_ui/lib/screens/settings/submenu/paint_list.dart b/filcnaplo_mobile_ui/lib/screens/settings/submenu/paint_list.dart index 25c9cab..9ca868c 100644 --- a/filcnaplo_mobile_ui/lib/screens/settings/submenu/paint_list.dart +++ b/filcnaplo_mobile_ui/lib/screens/settings/submenu/paint_list.dart @@ -5,7 +5,9 @@ import 'package:filcnaplo/models/settings.dart'; import 'package:filcnaplo/models/shared_theme.dart'; import 'package:filcnaplo/theme/colors/accent.dart'; import 'package:filcnaplo/theme/colors/colors.dart'; +import 'package:filcnaplo/theme/observer.dart'; import 'package:filcnaplo_kreta_api/providers/share_provider.dart'; +import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart'; import 'package:filcnaplo_mobile_ui/common/empty.dart'; import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart'; import 'package:filcnaplo_mobile_ui/common/splitted_panel/splitted_panel.dart'; @@ -76,6 +78,10 @@ class PaintListScreenState extends State late List tiles; + final _paintId = TextEditingController(); + + SharedTheme? newThemeByID; + @override void initState() { super.initState(); @@ -194,6 +200,37 @@ class PaintListScreenState extends State const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0), child: Column( children: [ + // enter id + SplittedPanel( + padding: EdgeInsets.zero, + cardPadding: const EdgeInsets.all(3.0), + hasBorder: true, + isTransparent: true, + children: [ + PanelButton( + onPressed: () => showEnterIDDialog(), + title: Text( + "enter_id".i18n, + style: TextStyle( + color: AppColors.of(context).text.withOpacity(.95), + ), + ), + leading: Icon( + FeatherIcons.plus, + size: 22.0, + color: AppColors.of(context).text.withOpacity(.95), + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12.0), + bottom: Radius.circular(12.0), + ), + ), + ], + ), + + const SizedBox( + height: 18.0, + ), // current paint SplittedPanel( title: Text('current_paint'.i18n), @@ -202,32 +239,44 @@ class PaintListScreenState extends State children: [ PanelButton( onPressed: () async { - SharedGradeColors gradeColors = await shareProvider - .shareCurrentGradeColors(context); - SharedTheme theme = - await shareProvider.shareCurrentTheme( - context, - gradeColors: gradeColors, - ); + if (settingsProvider.currentThemeId != '') { + Share.share( + settingsProvider.currentThemeId, + subject: 'share_subj_theme'.i18n, + ); + } else { + SharedGradeColors gradeColors = await shareProvider + .shareCurrentGradeColors(context); + SharedTheme theme = + await shareProvider.shareCurrentTheme( + context, + gradeColors: gradeColors, + ); - Share.share( - theme.id, - subject: 'share_subj_theme'.i18n, - ); + Share.share( + theme.id, + subject: 'share_subj_theme'.i18n, + ); + } }, longPressInstead: true, title: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 't.displayName', + settingsProvider.currentThemeDisplayName != + 'displayName' + ? settingsProvider.currentThemeDisplayName + : 'Névtelen téma', style: TextStyle( color: AppColors.of(context).text.withOpacity(.95), ), ), Text( - user.nickname ?? 'Anonymous', + settingsProvider.currentThemeCreator != '' + ? settingsProvider.currentThemeCreator + : 'Anonymous', style: TextStyle( color: AppColors.of(context).text.withOpacity(.65), @@ -339,4 +388,179 @@ class PaintListScreenState extends State ), ); } + + // enter id dialog + void showEnterIDDialog() { + _paintId.text = ''; + + showDialog( + context: context, + builder: (context) => StatefulBuilder(builder: (context, setS) { + return AlertDialog( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(14.0))), + title: Text("enter_id".i18n), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: _paintId, + onEditingComplete: () async { + // SharedTheme? theme = await shareProvider.getThemeById( + // context, + // id: _paintId.text.replaceAll(' ', ''), + // ); + + // if (theme != null) { + // // set theme variable + // newThemeByID = theme; + + // _paintId.clear(); + // } else { + // ScaffoldMessenger.of(context).showSnackBar( + // CustomSnackBar( + // content: Text("theme_not_found".i18n, + // style: const TextStyle(color: Colors.white)), + // backgroundColor: AppColors.of(context).red, + // context: context, + // ), + // ); + // } + }, + decoration: InputDecoration( + border: OutlineInputBorder( + borderSide: + const BorderSide(color: Colors.grey, width: 1.5), + borderRadius: BorderRadius.circular(12.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: + const BorderSide(color: Colors.grey, width: 1.5), + borderRadius: BorderRadius.circular(12.0), + ), + contentPadding: const EdgeInsets.symmetric(horizontal: 12.0), + hintText: 'paint_id'.i18n, + suffixIcon: IconButton( + icon: const Icon( + FeatherIcons.x, + color: Colors.grey, + ), + onPressed: () { + setState(() { + _paintId.text = ''; + }); + }, + ), + ), + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: Icon(FeatherIcons.arrowDown, size: 32), + ), + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: + const BorderRadius.all(Radius.circular(12.0))), + padding: const EdgeInsets.symmetric(vertical: 10.0), + child: Center( + child: Text( + 'set_as_current'.i18n, + style: const TextStyle( + fontWeight: FontWeight.w500, fontSize: 16.0), + ), + ), + ), + ], + ), + actions: [ + TextButton( + child: Text( + "cancel".i18n, + style: const TextStyle(fontWeight: FontWeight.w500), + ), + onPressed: () { + Navigator.of(context).maybePop(); + }, + ), + TextButton( + child: Text( + "done".i18n, + style: const TextStyle(fontWeight: FontWeight.w500), + ), + onPressed: () async { + // get sex + + SharedTheme? theme = await shareProvider.getThemeById( + context, + id: _paintId.text.replaceAll(' ', ''), + ); + + if (theme != null) { + // set theme variable + newThemeByID = theme; + + _paintId.clear(); + } else { + ScaffoldMessenger.of(context).showSnackBar( + CustomSnackBar( + content: Text("theme_not_found".i18n, + style: const TextStyle(color: Colors.white)), + backgroundColor: AppColors.of(context).red, + context: context, + ), + ); + } + + // slay + + setPaint(); + + setState(() {}); + Navigator.of(context).pop(); + }, + ), + ], + ); + }), + ).then((val) { + _paintId.clear(); + }); + } + + void setPaint() async { + if (newThemeByID == null) return; + + // changing grade colors + List colors = [ + newThemeByID!.gradeColors.oneColor, + newThemeByID!.gradeColors.twoColor, + newThemeByID!.gradeColors.threeColor, + newThemeByID!.gradeColors.fourColor, + newThemeByID!.gradeColors.fiveColor, + ]; + settingsProvider.update(gradeColors: colors); + + // changing shadow effect + settingsProvider.update(shadowEffect: newThemeByID!.shadowEffect); + + // changing theme + settingsProvider.update( + customBackgroundColor: newThemeByID!.backgroundColor, + customHighlightColor: newThemeByID!.panelsColor, + customAccentColor: newThemeByID!.accentColor, + customIconColor: newThemeByID!.iconColor, + // new things + currentThemeId: newThemeByID!.id, + currentThemeDisplayName: newThemeByID!.displayName, + currentThemeCreator: newThemeByID!.nickname, + // we should store it + store: true, + ); + + // seems weird but it works, trust me (idk why) + await settingsProvider.update(theme: settingsProvider.theme, store: true); + Provider.of(context, listen: false) + .changeTheme(settingsProvider.theme, updateNavbarColor: true); + } } diff --git a/filcnaplo_mobile_ui/lib/screens/settings/theme_screen.dart b/filcnaplo_mobile_ui/lib/screens/settings/theme_screen.dart index 7d5e5ff..23e1e9f 100644 --- a/filcnaplo_mobile_ui/lib/screens/settings/theme_screen.dart +++ b/filcnaplo_mobile_ui/lib/screens/settings/theme_screen.dart @@ -111,7 +111,7 @@ class _PremiumCustomAccentColorSettingState @override void initState() { super.initState(); - _colorsTabController = TabController(length: 5, vsync: this); + _colorsTabController = TabController(length: 4, vsync: this); _testTabController = TabController(length: 4, vsync: this); settings = Provider.of(context, listen: false); shareProvider = Provider.of(context, listen: false); @@ -159,6 +159,14 @@ class _PremiumCustomAccentColorSettingState void updateCustomColor(dynamic v, bool store, {Color? accent, Color? background, Color? panels, Color? icon}) { + // reset custom theme id + settings.update( + currentThemeId: '', + currentThemeDisplayName: '', + currentThemeCreator: '', + store: store, + ); + if (colorMode != CustomColorMode.theme) { settings.update(accentColor: AccentColor.custom, store: store); } @@ -681,9 +689,9 @@ class _PremiumCustomAccentColorSettingState tab: Tab( text: "colorpicker_presets" .i18n)), - ColorTab( - color: unknownColor, - tab: Tab(text: "enter_id".i18n)), + // ColorTab( + // color: unknownColor, + // tab: Tab(text: "enter_id".i18n)), /*ColorTab( color: settings.customAccentColor ?? @@ -742,37 +750,37 @@ class _PremiumCustomAccentColorSettingState CustomColorMode.theme; }); break; - case 1: - setState(() { - colorMode = - CustomColorMode.enterId; - }); - break; + // case 1: + // setState(() { + // colorMode = + // CustomColorMode.enterId; + // }); + // break; /*case 1: setState(() { colorMode = CustomColorMode.saved; }); break;*/ - case 2: + case 1: setState(() { colorMode = CustomColorMode.background; }); break; - case 3: + case 2: setState(() { colorMode = CustomColorMode.highlight; }); break; - case 4: + case 3: setState(() { colorMode = CustomColorMode.accent; }); break; - case 5: + case 4: setState(() { colorMode = CustomColorMode.icon;