From 7f00c8c5eac900f1942fd14158bbe3a834beffb1 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 13:50:06 +0530 Subject: [PATCH 01/14] started work on dark mode --- lib/core/common/app_asset.dart | 11 +- lib/core/common/app_buttons.dart | 75 ++-- lib/core/common/app_colors.dart | 135 +++---- lib/core/common/app_dialog.dart | 24 +- lib/core/common/app_dropdown.dart | 7 +- lib/core/common/app_semantic_colors.dart | 272 +++++++++++++ lib/core/common/app_text_field.dart | 66 +--- lib/core/common/app_text_styles.dart | 36 +- lib/core/common/app_theme.dart | 374 +++++++++++++++++- lib/core/common/common.dart | 1 + lib/core/extensions/context.dart | 14 +- lib/core/utils/decoration.dart | 15 - lib/core/utils/pro_utils.dart | 4 +- lib/core/widgets/app_pin_field.dart | 8 +- lib/core/widgets/app_rich_text.dart | 5 +- lib/core/widgets/app_text.dart | 6 +- lib/core/widgets/app_tile.dart | 17 +- lib/core/widgets/app_webview.dart | 4 +- lib/core/widgets/base_screen.dart | 3 +- lib/core/widgets/bottomsheet.dart | 13 +- lib/core/widgets/card_dropdown.dart | 23 +- lib/core/widgets/divider_space.dart | 6 +- lib/core/widgets/email_tag.dart | 2 +- lib/core/widgets/flag.dart | 5 +- lib/core/widgets/info_row.dart | 6 +- lib/core/widgets/labeled_card_dropdown.dart | 6 +- lib/core/widgets/labeled_card_input.dart | 2 +- lib/core/widgets/password_criteria.dart | 8 +- lib/core/widgets/platform_card.dart | 4 +- lib/core/widgets/pro_banner.dart | 6 +- lib/core/widgets/search_bar.dart | 8 +- lib/core/widgets/section_label.dart | 4 +- lib/core/widgets/setting_tile.dart | 36 +- lib/core/widgets/split_tunneling_tile.dart | 2 +- lib/core/widgets/switch_button.dart | 16 +- lib/features/account/account.dart | 18 +- lib/features/account/delete_account.dart | 4 +- lib/features/auth/add_email.dart | 12 +- lib/features/auth/choose_payment_method.dart | 20 +- lib/features/auth/confirm_email.dart | 4 +- lib/features/auth/create_password.dart | 6 +- lib/features/auth/device_limit_reached.dart | 4 +- lib/features/auth/lantern_pro_license.dart | 2 +- lib/features/auth/reset_password.dart | 10 +- lib/features/auth/sign_in_password.dart | 8 +- lib/features/home/data_usage.dart | 14 +- lib/features/home/home.dart | 13 +- lib/features/logs/logs.dart | 2 +- .../macos_extension_dialog.dart | 10 +- lib/features/onboarding/onboarding.dart | 46 +-- lib/features/plans/feature_list.dart | 2 +- lib/features/plans/plan_item.dart | 26 +- lib/features/plans/plans.dart | 18 +- .../private_server/join_private_server.dart | 8 +- .../private_server/manage_private_server.dart | 14 +- .../private_server/manually_server_setup.dart | 6 +- .../private_server_add_billing.dart | 12 +- .../private_server/private_server_deploy.dart | 10 +- .../private_server_locations.dart | 2 +- .../private_server/private_sever_details.dart | 2 +- .../private_server/provider_card.dart | 6 +- .../private_server/provider_carousel.dart | 14 +- lib/features/setting/download_links.dart | 6 +- lib/features/setting/invite_friends.dart | 29 +- lib/features/setting/setting.dart | 8 +- lib/features/setting/smart_routing.dart | 4 +- lib/features/setting/vpn_setting.dart | 4 +- .../split_tunneling/apps_split_tunneling.dart | 6 +- .../split_tunneling/split_tunneling.dart | 4 +- .../split_tunneling/split_tunneling_info.dart | 14 +- .../split_tunneling/website_domain_input.dart | 4 +- .../website_split_tunneling.dart | 4 +- lib/features/support/app_version.dart | 8 +- lib/features/vpn/server_desktop_view.dart | 8 +- lib/features/vpn/server_selection.dart | 34 +- lib/features/vpn/single_city_server_view.dart | 2 +- lib/features/vpn/vpn_status.dart | 16 +- lib/features/vpn/vpn_switch.dart | 16 +- lib/lantern_app.dart | 2 +- 79 files changed, 1157 insertions(+), 529 deletions(-) create mode 100644 lib/core/common/app_semantic_colors.dart diff --git a/lib/core/common/app_asset.dart b/lib/core/common/app_asset.dart index 526228a213..a37f5e787c 100644 --- a/lib/core/common/app_asset.dart +++ b/lib/core/common/app_asset.dart @@ -17,6 +17,9 @@ class AppImage extends StatelessWidget { final AssetType type; final OnPressed? onPressed; final BoxFit? fit; + // Set to false for decorative/multicolor assets (illustrations, logos) + // that should not be recolored by the theme. + final bool useThemeColor; const AppImage({ required this.path, @@ -26,6 +29,7 @@ class AppImage extends StatelessWidget { this.type = AssetType.svg, this.onPressed, this.fit, + this.useThemeColor = true, super.key, }); @@ -33,6 +37,9 @@ class AppImage extends StatelessWidget { Widget build(BuildContext context) { switch (type) { case AssetType.svg: + // Use explicit color > theme icon color > no filter (when opted out) + final effectiveColor = + color ?? (useThemeColor ? Theme.of(context).iconTheme.color : null); return GestureDetector( onTap: onPressed, child: SvgPicture.asset( @@ -40,8 +47,8 @@ class AppImage extends StatelessWidget { height: height, width: width, fit: fit ?? BoxFit.contain, - colorFilter: color != null - ? ColorFilter.mode(color!, BlendMode.srcIn) + colorFilter: effectiveColor != null + ? ColorFilter.mode(effectiveColor, BlendMode.srcIn) : null, ), ); diff --git a/lib/core/common/app_buttons.dart b/lib/core/common/app_buttons.dart index 492dc199a5..f2a833604f 100644 --- a/lib/core/common/app_buttons.dart +++ b/lib/core/common/app_buttons.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:lantern/core/common/app_asset.dart'; import 'package:lantern/core/common/app_colors.dart'; import 'package:lantern/core/common/app_dimens.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import 'package:lantern/core/common/app_text_styles.dart'; import 'package:lantern/core/common/cap_scaling.dart'; @@ -56,6 +57,7 @@ class PrimaryButton extends StatelessWidget { path: icon!, height: iconHeight, color: iconColor, + useThemeColor: false, ), label: Text(label), style: _buildButtonStyle(context, button!, iconSz), @@ -69,6 +71,7 @@ class PrimaryButton extends StatelessWidget { ) { final verticalPad = hCap(context, 12); final fontSz = spCap(context, 16); + final isDark = Theme.of(context).brightness == Brightness.dark; // Heights final minHeight = isTaller == true ? hCap(context, 56) : hCap(context, 48); @@ -78,36 +81,42 @@ class PrimaryButton extends StatelessWidget { backgroundColor: WidgetStateProperty.resolveWith( (Set states) { if (states.contains(WidgetState.disabled)) { - return AppColors.gray2; // Disabled background color + // primary-disabled-bg: Gray.200 light / Gray.700 dark + return isDark ? AppColors.gray7 : AppColors.gray2; } if (states.contains(WidgetState.hovered) && bgColor == AppColors.blue1) { - return AppColors.blue2; // Pressed background color + return AppColors.blue2; } if (states.contains(WidgetState.hovered)) { - return AppColors.blue8; // Hovered background color + // primary-bg-hover: Blue.800 light / Blue.500 dark + return isDark ? AppColors.blue5 : AppColors.blue8; } - return bgColor ?? AppColors.blue10; // Default background color + // primary-bg: Blue.1000 light / Blue.600 dark + return bgColor ?? (isDark ? AppColors.blue6 : AppColors.blue10); }, ), side: WidgetStateProperty.resolveWith( (Set states) { if (states.contains(WidgetState.disabled)) { - return BorderSide(color: AppColors.gray4, width: 1); + // primary-disabled-border: Gray.400 light / Gray.500 dark + return BorderSide( + color: isDark ? AppColors.gray5 : AppColors.gray4, + width: 1, + ); } if (showBorder) { - return BorderSide(color: AppColors.gray2, width: 1); + return BorderSide( + color: isDark ? AppColors.gray7 : AppColors.gray2, + width: 1, + ); } return BorderSide.none; }, ), - // backgroundColor: WidgetStatePropertyAll(bgColor ?? AppColors.blue7), iconSize: WidgetStatePropertyAll(iconSz), padding: WidgetStatePropertyAll( - EdgeInsets.symmetric( - vertical: verticalPad, - horizontal: 40.0, - ), + EdgeInsets.symmetric(vertical: verticalPad, horizontal: 40.0), ), textStyle: WidgetStatePropertyAll( AppTextStyles.primaryButtonTextStyle.copyWith( @@ -115,6 +124,7 @@ class PrimaryButton extends StatelessWidget { fontWeight: FontWeight.w500, ), ), + // primary-text: Gray.100 both / primary-disabled-text: Gray.500 both foregroundColor: WidgetStatePropertyAll( enabled == false ? AppColors.gray5 : textColor ?? AppColors.gray1, ), @@ -181,40 +191,58 @@ class SecondaryButton extends StatelessWidget { ) { final verticalPad = hCap(context, 12); final fontSz = spCap(context, 16); + final isDark = Theme.of(context).brightness == Brightness.dark; // Heights final height = isTaller == true ? hCap(context, 56) : hCap(context, 50); + // secondary-text: Gray.900 light / Gray.100 dark + final textColor = isDark ? AppColors.gray1 : AppColors.gray9; + return style.copyWith( backgroundColor: WidgetStateProperty.resolveWith( (Set states) { if (states.contains(WidgetState.disabled)) { - return AppColors.gray2; // Disabled background color + // secondary-disabled-bg: Gray.200 light / Gray.900 dark + return isDark ? AppColors.gray9 : AppColors.gray2; + } + if (states.contains(WidgetState.hovered)) { + // secondary-bg-hover: Gray.200 light / Gray.800 dark + return isDark ? AppColors.gray8 : AppColors.gray2; } - return bgColor ?? AppColors.gray1; // Default background color + // secondary-bg: Gray.100 light / Gray.900 dark + return bgColor ?? (isDark ? AppColors.gray9 : AppColors.gray1); }, ), side: WidgetStateProperty.resolveWith( (Set states) { if (states.contains(WidgetState.disabled)) { - return BorderSide(color: AppColors.gray4, width: 1); + // secondary-disabled-border: Gray.400 light / Gray.700 dark + return BorderSide( + color: isDark ? AppColors.gray7 : AppColors.gray4, + width: 1, + ); } - return BorderSide(color: AppColors.gray4, width: 1); + // secondary-border: Gray.500 light / Gray.600 dark + return BorderSide( + color: isDark ? AppColors.gray6 : AppColors.gray5, + width: 1, + ); }, ), - overlayColor: WidgetStatePropertyAll(AppColors.gray2), - foregroundColor: WidgetStatePropertyAll(AppColors.gray9), + // secondary-bg-hover used as overlay + overlayColor: WidgetStatePropertyAll( + isDark ? AppColors.gray8 : AppColors.gray2, + ), + foregroundColor: WidgetStatePropertyAll(textColor), iconSize: WidgetStatePropertyAll(iconSz), padding: WidgetStatePropertyAll( - EdgeInsets.symmetric( - vertical: verticalPad, - horizontal: 40.0, - ), + EdgeInsets.symmetric(vertical: verticalPad, horizontal: 40.0), ), textStyle: WidgetStatePropertyAll( AppTextStyles.primaryButtonTextStyle.copyWith( fontSize: expanded ? fontSz : 16.0, - color: AppColors.gray9, + color: textColor, fontWeight: FontWeight.w600, ), ), @@ -259,7 +287,8 @@ class AppTextButton extends StatelessWidget { underLine ? TextDecoration.underline : TextDecoration.none, fontSize: cappedFontSize, ), - foregroundColor: textColor ?? AppColors.blue7, + // text.link from semantic token + foregroundColor: textColor ?? context.textLink, ), child: Text(label), ); diff --git a/lib/core/common/app_colors.dart b/lib/core/common/app_colors.dart index 3737411824..b6d6df04f1 100644 --- a/lib/core/common/app_colors.dart +++ b/lib/core/common/app_colors.dart @@ -1,133 +1,136 @@ import 'package:flutter/material.dart'; class AppColors { - static Color get black => const Color(0xFF000000); + static const Color black = Color(0xFF000000); - static Color get black1 => const Color(0xFF1A1B1C); + static const Color black1 = Color(0xFF1A1B1C); - static Color get white => Colors.white; + static const Color white = Color(0xFFFFFFFF); - static Color get whiteBlur => const Color(0xCCF8FAFB); + static const Color whiteBlur = Color(0xCCF8FAFB); - static Color get blue1 => const Color(0xFFF0FDFF); + static const Color blue1 = Color(0xFFF0FDFF); - static Color get blue2 => const Color(0xFFD6F6FA); + static const Color blue2 = Color(0xFFD6F6FA); - static Color get blue3 => const Color(0xFF6AD8E7); + static const Color blue3 = Color(0xFF6AD8E7); - static Color get blue4 => const Color(0xFF00BDD6); + static const Color blue4 = Color(0xFF00BDD6); - static Color get blue5 => const Color(0xFF009EB2); + static const Color blue5 = Color(0xFF009EB2); - static Color get blue6 => const Color(0xFF008394); + static const Color blue6 = Color(0xFF008394); - static Color get blue7 => const Color(0xFF005F61); + static const Color blue7 = Color(0xFF005F61); - static Color get blue8 => const Color(0xFF004D57); + static const Color blue8 = Color(0xFF004D57); - static Color get blue9 => const Color(0xFF00353D); + static const Color blue9 = Color(0xFF00353D); - static Color get blue10 => const Color(0xFF012D2D); + static const Color blue10 = Color(0xFF012D2D); - static Color get gray0 => Colors.white; + static const Color gray0 = Color(0xFFFFFFFF); - static Color get gray1 => const Color(0xFFF8FAFB); + static const Color gray1 = Color(0xFFF8FAFB); - static Color get gray2 => const Color(0xFFEDEFEF); + static const Color gray2 = Color(0xFFEDEFEF); - static Color get gray3 => const Color(0xFFDEDFDF); + static const Color gray3 = Color(0xFFDEDFDF); - static Color get gray4 => const Color(0xFFBFBFBF); + static const Color gray4 = Color(0xFFBFBFBF); - static Color get gray5 => const Color(0xFFA2A2A2); + static const Color gray5 = Color(0xFFA2A2A2); - static Color get gray6 => const Color(0xFF848484); + static const Color gray6 = Color(0xFF848484); - static Color get gray7 => const Color(0xFF616569); + static const Color gray7 = Color(0xFF616569); - static Color get gray8 => const Color(0xFF3E464E); + static const Color gray8 = Color(0xFF3E464E); - static Color get gray9 => const Color(0xFF1B1C1D); + // Gray 850 – dark mode elevated/input surface (#2d3136) + static const Color gray850 = Color(0xFF2D3136); - static Color get gray10 => Colors.black; + static const Color gray9 = Color(0xFF1B1C1D); - static Color get gray11 => const Color(0xFF040404); + static const Color gray10 = Color(0xFF000000); - static Color get gray12 => const Color(0xFFBDBDBD); - static Color get lightGray => const Color(0xFF838383); + static const Color gray11 = Color(0xFF040404); - static Color get yellow0 => const Color(0xFFFEFDF6); + static const Color gray12 = Color(0xFFBDBDBD); + static const Color lightGray = Color(0xFF838383); - static Color get yellow1 => const Color(0xFFFCF8E8); + static const Color yellow0 = Color(0xFFFEFDF6); - static Color get yellow2 => const Color(0xFFFAF1D6); + static const Color yellow1 = Color(0xFFFCF8E8); - static Color get yellow3 => const Color(0xFFFFC105); + static const Color yellow2 = Color(0xFFFAF1D6); - static Color get yellow4 => const Color(0xFFD6A100); + static const Color yellow3 = Color(0xFFFFC105); - static Color get yellow5 => const Color(0xFFB88A00); + static const Color yellow4 = Color(0xFFD6A100); - static Color get yellow6 => const Color(0xFF946F00); + static const Color yellow5 = Color(0xFFB88A00); - static Color get yellow7 => const Color(0xFF7A5C00); + static const Color yellow6 = Color(0xFF946F00); - static Color get yellow8 => const Color(0xFF503C02); + static const Color yellow7 = Color(0xFF7A5C00); - static Color get yellow9 => const Color(0xFF3D2D00); + static const Color yellow8 = Color(0xFF503C02); - static Color get yellow10 => const Color(0xFF241800); + static const Color yellow9 = Color(0xFF3D2D00); - static Color get green0 => const Color(0xFFFBFFFA); + static const Color yellow10 = Color(0xFF241800); - static Color get green1 => const Color(0xFFF0FFF4); + static const Color green0 = Color(0xFFFBFFFA); - static Color get green2 => const Color(0xFFD4FAD6); + static const Color green1 = Color(0xFFF0FFF4); - static Color get green3 => const Color(0xFFA2DDAF); + static const Color green2 = Color(0xFFD4FAD6); - static Color get green4 => const Color(0xFF6FC087); + static const Color green3 = Color(0xFFA2DDAF); - static Color get green5 => const Color(0xFF3DA360); + static const Color green4 = Color(0xFF6FC087); - static Color get green6 => const Color(0xFF0A8638); + static const Color green5 = Color(0xFF3DA360); - static Color get green7 => const Color(0xFF006E2B); + static const Color green6 = Color(0xFF0A8638); - static Color get green8 => const Color(0xFF00531F); + static const Color green7 = Color(0xFF006E2B); - static Color get green9 => const Color(0xFF003913); + static const Color green8 = Color(0xFF00531F); - static Color get green10 => const Color(0xFF002108); + static const Color green9 = Color(0xFF003913); - static Color get green11 => const Color(0xFF005F61); + static const Color green10 = Color(0xFF002108); - static Color get green12 => const Color(0xFF1FBF63); + static const Color green11 = Color(0xFF005F61); - static Color get red0 => const Color(0xFFFFF8F7); + static const Color green12 = Color(0xFF1FBF63); - static Color get red1 => const Color(0xFFFFEDEA); + static const Color red0 = Color(0xFFFFF8F7); - static Color get red2 => const Color(0xFFFFDAD5); + static const Color red1 = Color(0xFFFFEDEA); - static Color get red3 => const Color(0xFFFFB4AA); + static const Color red2 = Color(0xFFFFDAD5); - static Color get red4 => const Color(0xFFFF8A7C); + static const Color red3 = Color(0xFFFFB4AA); - static Color get red5 => const Color(0xFFFF5447); + static const Color red4 = Color(0xFFFF8A7C); - static Color get red6 => const Color(0xFFDB1C1C); + static const Color red5 = Color(0xFFFF5447); - static Color get red7 => const Color(0xFFC0000E); + static const Color red6 = Color(0xFFDB1C1C); - static Color get red8 => const Color(0xFF930008); + static const Color red7 = Color(0xFFC0000E); - static Color get red9 => const Color(0xFF690004); + static const Color red8 = Color(0xFF930008); - static Color get red10 => const Color(0xFF410001); + static const Color red9 = Color(0xFF690004); - static Color get shadowColor => const Color(0x19006162); + static const Color red10 = Color(0xFF410001); - static Color get logTextColor => const Color(0xFF3D454D); - static Color get linkColor => const Color(0xFF005F60); + static const Color shadowColor = Color(0x19006162); + + static const Color logTextColor = Color(0xFF3D454D); + static const Color linkColor = Color(0xFF005F60); } diff --git a/lib/core/common/app_dialog.dart b/lib/core/common/app_dialog.dart index c779559d52..a32ced004d 100644 --- a/lib/core/common/app_dialog.dart +++ b/lib/core/common/app_dialog.dart @@ -15,13 +15,9 @@ class AppDialog { barrierDismissible: false, builder: (context) { return AlertDialog( - backgroundColor: AppColors.gray1, + // backgroundColor and shape come from dialogTheme in app_theme.dart contentPadding: EdgeInsets.symmetric(horizontal: defaultSize), actionsPadding: EdgeInsets.all(24), - // contentPadding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), content: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -83,7 +79,7 @@ class AppDialog { return AlertDialog( actionsAlignment: MainAxisAlignment.end, actionsOverflowAlignment: OverflowBarAlignment.end, - backgroundColor: AppColors.gray1, + // backgroundColor and shape come from dialogTheme in app_theme.dart contentPadding: EdgeInsets.symmetric(horizontal: size24), actionsPadding: actionPadding ?? EdgeInsets.only( @@ -91,10 +87,6 @@ class AppDialog { bottom: defaultSize, left: defaultSize, right: defaultSize), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - side: BorderSide(color: AppColors.gray3, width: 1), - ), content: content, actions: action, ); @@ -113,17 +105,13 @@ class AppDialog { barrierDismissible: false, builder: (context) { return AlertDialog( - backgroundColor: AppColors.gray3, + // backgroundColor and shape come from dialogTheme in app_theme.dart contentPadding: EdgeInsets.symmetric(horizontal: defaultSize), actionsPadding: EdgeInsets.only( top: defaultSize, bottom: defaultSize, left: defaultSize, right: defaultSize), - // contentPadding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), content: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -161,17 +149,13 @@ class AppDialog { barrierDismissible: false, builder: (context) { return AlertDialog( - backgroundColor: AppColors.gray3, + // backgroundColor and shape come from dialogTheme in app_theme.dart contentPadding: EdgeInsets.symmetric(horizontal: defaultSize), actionsPadding: EdgeInsets.only( top: defaultSize, bottom: defaultSize, left: defaultSize, right: defaultSize), - // contentPadding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), content: Column( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/core/common/app_dropdown.dart b/lib/core/common/app_dropdown.dart index f3e965fa09..84db83bee9 100644 --- a/lib/core/common/app_dropdown.dart +++ b/lib/core/common/app_dropdown.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:lantern/core/common/app_asset.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import 'app_colors.dart' show AppColors; @@ -28,7 +29,7 @@ class AppDropdown extends StatelessWidget { height: 56, decoration: BoxDecoration( border: Border.all( - color: AppColors.gray3, + color: context.borderInput, width: 1, ), borderRadius: BorderRadius.circular(16), @@ -41,7 +42,7 @@ class AppDropdown extends StatelessWidget { isExpanded: true, padding: EdgeInsets.only(left: prefixIconPath != null ? 8 : 0), style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray9, + color: context.textPrimary, ), value: value, borderRadius: BorderRadius.circular(16), @@ -63,7 +64,7 @@ class AppDropdown extends StatelessWidget { child: Text( label!, style: textTheme.labelLarge?.copyWith( - color: AppColors.gray8, + color: context.textSecondary, fontSize: 14.sp, ), ), diff --git a/lib/core/common/app_semantic_colors.dart b/lib/core/common/app_semantic_colors.dart new file mode 100644 index 0000000000..74b15e2d5a --- /dev/null +++ b/lib/core/common/app_semantic_colors.dart @@ -0,0 +1,272 @@ +import 'package:flutter/material.dart'; +import 'app_colors.dart'; + +/// BuildContext extension that maps Figma Color/Semantic tokens to AppColors. +/// Every property has a light and dark value derived directly from the JSON export. +/// +/// Usage: context.textPrimary, context.bgElevated, context.borderInput … +extension AppSemanticColors on BuildContext { + bool get _isDark => Theme.of(this).brightness == Brightness.dark; + + // ── Text ──────────────────────────────────────────────────────────────────── + + /// text.primary Gray.900 light / Gray.200 dark + Color get textPrimary => _isDark ? AppColors.gray2 : AppColors.gray9; + + /// text.secondary Gray.800 light / Gray.300 dark + Color get textSecondary => _isDark ? AppColors.gray3 : AppColors.gray8; + + /// text.tertiary Gray.700 light / Gray.400 dark + Color get textTertiary => _isDark ? AppColors.gray4 : AppColors.gray7; + + /// text.link Blue.700 light / Blue.200 dark + Color get textLink => _isDark ? AppColors.blue2 : AppColors.blue7; + + /// text.disabled Gray.600 light / Gray.500 dark + Color get textDisabled => _isDark ? AppColors.gray5 : AppColors.gray6; + + /// text.inverse Gray.100 light / Gray.900 dark + Color get textInverse => _isDark ? AppColors.gray9 : AppColors.gray1; + + /// text.inverse-color Blue.400 light / Blue.600 dark + Color get textInverseColor => _isDark ? AppColors.blue6 : AppColors.blue4; + + /// text.promo-icon Yellow.300 both modes + Color get textPromoIcon => AppColors.yellow3; + + // ── Background ────────────────────────────────────────────────────────────── + + /// bg.surface Gray.100 light / Gray.900 dark + Color get bgSurface => _isDark ? AppColors.gray9 : AppColors.gray1; + + /// bg.elevated White light / Gray.850 dark + Color get bgElevated => _isDark ? AppColors.gray850 : AppColors.white; + + /// bg.input White light / Gray.850 dark + Color get bgInput => _isDark ? AppColors.gray850 : AppColors.white; + + /// bg.hover Blue.100 light / Blue.900 dark + Color get bgHover => _isDark ? AppColors.blue9 : AppColors.blue1; + + /// bg.overlay Gray.100 light / Gray.900 dark + Color get bgOverlay => _isDark ? AppColors.gray9 : AppColors.gray1; + + /// bg.callout Gray.200 light / Gray.800 dark + Color get bgCallout => _isDark ? AppColors.gray8 : AppColors.gray2; + + /// bg.snackbar Blue.900 light / Blue.200 dark + Color get bgSnackbar => _isDark ? AppColors.blue2 : AppColors.blue9; + + /// bg.snackbar-error Red.700 light / Red.500 dark + Color get bgSnackbarError => _isDark ? AppColors.red5 : AppColors.red7; + + /// bg.promo Yellow.100 light / Gray.900 dark + Color get bgPromo => _isDark ? AppColors.gray9 : AppColors.yellow1; + + // ── Border ────────────────────────────────────────────────────────────────── + + /// border.default Gray.200 light / Gray.800 dark + Color get borderDefault => _isDark ? AppColors.gray8 : AppColors.gray2; + + /// border.input Gray.300 light / Gray.700 dark + Color get borderInput => _isDark ? AppColors.gray7 : AppColors.gray3; + + /// border.input-focus Blue.800 light / Blue.200 dark + Color get borderInputFocus => _isDark ? AppColors.blue2 : AppColors.blue8; + + /// border.input-filled Gray.900 light / Gray.400 dark + Color get borderInputFilled => _isDark ? AppColors.gray4 : AppColors.gray9; + + /// border.error Red.600 light / Red.500 dark + Color get borderError => _isDark ? AppColors.red5 : AppColors.red6; + + /// border.promo Yellow.500 both modes + Color get borderPromo => AppColors.yellow5; + + // ── Status ────────────────────────────────────────────────────────────────── + + /// status.error-text Red.800 light / Red.200 dark + Color get statusErrorText => _isDark ? AppColors.red2 : AppColors.red8; + + /// status.error-bg Red.200 light / Red.800 dark + Color get statusErrorBg => _isDark ? AppColors.red8 : AppColors.red2; + + /// status.error-border Red.400 light / Red.600 dark + Color get statusErrorBorder => _isDark ? AppColors.red6 : AppColors.red4; + + /// status.success-text Green.800 light / Green.300 dark + Color get statusSuccessText => _isDark ? AppColors.green3 : AppColors.green8; + + /// status.success-bg Green.200 light / Green.700 dark + Color get statusSuccessBg => _isDark ? AppColors.green7 : AppColors.green2; + + /// status.success-border Green.400 light / Green.600 dark + Color get statusSuccessBorder => + _isDark ? AppColors.green6 : AppColors.green4; + + /// status.warning-text Yellow.500 light / Yellow.200 dark + Color get statusWarningText => _isDark ? AppColors.yellow2 : AppColors.yellow5; + + /// status.warning-bg-dot Yellow.300 light / Yellow.500 dark + Color get statusWarningBgDot => + _isDark ? AppColors.yellow5 : AppColors.yellow3; + + /// status.neutral-text Gray.600 light / Gray.200 dark + Color get statusNeutralText => _isDark ? AppColors.gray2 : AppColors.gray6; + + /// status.informational-text Blue.800 light / Blue.200 dark + Color get statusInfoText => _isDark ? AppColors.blue2 : AppColors.blue8; + + /// status.Informational-bg Blue.200 light / Blue.700 dark + Color get statusInfoBg => _isDark ? AppColors.blue7 : AppColors.blue2; + + /// status.Informational-border Blue.400 light / Blue.600 dark + Color get statusInfoBorder => _isDark ? AppColors.blue6 : AppColors.blue4; + + /// status.error-bg-dot Red.600 light / Red.800 dark + Color get statusErrorBgDot => _isDark ? AppColors.red8 : AppColors.red6; + + /// status.error-border-dot Red.300 light / Red.500 dark + Color get statusErrorBorderDot => _isDark ? AppColors.red5 : AppColors.red3; + + /// status.warning-border-dot Yellow.200 light / Yellow.400 dark + Color get statusWarningBorderDot => + _isDark ? AppColors.yellow4 : AppColors.yellow2; + + /// status.success-bg-dot Green.600 light / Green.700 dark + Color get statusSuccessBgDot => + _isDark ? AppColors.green7 : AppColors.green6; + + /// status.success-border-dot Green.300 light / Green.500 dark + Color get statusSuccessBorderDot => + _isDark ? AppColors.green5 : AppColors.green3; + + /// status.neutral-bg-dot Gray.500 light / Gray.700 dark + Color get statusNeutralBgDot => _isDark ? AppColors.gray7 : AppColors.gray5; + + /// status.neutral-border-dot Gray.300 light / Gray.500 dark + Color get statusNeutralBorderDot => + _isDark ? AppColors.gray5 : AppColors.gray3; + + // ── Action / Primary ──────────────────────────────────────────────────────── + + /// action.primary.primary-bg Blue.1000 light / Blue.600 dark + Color get actionPrimaryBg => _isDark ? AppColors.blue6 : AppColors.blue10; + + /// action.primary.primary-bg-hover Blue.800 light / Blue.500 dark + Color get actionPrimaryBgHover => _isDark ? AppColors.blue5 : AppColors.blue8; + + /// action.primary.primary-text Gray.100 both modes + Color get actionPrimaryText => AppColors.gray1; + + /// action.primary.primary-disabled-bg Gray.200 light / Gray.700 dark + Color get actionPrimaryDisabledBg => + _isDark ? AppColors.gray7 : AppColors.gray2; + + /// action.primary.primary-disabled-text Gray.500 both modes + Color get actionPrimaryDisabledText => AppColors.gray5; + + /// action.primary.primary-disabled-border Gray.400 light / Gray.500 dark + Color get actionPrimaryDisabledBorder => + _isDark ? AppColors.gray5 : AppColors.gray4; + + // ── Action / Secondary ────────────────────────────────────────────────────── + + /// action.secondary.secondary-bg Gray.100 light / Gray.900 dark + Color get actionSecondaryBg => _isDark ? AppColors.gray9 : AppColors.gray1; + + /// action.secondary.secondary-bg-hover Gray.200 light / Gray.800 dark + Color get actionSecondaryBgHover => + _isDark ? AppColors.gray8 : AppColors.gray2; + + /// action.secondary.secondary-text Gray.900 light / Gray.100 dark + Color get actionSecondaryText => _isDark ? AppColors.gray1 : AppColors.gray9; + + /// action.secondary.secondary-border Gray.500 light / Gray.600 dark + Color get actionSecondaryBorder => + _isDark ? AppColors.gray6 : AppColors.gray5; + + /// action.secondary.secondary-disabled-bg Gray.200 light / Gray.900 dark + Color get actionSecondaryDisabledBg => + _isDark ? AppColors.gray9 : AppColors.gray2; + + /// action.secondary.secondary-disabled-text Gray.500 both modes + Color get actionSecondaryDisabledText => AppColors.gray5; + + /// action.secondary.secondary-disabled-border Gray.300 light / Gray.700 dark + Color get actionSecondaryDisabledBorder => + _isDark ? AppColors.gray7 : AppColors.gray3; + + // ── Action / Tertiary ─────────────────────────────────────────────────────── + + /// action.tertiary.tertiary-text Gray.900 light / Gray.100 dark + Color get actionTertiaryText => _isDark ? AppColors.gray1 : AppColors.gray9; + + /// action.tertiary.tertiary-hover-bg Gray.200 light / Gray.800 dark + Color get actionTertiaryHoverBg => + _isDark ? AppColors.gray8 : AppColors.gray2; + + /// action.tertiary.tertiary-disabled-text Gray.500 both modes + Color get actionTertiaryDisabledText => AppColors.gray5; + + // ── Action / Tonal ────────────────────────────────────────────────────────── + + /// action.tonal.tonal-bg Blue.100 light / Blue.700 dark + Color get actionTonalBg => _isDark ? AppColors.blue7 : AppColors.blue1; + + /// action.tonal.tonal-border Gray.200 light / Gray.800 dark + Color get actionTonalBorder => _isDark ? AppColors.gray8 : AppColors.gray2; + + /// action.tonal.tonal-bg-hover Blue.200 light / Blue.600 dark + Color get actionTonalBgHover => _isDark ? AppColors.blue6 : AppColors.blue2; + + /// action.tonal.tonal-text Gray.900 light / Gray.100 dark + Color get actionTonalText => _isDark ? AppColors.gray1 : AppColors.gray9; + + /// action.tonal.tonal-disabled-bg Gray.100 light / Gray.800 dark + Color get actionTonalDisabledBg => + _isDark ? AppColors.gray8 : AppColors.gray1; + + /// action.tonal.tonal-disabled-border Gray.200 light / Gray.800 dark + Color get actionTonalDisabledBorder => + _isDark ? AppColors.gray8 : AppColors.gray2; + + /// action.tonal.tonal-disabled-text Gray.400 light / Gray.500 dark + Color get actionTonalDisabledText => + _isDark ? AppColors.gray5 : AppColors.gray4; + + // ── Action / Toggle ───────────────────────────────────────────────────────── + + /// action.toggle.toggle-active-bg Green.500 light / Green.700 dark + Color get actionToggleActiveBg => + _isDark ? AppColors.green7 : AppColors.green5; + + /// action.toggle.toggle-brand-active-bg Blue.400 light / Blue.600 dark + Color get actionToggleBrandActiveBg => + _isDark ? AppColors.blue6 : AppColors.blue4; + + /// action.toggle.toggle-disabled-bg Gray.700 both modes + Color get actionToggleDisabledBg => AppColors.gray7; + + /// action.toggle.toggle-knob-bg Gray.000 light / Gray.100 dark + Color get actionToggleKnobBg => _isDark ? AppColors.gray1 : AppColors.gray0; + + /// action.toggle.toggle-border Gray.200 light / Gray.700 dark + Color get actionToggleBorder => _isDark ? AppColors.gray7 : AppColors.gray2; + + // ── Action / Tabbar ───────────────────────────────────────────────────────── + + /// action.tabbar.tabbar-bg Blue.200 light / Blue.800 dark + Color get actionTabbarBg => _isDark ? AppColors.blue8 : AppColors.blue2; + + /// action.tabbar.tabbar-border Blue.300 light / Blue.700 dark + Color get actionTabbarBorder => _isDark ? AppColors.blue7 : AppColors.blue3; + + /// action.tabbar.tabbar-selected-text Blue.1000 light / Blue.100 dark + Color get actionTabbarSelectedText => + _isDark ? AppColors.blue1 : AppColors.blue10; + + /// action.tabbar.tabbar-disabled-text Gray.600 light / Gray.200 dark + Color get actionTabbarDisabledText => + _isDark ? AppColors.gray2 : AppColors.gray6; +} diff --git a/lib/core/common/app_text_field.dart b/lib/core/common/app_text_field.dart index a94eee284a..7fa8a7683d 100644 --- a/lib/core/common/app_text_field.dart +++ b/lib/core/common/app_text_field.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:lantern/core/common/app_asset.dart'; -import 'package:lantern/core/common/app_colors.dart'; import 'package:lantern/core/common/app_dimens.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import 'package:lantern/core/common/cap_scaling.dart'; class AppTextField extends StatelessWidget { @@ -82,14 +82,14 @@ class AppTextField extends StatelessWidget { onEditingComplete: onEditingComplete, readOnly: onTap != null, onTap: onTap, - cursorColor: AppColors.blue10, + // cursorColor from textSelectionTheme autovalidateMode: autovalidateMode, validator: validator, cursorRadius: Radius.circular(16), cursorHeight: defaultSize, cursorOpacityAnimates: true, style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray9, + // text color from colorScheme.onSurface via theme fontSize: spCap(context, 14), ), textInputAction: textInputAction, @@ -100,50 +100,18 @@ class AppTextField extends StatelessWidget { required maxLength}) => counter, decoration: InputDecoration( - contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 16), + // borders, hintStyle, contentPadding come from inputDecorationTheme filled: true, - fillColor: enable ? AppColors.white : AppColors.gray3, + fillColor: enable + ? context.bgElevated // bg.input = bg.elevated + : context.bgCallout, // bg.callout for disabled hintText: hintText, - hintStyle: textTheme.bodyMedium!.copyWith( - color: AppColors.gray4, - ), - prefixIcon: prefixIcon != null ? _buildFix(prefixIcon!) : null, - suffixIcon: suffixIcon != null ? _buildFix(suffixIcon!) : null, - border: OutlineInputBorder( - borderRadius: defaultBorderRadius, - borderSide: BorderSide( - color: AppColors.gray3, - width: 1, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: defaultBorderRadius, - borderSide: BorderSide( - color: AppColors.gray3, - width: 1, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: defaultBorderRadius, - borderSide: BorderSide( - color: AppColors.blue8, - width: 2, - ), - ), - errorBorder: OutlineInputBorder( - borderRadius: defaultBorderRadius, - borderSide: BorderSide( - color: Colors.grey, - width: 1, - ), - ), - disabledBorder: OutlineInputBorder( - borderRadius: defaultBorderRadius, - borderSide: BorderSide( - color: AppColors.gray3, - width: 1, - ), - ), + prefixIcon: prefixIcon != null + ? _buildFix(prefixIcon!, iconColor: context.textPrimary) + : null, + suffixIcon: suffixIcon != null + ? _buildFix(suffixIcon!, iconColor: context.textPrimary) + : null, )); // If a label is provided, wrap the input field in a Column with a Text widget above. @@ -157,7 +125,7 @@ class AppTextField extends StatelessWidget { child: Text( label!, style: textTheme.labelLarge?.copyWith( - color: AppColors.gray8, + color: context.textSecondary, // text.secondary fontSize: spCap(context, 14), ), ), @@ -171,14 +139,14 @@ class AppTextField extends StatelessWidget { return inputField; } - Widget _buildFix(Object iconPath) { + Widget _buildFix(Object iconPath, {Color? iconColor}) { Widget? appAsset; if (iconPath is IconData) { - appAsset = Icon(iconPath, color: AppColors.yellow9); + appAsset = Icon(iconPath, color: iconColor); } else if (iconPath is String) { appAsset = AppImage( path: iconPath, - color: AppColors.yellow9, + color: iconColor, ); } else if (iconPath is Widget) { appAsset = iconPath; diff --git a/lib/core/common/app_text_styles.dart b/lib/core/common/app_text_styles.dart index 6c94e33224..ed02f41c36 100644 --- a/lib/core/common/app_text_styles.dart +++ b/lib/core/common/app_text_styles.dart @@ -9,37 +9,37 @@ class AppTextStyles { static TextStyle get displayLarge => GoogleFonts.urbanist( fontSize: 56, fontWeight: FontWeight.w700, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get displayMedium => GoogleFonts.urbanist( fontSize: 44, fontWeight: FontWeight.w700, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get displaySmall => GoogleFonts.urbanist( fontSize: 36, fontWeight: FontWeight.w700, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get headingLarge => GoogleFonts.urbanist( fontSize: 32, fontWeight: FontWeight.w600, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get headingMedium => GoogleFonts.urbanist( fontSize: 28, fontWeight: FontWeight.w600, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get headingSmall => GoogleFonts.urbanist( fontSize: 24, fontWeight: FontWeight.w600, - color: AppColors.black, + // color: AppColors.black, letterSpacing: 0, ); @@ -47,75 +47,75 @@ class AppTextStyles { fontSize: 14, fontWeight: FontWeight.w400, letterSpacing: 0, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get labelLargeBold => GoogleFonts.urbanist( fontSize: 14, fontWeight: FontWeight.bold, letterSpacing: 0, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get labelMedium => GoogleFonts.urbanist( fontSize: 12, fontWeight: FontWeight.w500, - color: AppColors.black, + // color: AppColors.black, letterSpacing: 0.0, ); static TextStyle get labelSmall => GoogleFonts.urbanist( fontSize: 10, fontWeight: FontWeight.w500, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get titleLarge => GoogleFonts.urbanist( fontSize: 22, fontWeight: FontWeight.w600, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get titleMedium => GoogleFonts.urbanist( fontSize: 16, fontWeight: FontWeight.w600, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get titleSmall => GoogleFonts.urbanist( fontSize: 14, fontWeight: FontWeight.w600, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get bodyLarge => GoogleFonts.urbanist( fontSize: 16, fontWeight: FontWeight.w400, - color: AppColors.black, + // color: AppColors.black, letterSpacing: 0); static TextStyle get bodyLargeBold => GoogleFonts.urbanist( fontSize: 16, fontWeight: FontWeight.bold, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get bodyMedium => GoogleFonts.urbanist( fontSize: 14, fontWeight: FontWeight.w400, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get bodyMediumBold => GoogleFonts.urbanist( fontSize: 14, fontWeight: FontWeight.bold, - color: AppColors.black, + // color: AppColors.black, ); static TextStyle get bodySmall => GoogleFonts.urbanist( fontSize: 12, fontWeight: FontWeight.w400, - color: AppColors.black, + // color: AppColors.black, ); //Text style for button diff --git a/lib/core/common/app_theme.dart b/lib/core/common/app_theme.dart index 34e32d7ecd..68c3bf94b5 100644 --- a/lib/core/common/app_theme.dart +++ b/lib/core/common/app_theme.dart @@ -5,16 +5,76 @@ import 'package:lantern/core/common/app_text_styles.dart'; import 'app_colors.dart'; +// ───────────────────────────────────────────────────────────────────────────── +// Figma token → ColorScheme slot reference +// +// token light dark +// ───────────────────────────────────────────────────────────────────────────── +// bg.elevated white gray850 → surface +// bg.surface gray1 gray9 → surfaceContainer +// bg.callout gray2 gray8 → surfaceContainerHighest +// bg.hover blue1 blue9 → primaryContainer +// text.primary gray9 gray2 → onSurface +// text.secondary gray8 gray3 → onSurfaceVariant +// text.link blue8(≈blue7) blue2 → primary (textButtonTheme) +// border.default gray2 gray8 → outline +// border.input gray3 gray7 → outlineVariant +// border.input-focus blue8 blue2 → primary (focused border) +// border.error red6 red5 → error +// status.error-bg red2 red8 → errorContainer +// status.error-text red8 red2 → onErrorContainer +// action.primary.bg blue10 blue6 → primary (elevatedButton) +// ───────────────────────────────────────────────────────────────────────────── + class AppTheme { + // ── Light ────────────────────────────────────────────────────────────────── + static ThemeData appTheme() { + const cs = ColorScheme.light( + // Primary action / brand + primary: AppColors.blue10, // Blue.1000 – action.primary.bg + onPrimary: AppColors.gray1, // Gray.100 – action.primary.text + primaryContainer: AppColors.blue1, // Blue.100 – bg.hover + onPrimaryContainer: AppColors.gray9, + // Secondary + secondary: AppColors.blue7, // Blue.700 + onSecondary: AppColors.gray1, + secondaryContainer: AppColors.blue2, // Blue.200 + onSecondaryContainer: AppColors.gray9, + // Success (tertiary) + tertiary: AppColors.green5, // Green.500 – toggle-active-bg + onTertiary: AppColors.gray1, + tertiaryContainer: AppColors.green2, // Green.200 – status.success-bg + onTertiaryContainer: AppColors.green8, // Green.800 – status.success-text + // Error + error: AppColors.red6, // Red.600 – border.error + onError: AppColors.gray1, + errorContainer: AppColors.red2, // Red.200 – status.error-bg + onErrorContainer: AppColors.red8, // Red.800 – status.error-text + // Surfaces + surface: AppColors.white, // White – bg.elevated (Card, Dialog, Sheet) + onSurface: AppColors.gray9, // Gray.900 – text.primary + onSurfaceVariant: AppColors.gray8, // Gray.800 – text.secondary + surfaceContainer: AppColors.gray1, // Gray.100 – bg.surface + surfaceContainerHighest: AppColors.gray2, // Gray.200 – bg.callout + // Borders + outline: AppColors.gray2, // Gray.200 – border.default + outlineVariant: AppColors.gray3, // Gray.300 – border.input + ); + return ThemeData( useMaterial3: true, + colorScheme: cs, hoverColor: AppColors.blue1, + scaffoldBackgroundColor: AppColors.gray1, // bg.surface + primaryColor: AppColors.blue10, pageTransitionsTheme: const PageTransitionsTheme( builders: { TargetPlatform.android: FadeForwardsPageTransitionsBuilder(), }, ), + + // ── Text ──────────────────────────────────────────────────────────────── textSelectionTheme: TextSelectionThemeData( cursorColor: AppColors.blue10, selectionColor: AppColors.blue6, @@ -37,6 +97,8 @@ class AppTheme { titleMedium: AppTextStyles.titleMedium, titleSmall: AppTextStyles.titleSmall, ), + + // ── AppBar ────────────────────────────────────────────────────────────── appBarTheme: AppBarTheme( centerTitle: true, surfaceTintColor: AppColors.white, @@ -45,7 +107,7 @@ class AppTheme { ), titleSpacing: 0, elevation: 0, - backgroundColor: AppColors.gray1, + backgroundColor: AppColors.gray1, // bg.surface systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: AppColors.white, statusBarBrightness: Brightness.light, @@ -53,38 +115,113 @@ class AppTheme { systemNavigationBarColor: AppColors.gray1, systemNavigationBarIconBrightness: Brightness.dark, ), - iconTheme: IconThemeData( - color: AppColors.blue10, - ), + iconTheme: IconThemeData(color: AppColors.blue10), ), - primaryColor: AppColors.blue10, - scaffoldBackgroundColor: AppColors.gray1, + + // ── Card ──────────────────────────────────────────────────────────────── cardTheme: CardThemeData( elevation: 0, margin: EdgeInsets.zero, - color: AppColors.white, + color: cs.surface, // bg.elevated clipBehavior: Clip.hardEdge, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.0), - side: BorderSide( - color: AppColors.gray2, - width: 1, - ), + side: BorderSide(color: cs.outline, width: 1), // border.default + ), + ), + + // ── Divider ───────────────────────────────────────────────────────────── + dividerTheme: DividerThemeData( + color: cs.outline, // border.default + thickness: 1, + ), + + // ── Input / TextField ──────────────────────────────────────────────────── + // Widgets using TextFormField / TextField inherit these automatically. + inputDecorationTheme: InputDecorationTheme( + filled: true, + fillColor: cs.surface, // bg.input = bg.elevated + contentPadding: const EdgeInsets.symmetric(vertical: 20, horizontal: 16), + hintStyle: TextStyle(color: AppColors.gray4), + labelStyle: TextStyle(color: cs.onSurfaceVariant), // text.secondary + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.outlineVariant), // border.input + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.outlineVariant), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: AppColors.blue8, width: 2), // border.input-focus + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.error), // border.error + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.error, width: 2), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.outlineVariant), + ), + ), + + // ── Dialog ────────────────────────────────────────────────────────────── + dialogTheme: DialogThemeData( + backgroundColor: cs.surface, // bg.elevated + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + side: BorderSide(color: cs.outlineVariant, width: 1), + ), + titleTextStyle: AppTextStyles.headingSmall, + contentTextStyle: AppTextStyles.bodyMedium, + ), + + // ── Bottom Sheet ───────────────────────────────────────────────────────── + bottomSheetTheme: BottomSheetThemeData( + backgroundColor: cs.surface, // bg.elevated + modalBackgroundColor: cs.surface, + dragHandleColor: AppColors.gray4, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), ), + + // ── ListTile (used by AppTile) ─────────────────────────────────────────── + listTileTheme: ListTileThemeData( + textColor: cs.onSurface, // text.primary + iconColor: cs.onSurface, + selectedColor: cs.primary, + selectedTileColor: cs.primaryContainer, // bg.hover + ), + + // ── TextButton (used by AppTextButton) ─────────────────────────────────── + textButtonTheme: TextButtonThemeData( + style: TextButton.styleFrom( + foregroundColor: AppColors.blue7, // text.link light + ), + ), + + // ── Radio ─────────────────────────────────────────────────────────────── radioTheme: RadioThemeData( - fillColor: WidgetStatePropertyAll(AppColors.gray9), + fillColor: WidgetStatePropertyAll(cs.onSurface), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, splashRadius: 10.0, ), + + // ── ElevatedButton (PrimaryButton) ─────────────────────────────────────── elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( elevation: 0, - backgroundColor: AppColors.blue10, + backgroundColor: cs.primary, // action.primary.primary-bg enableFeedback: true, - foregroundColor: AppColors.gray1, + foregroundColor: cs.onPrimary, // action.primary.primary-text textStyle: AppTextStyles.primaryButtonTextStyle - .copyWith(fontSize: 18.0, color: AppColors.gray1), + .copyWith(fontSize: 18.0, color: cs.onPrimary), overlayColor: AppColors.blue6, minimumSize: const Size(double.infinity, 52), tapTargetSize: MaterialTapTargetSize.padded, @@ -97,7 +234,212 @@ class AppTheme { ); } + // ── Dark ─────────────────────────────────────────────────────────────────── + static ThemeData darkTheme() { - return ThemeData(); + const cs = ColorScheme.dark( + // Primary action / brand + primary: AppColors.blue6, // Blue.600 – action.primary.bg + onPrimary: AppColors.gray1, // Gray.100 – action.primary.text + primaryContainer: AppColors.blue9, // Blue.900 – bg.hover + onPrimaryContainer: AppColors.gray2, + // Secondary + secondary: AppColors.blue5, // Blue.500 + onSecondary: AppColors.gray1, + secondaryContainer: AppColors.blue7, // Blue.700 + onSecondaryContainer: AppColors.gray2, + // Success (tertiary) + tertiary: AppColors.green7, // Green.700 – toggle-active-bg dark + onTertiary: AppColors.gray1, + tertiaryContainer: AppColors.green7, + onTertiaryContainer: AppColors.green3, // Green.300 – status.success-text dark + // Error + error: AppColors.red5, // Red.500 – border.error dark + onError: AppColors.gray1, + errorContainer: AppColors.red8, // Red.800 – status.error-bg dark + onErrorContainer: AppColors.red2, // Red.200 – status.error-text dark + // Surfaces + surface: AppColors.gray850, // Gray.850 – bg.elevated (Card, Dialog, Sheet) + onSurface: AppColors.gray2, // Gray.200 – text.primary dark + onSurfaceVariant: AppColors.gray3, // Gray.300 – text.secondary dark + surfaceContainer: AppColors.gray9, // Gray.900 – bg.surface dark + surfaceContainerHighest: AppColors.gray8, // Gray.800 – bg.callout dark + // Borders + outline: AppColors.gray8, // Gray.800 – border.default dark + outlineVariant: AppColors.gray7, // Gray.700 – border.input dark + ); + + return ThemeData( + useMaterial3: true, + brightness: Brightness.dark, + colorScheme: cs, + hoverColor: AppColors.blue9, + scaffoldBackgroundColor: AppColors.gray9, // bg.surface dark + primaryColor: AppColors.blue6, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: FadeForwardsPageTransitionsBuilder(), + }, + ), + + // ── Text ──────────────────────────────────────────────────────────────── + textSelectionTheme: TextSelectionThemeData( + cursorColor: AppColors.blue6, + selectionColor: AppColors.blue7, + selectionHandleColor: AppColors.blue5, + ), + textTheme: GoogleFonts.urbanistTextTheme( + ThemeData(brightness: Brightness.dark).textTheme, + ).copyWith( + bodyLarge: AppTextStyles.bodyLarge, + bodyMedium: AppTextStyles.bodyMedium, + bodySmall: AppTextStyles.bodySmall, + displayLarge: AppTextStyles.displayLarge, + displayMedium: AppTextStyles.displayMedium, + displaySmall: AppTextStyles.displaySmall, + headlineLarge: AppTextStyles.headingLarge, + headlineMedium: AppTextStyles.headingMedium, + headlineSmall: AppTextStyles.headingSmall, + labelLarge: AppTextStyles.labelLarge, + labelMedium: AppTextStyles.labelMedium, + labelSmall: AppTextStyles.labelSmall, + titleLarge: AppTextStyles.titleLarge, + titleMedium: AppTextStyles.titleMedium, + titleSmall: AppTextStyles.titleSmall, + ), + + // ── AppBar ────────────────────────────────────────────────────────────── + appBarTheme: AppBarTheme( + centerTitle: true, + surfaceTintColor: AppColors.gray850, + titleTextStyle: AppTextStyles.headingSmall.copyWith( + color: cs.onSurface, // text.primary dark + ), + titleSpacing: 0, + elevation: 0, + backgroundColor: AppColors.gray9, // bg.surface dark + systemOverlayStyle: SystemUiOverlayStyle( + statusBarColor: AppColors.gray9, + statusBarBrightness: Brightness.dark, + statusBarIconBrightness: Brightness.light, + systemNavigationBarColor: AppColors.gray9, + systemNavigationBarIconBrightness: Brightness.light, + ), + iconTheme: IconThemeData(color: cs.onSurface), + ), + + // ── Card ──────────────────────────────────────────────────────────────── + cardTheme: CardThemeData( + elevation: 0, + margin: EdgeInsets.zero, + color: cs.surface, // bg.elevated dark + clipBehavior: Clip.hardEdge, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + side: BorderSide(color: cs.outline, width: 1), // border.default dark + ), + ), + + // ── Divider ───────────────────────────────────────────────────────────── + dividerTheme: DividerThemeData( + color: cs.outline, // border.default dark + thickness: 1, + ), + + // ── Input / TextField ──────────────────────────────────────────────────── + inputDecorationTheme: InputDecorationTheme( + filled: true, + fillColor: cs.surface, // bg.input dark (gray850) + contentPadding: const EdgeInsets.symmetric(vertical: 20, horizontal: 16), + hintStyle: TextStyle(color: AppColors.gray5), // text.disabled dark + labelStyle: TextStyle(color: cs.onSurfaceVariant), // text.secondary dark + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.outlineVariant), // border.input dark + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.outlineVariant), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: AppColors.blue2, width: 2), // border.input-focus dark + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.error), // border.error dark + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.error, width: 2), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(16), + borderSide: BorderSide(color: cs.outlineVariant), + ), + ), + + // ── Dialog ────────────────────────────────────────────────────────────── + dialogTheme: DialogThemeData( + backgroundColor: cs.surface, // bg.elevated dark + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + side: BorderSide(color: cs.outlineVariant, width: 1), + ), + titleTextStyle: AppTextStyles.headingSmall, + contentTextStyle: AppTextStyles.bodyMedium, + ), + + // ── Bottom Sheet ───────────────────────────────────────────────────────── + bottomSheetTheme: BottomSheetThemeData( + backgroundColor: cs.surface, // bg.elevated dark + modalBackgroundColor: cs.surface, + dragHandleColor: AppColors.gray6, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + ), + + // ── ListTile (used by AppTile) ─────────────────────────────────────────── + listTileTheme: ListTileThemeData( + textColor: cs.onSurface, // text.primary dark + iconColor: cs.onSurface, + selectedColor: cs.primary, + selectedTileColor: cs.primaryContainer, // bg.hover dark + ), + + // ── TextButton (used by AppTextButton) ─────────────────────────────────── + textButtonTheme: TextButtonThemeData( + style: TextButton.styleFrom( + foregroundColor: AppColors.blue2, // text.link dark + ), + ), + + // ── Radio ─────────────────────────────────────────────────────────────── + radioTheme: RadioThemeData( + fillColor: WidgetStatePropertyAll(cs.onSurface), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + splashRadius: 10.0, + ), + + // ── ElevatedButton (PrimaryButton) ─────────────────────────────────────── + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + elevation: 0, + backgroundColor: cs.primary, // action.primary.primary-bg dark + enableFeedback: true, + foregroundColor: cs.onPrimary, // action.primary.primary-text + textStyle: AppTextStyles.primaryButtonTextStyle + .copyWith(fontSize: 18.0, color: cs.onPrimary), + overlayColor: AppColors.blue5, // action.primary.primary-bg-hover dark + minimumSize: const Size(double.infinity, 52), + tapTargetSize: MaterialTapTargetSize.padded, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(32.0), + side: BorderSide.none, + ), + ), + ), + ); } } diff --git a/lib/core/common/common.dart b/lib/core/common/common.dart index 675893e93a..67c3b1d8df 100644 --- a/lib/core/common/common.dart +++ b/lib/core/common/common.dart @@ -26,6 +26,7 @@ import '../utils/store_utils.dart'; export 'package:lantern/core/common/app_asset.dart'; export 'package:lantern/core/common/app_buttons.dart'; export 'package:lantern/core/common/app_colors.dart'; +export 'package:lantern/core/common/app_semantic_colors.dart'; export 'package:lantern/core/common/app_dialog.dart'; export 'package:lantern/core/common/app_dimens.dart'; export 'package:lantern/core/common/app_eum.dart'; diff --git a/lib/core/extensions/context.dart b/lib/core/extensions/context.dart index 3a0512bc57..946b27a86e 100644 --- a/lib/core/extensions/context.dart +++ b/lib/core/extensions/context.dart @@ -1,6 +1,6 @@ // Extension for showing error SnackBars. import 'package:flutter/material.dart'; -import 'package:lantern/core/common/app_colors.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import 'package:loader_overlay/loader_overlay.dart'; import '../common/app_dimens.dart' show defaultPadding; @@ -15,13 +15,13 @@ extension SnackBarExtensions on BuildContext { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), - backgroundColor: AppColors.red7, + backgroundColor: bgSnackbarError, showCloseIcon: closeButton, - closeIconColor: AppColors.white, + closeIconColor: textInverse, content: Text( message, style: textTheme!.copyWith( - color: AppColors.white, + color: textInverse, ), ), duration: Duration(seconds: 5), @@ -38,13 +38,13 @@ extension SnackBarExtensions on BuildContext { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), - backgroundColor: AppColors.blue9, + backgroundColor: bgSnackbar, showCloseIcon: closeButton, - closeIconColor: AppColors.white, + closeIconColor: textInverse, content: Text( message, style: textTheme!.copyWith( - color: AppColors.white, + color: textInverse, ), ), duration: Duration(seconds: 5), diff --git a/lib/core/utils/decoration.dart b/lib/core/utils/decoration.dart index c3e778f5c6..29d1c0d426 100644 --- a/lib/core/utils/decoration.dart +++ b/lib/core/utils/decoration.dart @@ -1,18 +1,3 @@ import 'package:flutter/material.dart'; import 'package:lantern/core/common/app_colors.dart'; -BoxDecoration get selectedDecoration { - return BoxDecoration( - color: AppColors.blue1, - border: Border.all(color: AppColors.blue7, width: 3), - borderRadius: BorderRadius.circular(16), - ); -} - -BoxDecoration get unselectedDecoration { - return BoxDecoration( - color: AppColors.white, - border: Border.all(color: AppColors.gray3, width: 1.5), - borderRadius: BorderRadius.circular(16), - ); -} diff --git a/lib/core/utils/pro_utils.dart b/lib/core/utils/pro_utils.dart index 6116f25bec..b382f3741b 100644 --- a/lib/core/utils/pro_utils.dart +++ b/lib/core/utils/pro_utils.dart @@ -23,7 +23,7 @@ Future showProAccountFlowDialog({ ? 'set_account_password_message'.i18n : 'update_pro_account_message'.i18n, style: Theme.of(context).textTheme.bodySmall!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ], @@ -31,7 +31,7 @@ Future showProAccountFlowDialog({ action: [ AppTextButton( label: 'cancel'.i18n, - textColor: AppColors.gray6, + textColor: context.textDisabled, onPressed: () => appRouter.maybePop(), ), AppTextButton( diff --git a/lib/core/widgets/app_pin_field.dart b/lib/core/widgets/app_pin_field.dart index 85b1a272c4..0ee735c43b 100644 --- a/lib/core/widgets/app_pin_field.dart +++ b/lib/core/widgets/app_pin_field.dart @@ -21,8 +21,8 @@ class AppPinField extends StatelessWidget { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), decoration: BoxDecoration( - color: AppColors.white, - border: Border.all(color: AppColors.gray3), + color: context.bgElevated, + border: Border.all(color: context.borderInput), borderRadius: BorderRadius.circular(16), ), child: Row( @@ -71,14 +71,14 @@ class AppPinField extends StatelessWidget { Container( width: 2, height: 20, - color: AppColors.gray4, + color: context.textDisabled, ), ], ), preFilledWidget: Container( width: 15, height: 1, - color: AppColors.gray4, + color: context.textDisabled, ), defaultPinTheme: PinTheme( width: 20, diff --git a/lib/core/widgets/app_rich_text.dart b/lib/core/widgets/app_rich_text.dart index 3a565b6f0a..7563d9819e 100644 --- a/lib/core/widgets/app_rich_text.dart +++ b/lib/core/widgets/app_rich_text.dart @@ -1,6 +1,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:lantern/core/common/app_buttons.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import '../common/app_colors.dart'; import '../common/app_text_styles.dart'; @@ -29,14 +30,14 @@ class AppRichText extends StatelessWidget { text: TextSpan( text: texts, style: textTheme.labelLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), children: [ TextSpan( text: boldTexts, style: AppTextStyles.labelLargeBold.copyWith( fontWeight: FontWeight.bold, - color: boldColor ?? AppColors.gray8, + color: boldColor ?? context.textSecondary, decoration: boldUnderline ? TextDecoration.underline : TextDecoration.none, diff --git a/lib/core/widgets/app_text.dart b/lib/core/widgets/app_text.dart index e2ed5276a1..06ae3f62e1 100644 --- a/lib/core/widgets/app_text.dart +++ b/lib/core/widgets/app_text.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:lantern/core/common/common.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; class HeaderText extends StatelessWidget { final String text; @@ -26,7 +26,9 @@ class HeaderText extends StatelessWidget { final textTheme = Theme.of(context).textTheme; return Text( text, - style: textTheme.labelLarge?.copyWith(color: AppColors.gray8), + style: textTheme.labelLarge?.copyWith( + color: color ?? context.textSecondary, + ), textAlign: textAlign, maxLines: maxLines, overflow: overflow, diff --git a/lib/core/widgets/app_tile.dart b/lib/core/widgets/app_tile.dart index 9c490e426b..d1c5a2ef24 100644 --- a/lib/core/widgets/app_tile.dart +++ b/lib/core/widgets/app_tile.dart @@ -92,7 +92,9 @@ class AppTile extends StatelessWidget { final textStyle = tileTextStyle ?? theme.textTheme.labelLarge!.copyWith( - color: enabled ? AppColors.gray9 : AppColors.gray6, + color: enabled + ? context.textPrimary // text.primary + : context.textPrimary.withValues(alpha: 0.38), // text.disabled fontWeight: FontWeight.w400, fontSize: 16, ); @@ -106,8 +108,11 @@ class AppTile extends StatelessWidget { child: AppImage(path: icon as String), ); } else if (icon is IconData) { - computedLeading = - Icon(icon as IconData, size: 24, color: AppColors.gray9); + computedLeading = Icon( + icon as IconData, + size: 24, + color: context.textPrimary, // text.primary + ); } else if (icon is Image) { computedLeading = icon as Image; } else if (icon is Widget) { @@ -128,8 +133,10 @@ class AppTile extends StatelessWidget { selected: selected, titleAlignment: titleAlignment??ListTileTitleAlignment.center, enableFeedback: true, - hoverColor: hoverColor ?? AppColors.blue1, - selectedTileColor: selectedTileColor ?? AppColors.blue1, + // hoverColor: hoverColor ?? AppColors.blue1, + hoverColor: hoverColor ?? theme.hoverColor, + // selectedTileColor: selectedTileColor ?? AppColors.blue1, + selectedTileColor: selectedTileColor ?? theme.hoverColor, tileColor: tileColor, minTileHeight: minHeight ?? effectiveMinHeight, shape: RoundedRectangleBorder( diff --git a/lib/core/widgets/app_webview.dart b/lib/core/widgets/app_webview.dart index 1b41bc2d0f..919e358db2 100644 --- a/lib/core/widgets/app_webview.dart +++ b/lib/core/widgets/app_webview.dart @@ -33,8 +33,8 @@ class AppWebView extends HookConsumerWidget { title: Text(title), centerTitle: true, leading: SizedBox(), - backgroundColor: AppColors.white, - iconTheme: IconThemeData(color: AppColors.black), + backgroundColor: context.bgElevated, + iconTheme: IconThemeData(color: context.textPrimary), actions: [ IconButton( icon: const Icon(Icons.close), diff --git a/lib/core/widgets/base_screen.dart b/lib/core/widgets/base_screen.dart index 753c576db2..23df336502 100644 --- a/lib/core/widgets/base_screen.dart +++ b/lib/core/widgets/base_screen.dart @@ -27,7 +27,8 @@ class BaseScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: backgroundColor ?? AppColors.gray1, + backgroundColor: backgroundColor ?? Theme.of(context).scaffoldBackgroundColor, + // backgroundColor: backgroundColor ?? AppColors.gray1, appBar: appBar ?? CustomAppBar( title: Text(title), diff --git a/lib/core/widgets/bottomsheet.dart b/lib/core/widgets/bottomsheet.dart index 2c4b19d51e..48f83d020f 100644 --- a/lib/core/widgets/bottomsheet.dart +++ b/lib/core/widgets/bottomsheet.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:lantern/core/common/app_colors.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import 'package:lantern/core/widgets/divider_space.dart'; typedef BottomSheetBuilder = Function( @@ -10,13 +10,12 @@ void showAppBottomSheet( required BottomSheetBuilder builder, required String title, double scrollControlDisabledMaxHeightRatio = .75}) { - final textTheme = Theme.of(context).textTheme.headlineSmall; + // backgroundColor and shape come from bottomSheetTheme in app_theme.dart showModalBottomSheet( context: context, isDismissible: true, enableDrag: true, showDragHandle: true, - backgroundColor: AppColors.white, scrollControlDisabledMaxHeightRatio: scrollControlDisabledMaxHeightRatio, builder: (context) { return DraggableScrollableSheet( @@ -32,14 +31,12 @@ void showAppBottomSheet( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( title, - style: textTheme!.copyWith( - color: AppColors.blue10, + style: Theme.of(context).textTheme.headlineSmall!.copyWith( + color: context.textPrimary, ), ), ), - DividerSpace( - padding: EdgeInsets.only(top: 16), - ), + DividerSpace(padding: EdgeInsets.only(top: 16)), builder(context, scrollController), ], ); diff --git a/lib/core/widgets/card_dropdown.dart b/lib/core/widgets/card_dropdown.dart index 8245fb44d0..9f20cb69d6 100644 --- a/lib/core/widgets/card_dropdown.dart +++ b/lib/core/widgets/card_dropdown.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:lantern/core/common/app_asset.dart'; import 'package:lantern/core/common/app_colors.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import 'package:lantern/core/common/app_text_styles.dart'; class CardDropdown extends StatelessWidget { @@ -23,18 +24,18 @@ class CardDropdown extends StatelessWidget { this.enabled = true, }); - Widget? _buildPrefix(Object? iconPath) { + Widget? _buildPrefix(Object? iconPath, BuildContext context) { if (iconPath == null) return null; const pad = EdgeInsets.only(left: 16, right: 16); if (iconPath is IconData) { return Padding( padding: pad, - child: Icon(iconPath, color: AppColors.yellow9), + child: Icon(iconPath, color: context.textPromoIcon), ); } else if (iconPath is String) { return Padding( padding: pad, - child: AppImage(path: iconPath, color: AppColors.yellow9), + child: AppImage(path: iconPath, color: context.textPromoIcon), ); } else if (iconPath is Widget) { return Padding(padding: pad, child: iconPath); @@ -50,20 +51,20 @@ class CardDropdown extends StatelessWidget { onChanged: enabled ? onChanged : null, validator: validator, decoration: InputDecoration( - prefixIcon: _buildPrefix(prefixIcon), + prefixIcon: _buildPrefix(prefixIcon, context), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), filled: true, - fillColor: enabled ? AppColors.white : AppColors.gray3.withOpacity(0.3), + fillColor: enabled ? context.bgElevated : context.borderInput.withOpacity(0.3), hintText: hintText, - hintStyle: AppTextStyles.bodyMedium.copyWith(color: AppColors.gray4), + hintStyle: AppTextStyles.bodyMedium.copyWith(color: context.textDisabled), border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: BorderSide(color: AppColors.gray3, width: 1), + borderSide: BorderSide(color: context.borderInput, width: 1), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: BorderSide(color: AppColors.gray3, width: 1), + borderSide: BorderSide(color: context.borderInput, width: 1), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), @@ -71,16 +72,16 @@ class CardDropdown extends StatelessWidget { ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), - borderSide: BorderSide(color: AppColors.red5, width: 1.2), + borderSide: BorderSide(color: context.statusErrorBorder, width: 1.2), ), disabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: - BorderSide(color: AppColors.gray3.withOpacity(0.5), width: 1), + BorderSide(color: context.borderInput.withOpacity(0.5), width: 1), ), ), style: AppTextStyles.bodyMedium.copyWith( - color: enabled ? AppColors.black1 : AppColors.gray4, + color: enabled ? context.textPrimary : context.textDisabled, ), icon: const Icon(Icons.keyboard_arrow_down_rounded, color: null), // uses default IconTheme diff --git a/lib/core/widgets/divider_space.dart b/lib/core/widgets/divider_space.dart index 1a8572c181..b38ebb3787 100644 --- a/lib/core/widgets/divider_space.dart +++ b/lib/core/widgets/divider_space.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; -import '../common/app_colors.dart'; - class DividerSpace extends StatelessWidget { final EdgeInsetsGeometry padding; @@ -15,7 +13,9 @@ class DividerSpace extends StatelessWidget { return Padding( padding: padding, child: Divider( - color: AppColors.gray2, + // border.default: Gray.200 light / Gray.800 dark + // color: AppColors.gray2, + color: Theme.of(context).dividerTheme.color, height: 1, ), ); diff --git a/lib/core/widgets/email_tag.dart b/lib/core/widgets/email_tag.dart index 09526deb27..9185059974 100644 --- a/lib/core/widgets/email_tag.dart +++ b/lib/core/widgets/email_tag.dart @@ -27,7 +27,7 @@ class EmailTag extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(100), side: BorderSide( - color: AppColors.gray3, + color: context.borderInput, width: 1, ), ), diff --git a/lib/core/widgets/flag.dart b/lib/core/widgets/flag.dart index be03441105..c096b766d7 100644 --- a/lib/core/widgets/flag.dart +++ b/lib/core/widgets/flag.dart @@ -1,7 +1,6 @@ import 'package:country_flags/country_flags.dart'; import 'package:flutter/material.dart'; - -import '../common/app_colors.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; class Flag extends StatelessWidget { final String countryCode; @@ -14,7 +13,7 @@ class Flag extends StatelessWidget { Widget build(BuildContext context) { return Container( decoration: BoxDecoration( - border: Border.all(color: AppColors.gray3, width: .5), + border: Border.all(color: context.borderInput, width: .5), ), child: SizedBox.fromSize( size: size, diff --git a/lib/core/widgets/info_row.dart b/lib/core/widgets/info_row.dart index c77fb407bb..65ea012a9f 100644 --- a/lib/core/widgets/info_row.dart +++ b/lib/core/widgets/info_row.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:lantern/core/common/app_asset.dart'; -import 'package:lantern/core/common/app_colors.dart'; import 'package:lantern/core/common/app_image_paths.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; class InfoRow extends StatelessWidget { final Widget? icon; @@ -44,7 +44,7 @@ class InfoRow extends StatelessWidget { padding ?? EdgeInsets.symmetric(horizontal: 16, vertical: 4), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(borderRadius), - side: BorderSide(color: borderColor ?? AppColors.gray2), + side: BorderSide(color: borderColor ?? context.borderDefault), ), leading: showLeadingIcon ? AppImage( @@ -56,7 +56,7 @@ class InfoRow extends StatelessWidget { text, style: textStyle ?? (textTheme.bodyMedium)!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), )); } diff --git a/lib/core/widgets/labeled_card_dropdown.dart b/lib/core/widgets/labeled_card_dropdown.dart index 255e22e665..a6e0119621 100644 --- a/lib/core/widgets/labeled_card_dropdown.dart +++ b/lib/core/widgets/labeled_card_dropdown.dart @@ -28,7 +28,7 @@ class LabeledCardDropdownWithFlag extends StatelessWidget { decoration: BoxDecoration( color: finalizeCardColor, borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.gray2, width: 1), + border: Border.all(color: context.borderDefault, width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -46,7 +46,7 @@ class LabeledCardDropdownWithFlag extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 4), decoration: BoxDecoration( border: Border.all( - color: AppColors.gray2, + color: context.borderDefault, width: 1, ), borderRadius: BorderRadius.circular(12), @@ -68,7 +68,7 @@ class LabeledCardDropdownWithFlag extends StatelessWidget { Text( countryLabelKey.i18n, style: AppTextStyles.bodyLarge.copyWith( - color: AppColors.black1, + color: context.textPrimary, height: 1.62, ), ), diff --git a/lib/core/widgets/labeled_card_input.dart b/lib/core/widgets/labeled_card_input.dart index bd6002cf68..93b580bd1b 100644 --- a/lib/core/widgets/labeled_card_input.dart +++ b/lib/core/widgets/labeled_card_input.dart @@ -39,7 +39,7 @@ class LabeledCardInput extends StatelessWidget { color: cardColor, borderRadius: BorderRadius.circular(16), border: Border.all( - color: AppColors.gray2, + color: context.borderDefault, width: 1, ), ), diff --git a/lib/core/widgets/password_criteria.dart b/lib/core/widgets/password_criteria.dart index 514f5fb531..4ffb98b726 100644 --- a/lib/core/widgets/password_criteria.dart +++ b/lib/core/widgets/password_criteria.dart @@ -50,10 +50,10 @@ class _PasswordCriteriaWidgetState extends State { return Container( padding: const EdgeInsets.all(12.0), decoration: BoxDecoration( - color: AppColors.white, + color: context.bgElevated, borderRadius: BorderRadius.circular(16.0), border: Border.all( - color: AppColors.gray3, + color: context.borderInput, width: .5, ), ), @@ -84,7 +84,7 @@ class _PasswordCriteriaWidgetState extends State { children: [ Icon( metCriteria ? Icons.check_circle : Icons.radio_button_unchecked, - color: metCriteria ? AppColors.green6 : Colors.grey, + color: metCriteria ? context.statusSuccessBorder : Colors.grey, size: 18, ), const SizedBox(width: 8), @@ -92,7 +92,7 @@ class _PasswordCriteriaWidgetState extends State { criteria, style: textTheme!.labelMedium!.copyWith( fontSize: 14, - color: AppColors.gray9, + color: context.textPrimary, ), ), ], diff --git a/lib/core/widgets/platform_card.dart b/lib/core/widgets/platform_card.dart index 8dba25820e..a3ce1164b5 100644 --- a/lib/core/widgets/platform_card.dart +++ b/lib/core/widgets/platform_card.dart @@ -17,10 +17,10 @@ class PlatformCard extends StatelessWidget { onPressed: onPressed, style: IconButton.styleFrom( padding: EdgeInsets.all(15.r), - backgroundColor: AppColors.white, + backgroundColor: context.bgElevated, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), - side: BorderSide(color: AppColors.gray3, width: .5), + side: BorderSide(color: context.borderInput, width: .5), )), icon: AppImage( fit: BoxFit.contain, diff --git a/lib/core/widgets/pro_banner.dart b/lib/core/widgets/pro_banner.dart index 3ce6a2eea2..24c572f31a 100644 --- a/lib/core/widgets/pro_banner.dart +++ b/lib/core/widgets/pro_banner.dart @@ -23,9 +23,9 @@ class ProBanner extends HookConsumerWidget { margin: EdgeInsets.only(top: topMargin), padding: EdgeInsets.all(defaultSize), decoration: BoxDecoration( - color: AppColors.yellow1, + color: context.bgPromo, borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.yellow4, width: 1)), + border: Border.all(color: context.borderPromo, width: 1)), child: Column( children: [ AutoSizeText( @@ -37,7 +37,7 @@ class ProBanner extends HookConsumerWidget { maxFontSize: 16, overflow: TextOverflow.ellipsis, style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray9, + color: context.textPrimary, fontSize: 16, ), ), diff --git a/lib/core/widgets/search_bar.dart b/lib/core/widgets/search_bar.dart index 021a1a65e4..d9b86861c9 100644 --- a/lib/core/widgets/search_bar.dart +++ b/lib/core/widgets/search_bar.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:lantern/core/common/app_asset.dart'; -import 'package:lantern/core/common/app_colors.dart'; import 'package:lantern/core/common/app_image_paths.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import 'package:lantern/features/split_tunneling/provider/search_query.dart'; class AppSearchBar extends AppBar { @@ -64,7 +64,7 @@ class _SearchBarContent extends HookConsumerWidget { decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle( - color: AppColors.gray7, + color: context.textSecondary, fontSize: 16, fontWeight: FontWeight.w400, ), @@ -75,7 +75,7 @@ class _SearchBarContent extends HookConsumerWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, - color: AppColors.gray9, + color: context.textPrimary, ), ) : Text( @@ -83,7 +83,7 @@ class _SearchBarContent extends HookConsumerWidget { style: TextStyle( fontSize: 24, fontWeight: FontWeight.w600, - color: AppColors.gray9, + color: context.textPrimary, ), ), ), diff --git a/lib/core/widgets/section_label.dart b/lib/core/widgets/section_label.dart index c8f76fa91e..e794553525 100644 --- a/lib/core/widgets/section_label.dart +++ b/lib/core/widgets/section_label.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:lantern/core/common/app_colors.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; class SectionLabel extends StatelessWidget { final String title; @@ -13,7 +13,7 @@ class SectionLabel extends StatelessWidget { child: Text( title, style: Theme.of(context).textTheme.labelLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, fontSize: 14, fontWeight: FontWeight.w500, ), diff --git a/lib/core/widgets/setting_tile.dart b/lib/core/widgets/setting_tile.dart index bf158e6289..31900b4553 100644 --- a/lib/core/widgets/setting_tile.dart +++ b/lib/core/widgets/setting_tile.dart @@ -1,7 +1,9 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; -import '../common/common.dart'; +import '../common/app_asset.dart'; +import '../common/app_semantic_colors.dart'; +import '../extensions/string.dart'; class SettingTile extends StatelessWidget { final String label; @@ -29,7 +31,7 @@ class SettingTile extends StatelessWidget { return InkWell( borderRadius: BorderRadius.circular(16), onTap: onTap, - splashColor: AppColors.gray2, + splashColor: context.bgCallout, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), child: Column( @@ -43,9 +45,11 @@ class SettingTile extends StatelessWidget { child: icon is String ? AppImage(path: icon) : icon as Widget, ), SizedBox(width: 8), - Text(label, - style: - textTheme.labelLarge!.copyWith(color: AppColors.gray7)), + Text( + label, + style: textTheme.labelLarge! + .copyWith(color: context.textSecondary), + ), ], ), Row( @@ -55,12 +59,14 @@ class SettingTile extends StatelessWidget { Expanded(child: child!) else Expanded( - child: AutoSizeText(value, - maxLines: 1, - maxFontSize: 16, - minFontSize: 14, - style: textTheme.titleMedium! - .copyWith(color: AppColors.gray9)), + child: AutoSizeText( + value, + maxLines: 1, + maxFontSize: 16, + minFontSize: 14, + style: textTheme.titleMedium! + .copyWith(color: context.textPrimary), + ), ), ...actions ], @@ -68,9 +74,11 @@ class SettingTile extends StatelessWidget { if (subtitle != null && subtitle!.isNotEmpty) Padding( padding: const EdgeInsets.only(left: 32.0), - child: Text(subtitle!.capitalize, - style: - textTheme.labelLarge!.copyWith(color: AppColors.gray7)), + child: Text( + subtitle!.capitalize, + style: textTheme.labelLarge! + .copyWith(color: context.textSecondary), + ), ), ], ), diff --git a/lib/core/widgets/split_tunneling_tile.dart b/lib/core/widgets/split_tunneling_tile.dart index c4ebca827e..a57f0be084 100644 --- a/lib/core/widgets/split_tunneling_tile.dart +++ b/lib/core/widgets/split_tunneling_tile.dart @@ -27,7 +27,7 @@ class SplitTunnelingTile extends StatelessWidget { ? Text( subtitle!, style: AppTextStyles.labelMedium.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ) : null, diff --git a/lib/core/widgets/switch_button.dart b/lib/core/widgets/switch_button.dart index d391f111d3..56dc6a0771 100644 --- a/lib/core/widgets/switch_button.dart +++ b/lib/core/widgets/switch_button.dart @@ -30,26 +30,34 @@ class SwitchButton extends StatelessWidget { spacing: 10.h, height: PlatformUtils.isDesktop ? 40.h : 30.h, wrapperBuilder: (context, global, child) { + final isDark = Theme.of(context).brightness == Brightness.dark; return Container( width: trackWidth, padding: const EdgeInsets.symmetric(horizontal: 5), decoration: BoxDecoration( - color: value ? (activeColor ?? AppColors.green5) : AppColors.gray7, + // toggle-active-bg: Green.500 light / Green.700 dark + // toggle-disabled-bg (off state): Gray.700 both + color: value + ? (activeColor ?? + (isDark ? AppColors.green7 : AppColors.green5)) + : AppColors.gray7, borderRadius: BorderRadius.circular(100), ), child: child, ); }, foregroundIndicatorBuilder: (context, global) { + final isDark = Theme.of(context).brightness == Brightness.dark; return GestureDetector( onTap: () { onChanged(value ? false : true); }, child: Container( - decoration: const BoxDecoration( - color: Colors.white, + decoration: BoxDecoration( + // toggle-knob-bg: White light / Gray.100 dark + color: isDark ? AppColors.gray1 : Colors.white, shape: BoxShape.circle, - boxShadow: [ + boxShadow: const [ BoxShadow( color: Colors.black12, blurRadius: 4, diff --git a/lib/features/account/account.dart b/lib/features/account/account.dart index f3562ec162..30f0d434c3 100644 --- a/lib/features/account/account.dart +++ b/lib/features/account/account.dart @@ -41,7 +41,7 @@ class Account extends HookConsumerWidget { backgroundColor: AppColors.red1, borderColor: AppColors.red2, textStyle: theme.labelLarge!.copyWith( - color: AppColors.red9, + color: buildContext.statusErrorBg, ), text: 'pro_subscription_expired_message'.i18n, ), @@ -59,7 +59,7 @@ class Account extends HookConsumerWidget { child: Text( 'lantern_pro_email'.i18n, style: theme.labelLarge!.copyWith( - color: AppColors.gray8, + color: buildContext.textSecondary, ), ), ), @@ -90,7 +90,7 @@ class Account extends HookConsumerWidget { child: Text( 'last_subscription_renewal_date'.i18n, style: theme.labelLarge!.copyWith( - color: AppColors.gray8, + color: buildContext.textSecondary, ), ), ) @@ -102,7 +102,7 @@ class Account extends HookConsumerWidget { ? 'subscription_renewal_date'.i18n : 'pro_account_expiration'.i18n, style: theme.labelLarge!.copyWith( - color: AppColors.gray8, + color: buildContext.textSecondary, ), ), ), @@ -120,7 +120,7 @@ class Account extends HookConsumerWidget { child: Text( 'lantern_pro_devices'.i18n, style: theme.labelLarge!.copyWith( - color: AppColors.gray8, + color: buildContext.textSecondary, ), ), ), @@ -140,7 +140,7 @@ class Account extends HookConsumerWidget { child: Text( 'danger_zone'.i18n, style: theme.labelLarge!.copyWith( - color: AppColors.gray8, + color: buildContext.textSecondary, ), ), ), @@ -151,7 +151,7 @@ class Account extends HookConsumerWidget { label: 'delete_account'.i18n, trailing: AppTextButton( label: 'delete'.i18n, - textColor: AppColors.red7, + textColor: buildContext.statusErrorBg, onPressed: _onDeleteTap, ), ), @@ -337,7 +337,7 @@ class Account extends HookConsumerWidget { action: [ AppTextButton( label: 'not_now'.i18n, - textColor: AppColors.gray8, + textColor: context.textSecondary, onPressed: () { appRouter.pop(); }, @@ -362,7 +362,7 @@ class Account extends HookConsumerWidget { Text( isExpired ? 'logout_message_expired'.i18n : 'logout_message'.i18n, style: theme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ], diff --git a/lib/features/account/delete_account.dart b/lib/features/account/delete_account.dart index cc7978bd4e..7d245662a6 100644 --- a/lib/features/account/delete_account.dart +++ b/lib/features/account/delete_account.dart @@ -48,7 +48,7 @@ class _DeleteAccountState extends ConsumerState { child: Text( 'delete_account_message'.i18n, style: textTheme.bodyLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -58,7 +58,7 @@ class _DeleteAccountState extends ConsumerState { child: Text( 'delete_account_message_two'.i18n, style: textTheme.bodyLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), diff --git a/lib/features/auth/add_email.dart b/lib/features/auth/add_email.dart index 6f157003f3..22288b2adc 100644 --- a/lib/features/auth/add_email.dart +++ b/lib/features/auth/add_email.dart @@ -91,7 +91,7 @@ class _AddEmailState extends ConsumerState { padding: EdgeInsets.symmetric(horizontal: defaultSize), child: Text('lantern_pro_license_applied'.i18n, style: textTheme!.bodyMedium! - .copyWith(color: AppColors.gray6, fontSize: 12)), + .copyWith(color: context.textDisabled, fontSize: 12)), ), SizedBox(height: defaultSize), }, @@ -100,7 +100,7 @@ class _AddEmailState extends ConsumerState { padding: EdgeInsets.symmetric(horizontal: defaultSize), child: Text('change_email_message'.i18n, style: textTheme!.bodyMedium!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, )), ) else @@ -108,7 +108,7 @@ class _AddEmailState extends ConsumerState { padding: EdgeInsets.symmetric(horizontal: defaultSize), child: Text('add_your_email_message'.i18n, style: textTheme!.bodyMedium!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, )), ), SizedBox(height: 32), @@ -451,18 +451,18 @@ class _AddEmailState extends ConsumerState { Text( 'email_deliverability_notice'.i18n, style: textTheme!.headlineSmall!.copyWith( - color: AppColors.gray9, + color: context.textPrimary, ), ), SizedBox(height: defaultSize), Text( 'email_deliverability_notice_message'.i18n, - style: textTheme!.bodyMedium!.copyWith(color: AppColors.gray9), + style: textTheme!.bodyMedium!.copyWith(color: context.textPrimary), ), SizedBox(height: defaultSize), Text( 'email_deliverability_notice_message_two'.i18n, - style: textTheme!.bodyMedium!.copyWith(color: AppColors.gray9), + style: textTheme!.bodyMedium!.copyWith(color: context.textPrimary), ), ], ), diff --git a/lib/features/auth/choose_payment_method.dart b/lib/features/auth/choose_payment_method.dart index b804fd32f3..2f497d4017 100644 --- a/lib/features/auth/choose_payment_method.dart +++ b/lib/features/auth/choose_payment_method.dart @@ -114,7 +114,7 @@ class ChoosePaymentMethod extends HookConsumerWidget { action: [ AppTextButton( label: 'cancel'.i18n, - textColor: AppColors.gray8, + textColor: context.textSecondary, underLine: false, onPressed: () { appRouter.pop(); @@ -332,19 +332,19 @@ class PaymentCheckoutMethods extends HookConsumerWidget { padding: const EdgeInsets.only(bottom: 16), child: ExpansionTile( initiallyExpanded: index == 0, - backgroundColor: AppColors.white, - collapsedBackgroundColor: AppColors.white, + backgroundColor: context.bgElevated, + collapsedBackgroundColor: context.bgElevated, collapsedShape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: BorderSide( - color: AppColors.gray3, + color: context.borderInput, width: 1, ), ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: BorderSide( - color: AppColors.gray3, + color: context.borderInput, width: 1, ), ), @@ -370,7 +370,7 @@ class PaymentCheckoutMethods extends HookConsumerWidget { Text( '${userPlan.formattedMonthlyPrice}/month', style: theme.bodyMedium!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, ), ), ], @@ -388,7 +388,7 @@ class PaymentCheckoutMethods extends HookConsumerWidget { Text( 'free'.i18n, style: theme.bodyMedium!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, ), ), ], @@ -400,12 +400,12 @@ class PaymentCheckoutMethods extends HookConsumerWidget { children: [ Text('Order Total:', style: theme.titleSmall!.copyWith( - color: AppColors.gray9, + color: context.textPrimary, )), Text( userPlan.formattedYearlyPrice, style: theme.titleSmall!.copyWith( - color: AppColors.blue10, + color: context.textPrimary, ), ), ], @@ -417,7 +417,7 @@ class PaymentCheckoutMethods extends HookConsumerWidget { ? "Billed every ${userPlan.getDurationText()}. Cancel anytime." : 'billed_once'.i18n.capitalize, style: theme.bodySmall!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, ), ), SizedBox(height: defaultSize), diff --git a/lib/features/auth/confirm_email.dart b/lib/features/auth/confirm_email.dart index 860f7d00d3..4229aa8081 100644 --- a/lib/features/auth/confirm_email.dart +++ b/lib/features/auth/confirm_email.dart @@ -54,7 +54,7 @@ class ConfirmEmail extends HookConsumerWidget { child: Text( 'confirm_email_code'.i18n, style: textTheme.labelLarge?.copyWith( - color: AppColors.gray8, + color: context.textSecondary, fontSize: 14.sp, ), ), @@ -90,7 +90,7 @@ class ConfirmEmail extends HookConsumerWidget { Center( child: AppTextButton( label: 'resend_email'.i18n, - textColor: AppColors.black, + textColor: context.textPrimary, onPressed: () => onResendEmail(context, ref), ), ) diff --git a/lib/features/auth/create_password.dart b/lib/features/auth/create_password.dart index 289c2a2db6..413af39310 100644 --- a/lib/features/auth/create_password.dart +++ b/lib/features/auth/create_password.dart @@ -45,7 +45,7 @@ class CreatePassword extends HookConsumerWidget { hintText: '', prefixIcon: AppImagePaths.lock, label: "create_password".i18n, - suffixIcon: _buildSuffix(obscureText), + suffixIcon: _buildSuffix(obscureText, context), obscureText: obscureText.value, onSubmitted: (_) { if (passwordTextController.text.isPasswordValid()) { @@ -74,9 +74,9 @@ class CreatePassword extends HookConsumerWidget { ); } - Widget _buildSuffix(ValueNotifier obscureText) { + Widget _buildSuffix(ValueNotifier obscureText, BuildContext context) { return AppImage( - color: AppColors.yellow9, + color: context.textPromoIcon, path: obscureText.value ? AppImagePaths.eyeHide : AppImagePaths.eye, onPressed: () { obscureText.value = !obscureText.value; diff --git a/lib/features/auth/device_limit_reached.dart b/lib/features/auth/device_limit_reached.dart index 92bf3bf34c..0772287b76 100644 --- a/lib/features/auth/device_limit_reached.dart +++ b/lib/features/auth/device_limit_reached.dart @@ -38,7 +38,7 @@ class DeviceLimitReached extends HookConsumerWidget { padding: const EdgeInsets.only(left: 16.0), child: Text("lantern_pro_devices".i18n, style: textTheme.labelLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, )), ), AppCard( @@ -79,7 +79,7 @@ class DeviceLimitReached extends HookConsumerWidget { Center( child: AppTextButton( label: 'cancel_sign_in'.i18n, - textColor: AppColors.gray9, + textColor: context.textPrimary, onPressed: () { appRouter.popUntilRoot(); }, diff --git a/lib/features/auth/lantern_pro_license.dart b/lib/features/auth/lantern_pro_license.dart index 15c7066d57..9f2b5f7d9d 100644 --- a/lib/features/auth/lantern_pro_license.dart +++ b/lib/features/auth/lantern_pro_license.dart @@ -83,7 +83,7 @@ class LanternProLicense extends HookConsumerWidget { child: Text( '${normalizedLen.value}/25', style: Theme.of(context).textTheme.labelSmall?.copyWith( - color: AppColors.gray6, + color: context.textDisabled, ), ), ), diff --git a/lib/features/auth/reset_password.dart b/lib/features/auth/reset_password.dart index c4f7288bd5..294c37a092 100644 --- a/lib/features/auth/reset_password.dart +++ b/lib/features/auth/reset_password.dart @@ -43,7 +43,7 @@ class ResetPassword extends HookConsumerWidget { controller: passwordController, prefixIcon: AppImagePaths.lock, onChanged: (value) {}, - suffixIcon: _buildSuffix(obscureText), + suffixIcon: _buildSuffix(obscureText, context), ), SizedBox(height: 20), AppTextField( @@ -76,7 +76,7 @@ class ResetPassword extends HookConsumerWidget { } return null; }, - suffixIcon: _buildSuffix(obscureText), + suffixIcon: _buildSuffix(obscureText, context), ), SizedBox(height: 32), PrimaryButton( @@ -96,9 +96,9 @@ class ResetPassword extends HookConsumerWidget { ); } - Widget _buildSuffix(ValueNotifier obscureText) { + Widget _buildSuffix(ValueNotifier obscureText, BuildContext context) { return AppImage( - color: AppColors.yellow9, + color: context.textPromoIcon, path: obscureText.value ? AppImagePaths.eyeHide : AppImagePaths.eye, onPressed: () { obscureText.value = !obscureText.value; @@ -138,7 +138,7 @@ class ResetPassword extends HookConsumerWidget { action: [ AppTextButton( label: 'continue'.i18n, - textColor: AppColors.gray7, + textColor: context.textTertiary, onPressed: () { appRouter.popUntilRoot(); }, diff --git a/lib/features/auth/sign_in_password.dart b/lib/features/auth/sign_in_password.dart index 48da24a52d..0e2b2badf3 100644 --- a/lib/features/auth/sign_in_password.dart +++ b/lib/features/auth/sign_in_password.dart @@ -67,7 +67,7 @@ class _SignInPasswordState extends ConsumerState { 'if_you_have_not_set_password'.i18n, textAlign: TextAlign.start, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, ), ), ), @@ -75,7 +75,7 @@ class _SignInPasswordState extends ConsumerState { if (widget.fromChangeEmail) Text('confirm_password_to_continue'.i18n, style: Theme.of(context).textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, )), SizedBox(height: 32), PrimaryButton( @@ -90,7 +90,7 @@ class _SignInPasswordState extends ConsumerState { SizedBox(height: 32), AppTextButton( label: 'forgot_password'.i18n, - textColor: AppColors.gray9, + textColor: context.textPrimary, onPressed: () { appRouter.push(ResetPasswordEmail(email: widget.email)); }, @@ -104,7 +104,7 @@ class _SignInPasswordState extends ConsumerState { Widget _buildSuffix(ValueNotifier obscureText) { return AppImage( - color: AppColors.yellow9, + color: context.textPromoIcon, path: obscureText.value ? AppImagePaths.eyeHide : AppImagePaths.eye, onPressed: () { obscureText.value = !obscureText.value; diff --git a/lib/features/home/data_usage.dart b/lib/features/home/data_usage.dart index d8a646d664..f5f22d2211 100644 --- a/lib/features/home/data_usage.dart +++ b/lib/features/home/data_usage.dart @@ -84,8 +84,8 @@ class DataUsage extends ConsumerWidget { : 'daily_data_usage'.i18n, style: textTheme.labelLarge!.copyWith( color: isDataCapReached - ? AppColors.red8 - : AppColors.gray7, + ? context.statusErrorBg + : context.textTertiary, ), ), Spacer(), @@ -93,7 +93,7 @@ class DataUsage extends ConsumerWidget { Text( '$usageString${'mb'.i18n}', style: textTheme.titleSmall!.copyWith( - color: AppColors.gray9, + color: context.textPrimary, ), ), ], @@ -107,7 +107,7 @@ class DataUsage extends ConsumerWidget { maxFontSize: 12, maxLines: 1, style: textTheme.bodySmall!.copyWith( - color: AppColors.red8, + color: context.statusErrorBg, ), ), ), @@ -117,7 +117,7 @@ class DataUsage extends ConsumerWidget { shape: RoundedRectangleBorder( side: isDataCapReached ? BorderSide.none - : BorderSide(width: 1, color: AppColors.gray3), + : BorderSide(width: 1, color: context.borderInput), borderRadius: BorderRadius.circular(8), ), ), @@ -133,9 +133,9 @@ class DataUsage extends ConsumerWidget { Radius.circular(defaultSize), ), trackGap: 10, - backgroundColor: AppColors.gray1, + backgroundColor: context.bgSurface, valueColor: AlwaysStoppedAnimation( - isDataCapReached ? AppColors.red6 : AppColors.yellow3, + isDataCapReached ? context.borderError : AppColors.yellow3, ), ), ), diff --git a/lib/features/home/home.dart b/lib/features/home/home.dart index 3ad13717dd..811d16978f 100644 --- a/lib/features/home/home.dart +++ b/lib/features/home/home.dart @@ -90,8 +90,7 @@ class _HomeState extends ConsumerState { ref.read(appEventProvider); return Scaffold( appBar: AppBar( - backgroundColor: AppColors.white, - title: LanternLogo(isPro: isUserPro), + title: LanternLogo(isPro: isUserPro,color: context.textPrimary,), bottom: PreferredSize( preferredSize: Size.fromHeight(0), child: DividerSpace(padding: EdgeInsets.zero), @@ -264,31 +263,31 @@ class _HomeState extends ConsumerState { SizedBox(height: 24), Text( 'help_improve_lantern'.i18n, - style: textTheme!.headlineSmall!.copyWith(color: AppColors.gray9), + style: textTheme!.headlineSmall!.copyWith(color: context.textPrimary), ), SizedBox(height: defaultSize), Text( 'share_anonymous_usage_data'.i18n, - style: textTheme!.bodyMedium!.copyWith(color: AppColors.gray8), + style: textTheme!.bodyMedium!.copyWith(color: context.textSecondary), ), SizedBox(height: defaultSize), Text( 'data_we_collect'.i18n, style: AppTextStyles.bodyMediumBold.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), SizedBox(height: defaultSize), Text( 'you_can_change_anytime'.i18n, - style: textTheme!.bodyMedium!.copyWith(color: AppColors.gray8), + style: textTheme!.bodyMedium!.copyWith(color: context.textSecondary), ), ], ), action: [ AppTextButton( label: 'dont_allow'.i18n, - textColor: AppColors.gray6, + textColor: context.textDisabled, onPressed: () { context.pop(); ref diff --git a/lib/features/logs/logs.dart b/lib/features/logs/logs.dart index d7f198c0a7..b8ca428bac 100644 --- a/lib/features/logs/logs.dart +++ b/lib/features/logs/logs.dart @@ -80,7 +80,7 @@ class Logs extends HookConsumerWidget { Expanded( child: Container( decoration: ShapeDecoration( - color: AppColors.black1, + color: context.textPrimary, shape: RoundedRectangleBorder( side: BorderSide(width: 1), borderRadius: BorderRadius.circular(16), diff --git a/lib/features/macos_extension/macos_extension_dialog.dart b/lib/features/macos_extension/macos_extension_dialog.dart index a6f3e91587..5c9643ab27 100644 --- a/lib/features/macos_extension/macos_extension_dialog.dart +++ b/lib/features/macos_extension/macos_extension_dialog.dart @@ -54,7 +54,7 @@ class _MacOSExtensionDialogState extends ConsumerState { actions: [ CloseButton(), ], - backgroundColor: AppColors.white, + backgroundColor: context.bgElevated, ), body: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -62,7 +62,7 @@ class _MacOSExtensionDialogState extends ConsumerState { AppImage(path: AppImagePaths.sysDialog), const SizedBox(height: 48.0), Text('enable_network_extension'.i18n, - style: textTheme.headlineSmall!.copyWith(color: AppColors.gray8), + style: textTheme.headlineSmall!.copyWith(color: context.textSecondary), textAlign: TextAlign.center), const SizedBox(height: 16.0), Padding( @@ -70,21 +70,21 @@ class _MacOSExtensionDialogState extends ConsumerState { child: Text( 'enable_network_extension_message'.i18n, style: textTheme.bodyLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), const SizedBox(height: 16.0), RichText( text: TextSpan( - style: textTheme.bodyLarge!.copyWith(color: AppColors.gray7), + style: textTheme.bodyLarge!.copyWith(color: context.textTertiary), children: [ TextSpan(text: 'click'.i18n), WidgetSpan(child: SizedBox(width: 4.0)), TextSpan( text: 'open_system_settings'.i18n, style: AppTextStyles.bodyLargeBold.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), WidgetSpan(child: SizedBox(width: 4.0)), diff --git a/lib/features/onboarding/onboarding.dart b/lib/features/onboarding/onboarding.dart index 46a7adf4b0..c35441d957 100644 --- a/lib/features/onboarding/onboarding.dart +++ b/lib/features/onboarding/onboarding.dart @@ -45,7 +45,7 @@ class _OnboardingState extends ConsumerState { return Scaffold( appBar: AppBar( leading: const SizedBox.shrink(), - backgroundColor: AppColors.white, + backgroundColor: context.bgElevated, title: const LanternLogo(), bottom: PreferredSize( preferredSize: Size.fromHeight(0), @@ -53,7 +53,7 @@ class _OnboardingState extends ConsumerState { ), ), body: Container( - color: AppColors.white, + color: context.bgElevated, padding: const EdgeInsets.symmetric(horizontal: 16.0), child: SafeArea( child: Column( @@ -76,7 +76,7 @@ class _OnboardingState extends ConsumerState { itemSpacing: 15, indicatorBorderWidth: 0.0, currentIndicatorColor: AppColors.blue3, - indicatorBackgroundColor: AppColors.gray3, + indicatorBackgroundColor: context.borderInput, enableAnimation: true, padding: EdgeInsets.only(bottom: 10.0), alignment: Alignment.bottomCenter, @@ -97,7 +97,7 @@ class _OnboardingState extends ConsumerState { 'welcome_to_lantern'.i18n, style: textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, - color: AppColors.gray8), + color: context.textSecondary), ), SizedBox(height: 16), Text('lantern_pro_tagline'.i18n) @@ -128,7 +128,7 @@ class _OnboardingState extends ConsumerState { SizedBox(height: 12.0), AppTextButton( label: 'skip_connect_now'.i18n, - textColor: AppColors.gray9, + textColor: context.textPrimary, onPressed: () { onboardingCompleted(); }, @@ -150,14 +150,14 @@ class _OnboardingState extends ConsumerState { Text( 'what_makes_lantern_different'.i18n, style: textTheme.headlineSmall!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), SizedBox(height: 8.0), Text( 'built_for_privacy_speed_freedom'.i18n, style: textTheme.bodyLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), SizedBox(height: 24.0), @@ -171,13 +171,13 @@ class _OnboardingState extends ConsumerState { labelWidget: Text( 'smart_routing_mode'.i18n, style: textTheme.titleMedium!.copyWith( - color: AppColors.black, + color: context.textPrimary, ), ), subtitle: Text( 'region_specific_routing_description'.i18n, style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -192,13 +192,13 @@ class _OnboardingState extends ConsumerState { labelWidget: Text( 'advanced_protocols'.i18n, style: textTheme.titleMedium!.copyWith( - color: AppColors.black, + color: context.textPrimary, ), ), subtitle: Text( 'advanced_protocols_description'.i18n, style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -213,13 +213,13 @@ class _OnboardingState extends ConsumerState { labelWidget: Text( 'private_servers'.i18n, style: textTheme.titleMedium!.copyWith( - color: AppColors.black, + color: context.textPrimary, ), ), subtitle: Text( 'private_servers_description'.i18n, style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -234,13 +234,13 @@ class _OnboardingState extends ConsumerState { labelWidget: Text( 'nonprofit_mission'.i18n, style: textTheme.titleMedium!.copyWith( - color: AppColors.black, + color: context.textPrimary, ), ), subtitle: Text( 'built_by_nonprofit'.i18n, style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -284,7 +284,7 @@ class _OnboardingState extends ConsumerState { Text( 'choose_your_routing_mode'.i18n, style: textTheme.headlineSmall!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), SizedBox(height: 24.0), @@ -328,11 +328,11 @@ class RouteModeContainer extends StatelessWidget { duration: Duration(milliseconds: 250), padding: EdgeInsets.all(16.0), decoration: BoxDecoration( - color: isSelected ? AppColors.blue1 : AppColors.gray1, + color: isSelected ? AppColors.blue1 : context.bgSurface, borderRadius: BorderRadius.circular(16.0), border: isSelected - ? Border.all(color: AppColors.blue7, width: 3.0) - : Border.all(color: AppColors.gray2, width: 1.0), + ? Border.all(color: context.textLink, width: 3.0) + : Border.all(color: context.borderDefault, width: 1.0), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -347,7 +347,7 @@ class RouteModeContainer extends StatelessWidget { Text( title(), style: textTheme.titleMedium!.copyWith( - color: AppColors.black, + color: context.textPrimary, ), ), SizedBox(width: 8.0), @@ -357,12 +357,12 @@ class RouteModeContainer extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), border: Border.all(color: AppColors.blue4), - color: AppColors.blue2, + color: context.textLink, ), child: Text( tags(), style: - textTheme.labelMedium!.copyWith(color: AppColors.blue8), + textTheme.labelMedium!.copyWith(color: context.borderInputFocus), )) ], ), @@ -370,7 +370,7 @@ class RouteModeContainer extends StatelessWidget { Padding( padding: const EdgeInsets.only(left: 38), child: Text(description(), - style: textTheme.bodyMedium!.copyWith(color: AppColors.gray8)), + style: textTheme.bodyMedium!.copyWith(color: context.textSecondary)), ) ], ), diff --git a/lib/features/plans/feature_list.dart b/lib/features/plans/feature_list.dart index f363a91052..199d4491ed 100644 --- a/lib/features/plans/feature_list.dart +++ b/lib/features/plans/feature_list.dart @@ -53,7 +53,7 @@ class _FeatureTile extends StatelessWidget { children: [ AppImage( path: image, - color: AppColors.blue10, + color: context.textPrimary, height: 24, ), SizedBox(width: defaultSize), diff --git a/lib/features/plans/plan_item.dart b/lib/features/plans/plan_item.dart index 72a0e7d19d..edbf17d015 100644 --- a/lib/features/plans/plan_item.dart +++ b/lib/features/plans/plan_item.dart @@ -2,7 +2,6 @@ import 'package:badges/badges.dart' as badges; import 'package:flutter/material.dart'; import 'package:lantern/core/extensions/plan.dart'; import 'package:lantern/core/models/plan_data.dart'; -import 'package:lantern/core/utils/decoration.dart'; import '../../core/common/common.dart'; @@ -44,7 +43,7 @@ class PlanItem extends StatelessWidget { ), badgeContent: Text( 'best_value'.i18n, - style: textTheme.labelMedium, + style: textTheme.labelMedium!, ), child: GestureDetector( onTap: () { @@ -54,7 +53,7 @@ class PlanItem extends StatelessWidget { margin: EdgeInsets.only(top: 16), padding: EdgeInsets.symmetric(horizontal: defaultSize, vertical: 12), duration: Duration(milliseconds: 300), - decoration: planSelected ? selectedDecoration : unselectedDecoration, + decoration: getPlanDecoration(planSelected, context), child: Row( children: [ Column( @@ -62,7 +61,9 @@ class PlanItem extends StatelessWidget { children: [ Text( plan.description.toTitleCase(), - style: textTheme.titleMedium, + style: textTheme.titleMedium!.copyWith( + color: context.textPrimary, + ), ), if (referralMessage.isNotEmpty) Text( @@ -78,13 +79,13 @@ class PlanItem extends StatelessWidget { Text( plan.formattedYearlyPrice, style: textTheme.titleMedium!.copyWith( - color: AppColors.blue7, + color: context.textLink, ), ), Text( '${plan.formattedMonthlyPrice}/month', style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), ], @@ -92,7 +93,7 @@ class PlanItem extends StatelessWidget { Radio( value: true, groupValue: planSelected, - fillColor: WidgetStatePropertyAll(AppColors.gray9), + fillColor: WidgetStatePropertyAll(context.textPrimary), onChanged: (value) { onPressed.call(plan); }, @@ -103,4 +104,15 @@ class PlanItem extends StatelessWidget { ), ); } + + BoxDecoration getPlanDecoration(bool isSelected, BuildContext context) { + return BoxDecoration( + color: isSelected ? context.bgHover : context.bgElevated, + border: Border.all( + color: isSelected ? context.textLink : context.borderInput, + width: isSelected ? 3 : 1.5, + ), + borderRadius: BorderRadius.circular(16), + ); + } } diff --git a/lib/features/plans/plans.dart b/lib/features/plans/plans.dart index 419fdce951..ba2eefdc34 100644 --- a/lib/features/plans/plans.dart +++ b/lib/features/plans/plans.dart @@ -36,17 +36,17 @@ class _PlansState extends ConsumerState { Widget build(BuildContext context) { textTheme = Theme.of(context).textTheme; return BaseScreen( - backgroundColor: AppColors.white, + backgroundColor: context.bgElevated, padded: false, appBar: CustomAppBar( title: SizedBox( height: 20.h, child: LanternLogo( - color: AppColors.gray9, + color: context.textPrimary, isPro: true, ), ), - backgroundColor: AppColors.white, + backgroundColor: context.bgElevated, leading: IconButton( icon: Icon(Icons.close), onPressed: () { @@ -82,7 +82,7 @@ class _PlansState extends ConsumerState { DividerSpace(padding: EdgeInsets.zero), Expanded( child: Container( - color: AppColors.gray1, + color: context.bgSurface, padding: EdgeInsets.symmetric( horizontal: context.isSmallDevice ? 0 : defaultSize), child: Column( @@ -137,7 +137,7 @@ class _PlansState extends ConsumerState { child: Text( 'subscription_renewal_info'.i18n, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), ), @@ -148,7 +148,7 @@ class _PlansState extends ConsumerState { AppTextButton( label: 'privacy_policy'.i18n, fontSize: 12, - textColor: AppColors.gray7, + textColor: context.textTertiary, onPressed: () { UrlUtils.openWithSystemBrowser( AppUrls.privacyPolicy); @@ -161,7 +161,7 @@ class _PlansState extends ConsumerState { AppTextButton( label: 'terms_of_service'.i18n, fontSize: 12, - textColor: AppColors.gray7, + textColor: context.textTertiary, onPressed: () { UrlUtils.openWithSystemBrowser( AppUrls.termsOfService); @@ -237,7 +237,7 @@ class _PlansState extends ConsumerState { SizedBox(height: defaultSize), Text('referral_code'.i18n, style: textTheme.headlineSmall!.copyWith( - color: AppColors.gray9, + color: context.textPrimary, )), SizedBox(height: 24), AppTextField( @@ -255,7 +255,7 @@ class _PlansState extends ConsumerState { AppTextButton( label: 'cancel'.i18n, underLine: false, - textColor: AppColors.gray6, + textColor: context.textDisabled, onPressed: () { appRouter.pop(); }, diff --git a/lib/features/private_server/join_private_server.dart b/lib/features/private_server/join_private_server.dart index a02bdfde02..b7e2b377cf 100644 --- a/lib/features/private_server/join_private_server.dart +++ b/lib/features/private_server/join_private_server.dart @@ -56,7 +56,7 @@ class _JoinPrivateServerState extends ConsumerState { child: Column(children: [ // SizedBox(height: 16), InfoRow( - backgroundColor: AppColors.yellow1, + backgroundColor: context.bgPromo, showLeadingIcon: false, text: '', child: Row( @@ -106,7 +106,7 @@ class _JoinPrivateServerState extends ConsumerState { child: Text( "how_server_appears".i18n, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, ), ), ), @@ -185,7 +185,7 @@ class _JoinPrivateServerState extends ConsumerState { AppImage( path: AppImagePaths.security, height: 40, - color: AppColors.gray9, + color: context.textPrimary, ), SizedBox(height: 16), Text( @@ -274,7 +274,7 @@ class _JoinPrivateServerState extends ConsumerState { onPressed: () { appRouter.popUntilRoot(); }, - textColor: AppColors.gray6, + textColor: context.textDisabled, ), AppTextButton( label: "go_to_server_locations".i18n, diff --git a/lib/features/private_server/manage_private_server.dart b/lib/features/private_server/manage_private_server.dart index e197d0d2c1..cc68bf1833 100644 --- a/lib/features/private_server/manage_private_server.dart +++ b/lib/features/private_server/manage_private_server.dart @@ -52,7 +52,7 @@ class _ManagePrivateServerState extends ConsumerState { unselectedLabelColor: Colors.grey, labelStyle: textTheme!.titleSmall, indicator: BoxDecoration( - color: AppColors.blue2, + color: context.textLink, borderRadius: BorderRadius.circular(40), shape: BoxShape.rectangle, border: Border.all(color: AppColors.blue3, width: 1), @@ -110,7 +110,7 @@ class _ManagePrivateServerState extends ConsumerState { mainAxisSize: MainAxisSize.min, children: [ IconButton( - icon: Icon(Icons.delete_outline, color: AppColors.gray9), + icon: Icon(Icons.delete_outline, color: context.textPrimary), iconSize: 24, onPressed: () => showDeleteDialog(item.serverName), ), @@ -123,9 +123,9 @@ class _ManagePrivateServerState extends ConsumerState { label: 'share_access_key'.i18n, bgColor: AppColors.blue1, icon: AppImagePaths.shareV2, - iconColor: AppColors.gray9, + iconColor: context.textPrimary, showBorder: true, - textColor: AppColors.gray9, + textColor: context.textPrimary, onPressed: () => onTapShareAccessKey(item)), SizedBox(height: 16), } @@ -181,7 +181,7 @@ class _ManagePrivateServerState extends ConsumerState { action: [ AppTextButton( label: 'cancel'.i18n, - textColor: AppColors.gray6, + textColor: context.textDisabled, onPressed: () { appRouter.pop(); }, @@ -253,7 +253,7 @@ class _ManagePrivateServerState extends ConsumerState { action: [ AppTextButton( label: 'cancel', - textColor: AppColors.gray6, + textColor: context.textDisabled, onPressed: () { appRouter.pop(); }, @@ -292,7 +292,7 @@ class _ManagePrivateServerState extends ConsumerState { action: [ AppTextButton( label: 'cancel'.i18n, - textColor: AppColors.gray6, + textColor: context.textDisabled, onPressed: () { appRouter.pop(); }, diff --git a/lib/features/private_server/manually_server_setup.dart b/lib/features/private_server/manually_server_setup.dart index 28a2ef1d4e..1bb4f1f1fc 100644 --- a/lib/features/private_server/manually_server_setup.dart +++ b/lib/features/private_server/manually_server_setup.dart @@ -62,7 +62,7 @@ class _ManuallyServerSetupState extends ConsumerState { SizedBox(height: 16), PrimaryButton( icon: AppImagePaths.github, - iconColor: AppColors.white, + iconColor: context.textInverse, isTaller: true, label: 'view_instructions_github'.i18n, onPressed: () { @@ -99,7 +99,7 @@ class _ManuallyServerSetupState extends ConsumerState { child: Text( "how_server_appears".i18n, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, ), ), ), @@ -226,7 +226,7 @@ class _ManuallyServerSetupState extends ConsumerState { onPressed: () { appRouter.popUntilRoot(); }, - textColor: AppColors.gray6, + textColor: context.textDisabled, ), AppTextButton( label: "connect_now".i18n, diff --git a/lib/features/private_server/private_server_add_billing.dart b/lib/features/private_server/private_server_add_billing.dart index f189e8272f..c55a8a8810 100644 --- a/lib/features/private_server/private_server_add_billing.dart +++ b/lib/features/private_server/private_server_add_billing.dart @@ -70,7 +70,7 @@ class PrivateServerAddBilling extends HookConsumerWidget { Center( child: AppImage( path: AppImagePaths.creditCard, - color: AppColors.gray9, + color: context.textPrimary, height: 30, ), ), @@ -87,14 +87,14 @@ class PrivateServerAddBilling extends HookConsumerWidget { textAlign: TextAlign.left, text: TextSpan( style: - textTheme.bodyMedium!.copyWith(color: AppColors.gray8), + textTheme.bodyMedium!.copyWith(color: context.textSecondary), text: '${'1'.i18n}. ', children: [ TextSpan(text: '${'tap'.i18n} '), TextSpan( text: '${'open_system_settings'.i18n} ', style: AppTextStyles.bodyMediumBold!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, )), TextSpan(text: 'below_to_go_to_do'.i18n), ], @@ -104,7 +104,7 @@ class PrivateServerAddBilling extends HookConsumerWidget { RichText( text: TextSpan( style: - textTheme.bodyMedium!.copyWith(color: AppColors.gray8), + textTheme.bodyMedium!.copyWith(color: context.textSecondary), text: '${'2'.i18n}. ', children: [ TextSpan(text: '${'add_payment_method'.i18n} '), @@ -115,7 +115,7 @@ class PrivateServerAddBilling extends HookConsumerWidget { RichText( text: TextSpan( style: - textTheme.bodyMedium!.copyWith(color: AppColors.gray8), + textTheme.bodyMedium!.copyWith(color: context.textSecondary), text: '${'3'.i18n}. ', children: [ TextSpan(text: '${'return_to_lantern'.i18n} '), @@ -130,7 +130,7 @@ class PrivateServerAddBilling extends HookConsumerWidget { PrimaryButton( isTaller: true, icon: AppImagePaths.outsideBrowser, - iconColor: AppColors.white, + iconColor: context.textInverse, label: 'open_system_settings'.i18n, onPressed: () { UrlUtils.openUrl(AppUrls.digitalOceanBillingUrl); diff --git a/lib/features/private_server/private_server_deploy.dart b/lib/features/private_server/private_server_deploy.dart index fcf0d88cc4..75d865d7c2 100644 --- a/lib/features/private_server/private_server_deploy.dart +++ b/lib/features/private_server/private_server_deploy.dart @@ -69,7 +69,7 @@ class _PrivateServerDeployState extends ConsumerState { child: Text( 'private_server_setup_in_progress'.i18n, style: textTheme!.bodyLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -106,7 +106,7 @@ class _PrivateServerDeployState extends ConsumerState { SizedBox(height: 16), Text( 'private_server_ready_message'.i18n.fill([widget.serverName]), - style: textTheme!.bodyMedium!.copyWith(color: AppColors.gray8), + style: textTheme!.bodyMedium!.copyWith(color: context.textSecondary), ), ], ), @@ -116,7 +116,7 @@ class _PrivateServerDeployState extends ConsumerState { onPressed: () { appRouter.popUntilRoot(); }, - textColor: AppColors.gray6, + textColor: context.textDisabled, ), AppTextButton( label: "go_to_server_locations".i18n, @@ -149,7 +149,7 @@ class _PrivateServerDeployState extends ConsumerState { SizedBox(height: 16), Text( 'server_setup_failed_message'.i18n, - style: textTheme!.bodyMedium!.copyWith(color: AppColors.gray8), + style: textTheme!.bodyMedium!.copyWith(color: context.textSecondary), ), ], ), @@ -159,7 +159,7 @@ class _PrivateServerDeployState extends ConsumerState { onPressed: () { appRouter.popUntilRoot(); }, - textColor: AppColors.gray6, + textColor: context.textDisabled, ), AppTextButton( label: "retry".i18n, diff --git a/lib/features/private_server/private_server_locations.dart b/lib/features/private_server/private_server_locations.dart index c23bf01259..25e6765f58 100644 --- a/lib/features/private_server/private_server_locations.dart +++ b/lib/features/private_server/private_server_locations.dart @@ -57,7 +57,7 @@ class _PrivateServerLocationState extends ConsumerState { child: Text( '${widget.provider.displayName} Location Options (${widget.location.length}) ', style: textTheme.labelLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), diff --git a/lib/features/private_server/private_sever_details.dart b/lib/features/private_server/private_sever_details.dart index b125d3cfc5..5aed7ffa69 100644 --- a/lib/features/private_server/private_sever_details.dart +++ b/lib/features/private_server/private_sever_details.dart @@ -266,7 +266,7 @@ class _PrivateSeverDetailsState extends ConsumerState { child: Text( "how_server_appears".i18n, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray6, + color: context.textDisabled, ), ), ), diff --git a/lib/features/private_server/provider_card.dart b/lib/features/private_server/provider_card.dart index def5197a3e..ccba221d4b 100644 --- a/lib/features/private_server/provider_card.dart +++ b/lib/features/private_server/provider_card.dart @@ -46,7 +46,7 @@ class ProviderCard extends StatelessWidget { child: Text( title, style: t.titleMedium?.copyWith( - color: AppColors.black1, + color: context.textPrimary, fontWeight: FontWeight.w600, // height: 1.50, ), @@ -115,7 +115,7 @@ class CheckmarkTile extends StatelessWidget { softWrap: true, overflow: TextOverflow.visible, style: t.bodyMedium?.copyWith( - color: AppColors.black1, + color: context.textPrimary, height: 1.64, ), ), @@ -134,7 +134,7 @@ class CheckmarkTile extends StatelessWidget { return Column( children: [ row, - Divider(height: 1, color: AppColors.gray2), + Divider(height: 1, color: context.borderDefault), ], ); } diff --git a/lib/features/private_server/provider_carousel.dart b/lib/features/private_server/provider_carousel.dart index d2158335c3..fbd83bb901 100644 --- a/lib/features/private_server/provider_carousel.dart +++ b/lib/features/private_server/provider_carousel.dart @@ -82,9 +82,9 @@ class ProviderCarousel extends HookConsumerWidget { child: Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( - color: AppColors.white, + color: context.bgElevated, shape: BoxShape.circle, - border: Border.all(color: AppColors.gray4, width: 1), + border: Border.all(color: context.textDisabled, width: 1), ), child: AppImage( path: AppImagePaths.arrowBack, @@ -103,9 +103,9 @@ class ProviderCarousel extends HookConsumerWidget { child: Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( - color: AppColors.white, + color: context.bgElevated, shape: BoxShape.circle, - border: Border.all(color: AppColors.gray4, width: 1), + border: Border.all(color: context.textDisabled, width: 1), ), child: AppImage( path: AppImagePaths.arrowForward, @@ -184,7 +184,7 @@ class _CarouselDots extends StatelessWidget { spacing: 8, children: List.generate(count, (i) { final active = i == current; - final fill = active ? AppColors.gray4 : AppColors.gray2; + final fill = active ? context.textDisabled : context.borderDefault; return Semantics( selected: active, label: 'Page ${i + 1} of $count', @@ -198,7 +198,7 @@ class _CarouselDots extends StatelessWidget { decoration: BoxDecoration( color: fill, borderRadius: BorderRadius.circular(100), - border: Border.all(color: AppColors.gray3, width: 1), + border: Border.all(color: context.borderInput, width: 1), ), ), ), @@ -225,7 +225,7 @@ class _ArrowButton extends StatelessWidget { @override Widget build(BuildContext context) { - final iconColor = enabled ? AppColors.black1 : AppColors.gray4; + final iconColor = enabled ? context.textPrimary : context.textDisabled; Widget icon = assetPath != null ? AppImage(path: assetPath!, width: 24, height: 24, color: iconColor) diff --git a/lib/features/setting/download_links.dart b/lib/features/setting/download_links.dart index 425d10ea4b..f27446a110 100644 --- a/lib/features/setting/download_links.dart +++ b/lib/features/setting/download_links.dart @@ -51,7 +51,7 @@ class DownloadLinks extends StatelessWidget { child: Text( 'alternative_download_links'.i18n, style: theme.labelLarge!.copyWith( - color: AppColors.gray8, + color: buildContext.textSecondary, ), ), ), @@ -79,7 +79,7 @@ class DownloadLinks extends StatelessWidget { child: Text( 'if_you_cannot_access_website'.i18n, style: theme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: buildContext.textSecondary, ), ), ), @@ -91,7 +91,7 @@ class DownloadLinks extends StatelessWidget { child: Text( 'available_on'.i18n, style: theme.labelLarge!.copyWith( - color: AppColors.gray8, + color: buildContext.textSecondary, ), ), ), diff --git a/lib/features/setting/invite_friends.dart b/lib/features/setting/invite_friends.dart index a6c4857bd5..fbb32a4626 100644 --- a/lib/features/setting/invite_friends.dart +++ b/lib/features/setting/invite_friends.dart @@ -21,7 +21,8 @@ class InviteFriends extends HookConsumerWidget { Widget _buildBody(String referralCode) { final isCopied = useState(false); - final textTheme = Theme.of(useContext()).textTheme; + final context = useContext(); + final textTheme = Theme.of(context).textTheme; return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -33,7 +34,7 @@ class InviteFriends extends HookConsumerWidget { child: Text( 'your_referral_code'.i18n, style: textTheme.labelLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -50,7 +51,7 @@ class InviteFriends extends HookConsumerWidget { firstChild: AppImage(path: AppImagePaths.copy), secondChild: Icon( Icons.check_circle, - color: AppColors.green7, + color: context.statusSuccessBg, ), ), label: referralCode, @@ -66,7 +67,7 @@ class InviteFriends extends HookConsumerWidget { Text( 'invite_friends_message'.i18n, style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), SizedBox(height: defaultSize), @@ -76,19 +77,19 @@ class InviteFriends extends HookConsumerWidget { TextSpan( text: '- ', style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), TextSpan( text: 'monthly_plan'.i18n, style: AppTextStyles.bodyMediumBold.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), TextSpan( text: ' ${'15_days_each'.i18n}', style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ], @@ -101,19 +102,19 @@ class InviteFriends extends HookConsumerWidget { TextSpan( text: '- ', style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), TextSpan( text: 'annual_plan'.i18n, style: AppTextStyles.bodyMediumBold.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), TextSpan( text: ' ${'1_month_each'.i18n}', style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ], @@ -126,19 +127,19 @@ class InviteFriends extends HookConsumerWidget { TextSpan( text: '- ', style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), TextSpan( text: 'two_year_plan'.i18n, style: AppTextStyles.bodyMediumBold.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), TextSpan( text: ' ${'2_month_each'.i18n}', style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ], @@ -148,7 +149,7 @@ class InviteFriends extends HookConsumerWidget { Text( 'referral_code_info'.i18n, style: textTheme.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ], diff --git a/lib/features/setting/setting.dart b/lib/features/setting/setting.dart index 46f127ec5e..66de649c3a 100644 --- a/lib/features/setting/setting.dart +++ b/lib/features/setting/setting.dart @@ -99,7 +99,7 @@ class _SettingState extends ConsumerState { : Text( email, style: textTheme.labelMedium!.copyWith( - color: AppColors.blue7, + color: context.textLink, ), ), onPressed: () => settingMenuTap(_SettingType.account), @@ -132,7 +132,7 @@ class _SettingState extends ConsumerState { trailing: Text( displayLanguage(locale), style: textTheme.titleMedium!.copyWith( - color: AppColors.blue7, + color: context.textLink, ), ), onPressed: () => settingMenuTap(_SettingType.language), @@ -198,7 +198,7 @@ class _SettingState extends ConsumerState { child: Text( 'lantern_projects'.i18n, style: textTheme.labelLarge!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -212,7 +212,7 @@ class _SettingState extends ConsumerState { subtitle: Text( 'help_fight_global_internet_censorship'.i18n, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), onPressed: () { diff --git a/lib/features/setting/smart_routing.dart b/lib/features/setting/smart_routing.dart index f261dbd6f7..7c22d0acc2 100644 --- a/lib/features/setting/smart_routing.dart +++ b/lib/features/setting/smart_routing.dart @@ -50,7 +50,7 @@ class SmartRouting extends HookConsumerWidget { maxLines: 1, overflow: TextOverflow.ellipsis, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, letterSpacing: 0.0, ), ), @@ -68,7 +68,7 @@ class SmartRouting extends HookConsumerWidget { maxLines: 1, overflow: TextOverflow.ellipsis, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, letterSpacing: 0.0, ), ), diff --git a/lib/features/setting/vpn_setting.dart b/lib/features/setting/vpn_setting.dart index 8e50586808..b1bbab6e11 100644 --- a/lib/features/setting/vpn_setting.dart +++ b/lib/features/setting/vpn_setting.dart @@ -84,7 +84,7 @@ class VPNSetting extends HookConsumerWidget { subtitle: Text( 'only_active'.i18n, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, letterSpacing: 0.0, ), ), @@ -163,7 +163,7 @@ class VPNSetting extends HookConsumerWidget { maxFontSize: 12, maxLines: 2, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, letterSpacing: 0.0, ), ), diff --git a/lib/features/split_tunneling/apps_split_tunneling.dart b/lib/features/split_tunneling/apps_split_tunneling.dart index 434898256a..855c7de694 100644 --- a/lib/features/split_tunneling/apps_split_tunneling.dart +++ b/lib/features/split_tunneling/apps_split_tunneling.dart @@ -198,9 +198,9 @@ class AppRow extends HookConsumerWidget { fit: BoxFit.cover, ); } - return Icon(Icons.apps, size: 24, color: AppColors.gray6); + return Icon(Icons.apps, size: 24, color: context.textDisabled); }, - orElse: () => Icon(Icons.apps, size: 24, color: AppColors.gray6), + orElse: () => Icon(Icons.apps, size: 24, color: context.textDisabled), ); } @@ -220,7 +220,7 @@ class AppRow extends HookConsumerWidget { style: AppTextStyles.bodyMedium.copyWith( fontSize: 16, fontWeight: FontWeight.w400, - color: AppColors.gray9, + color: context.textPrimary, ), ), ), diff --git a/lib/features/split_tunneling/split_tunneling.dart b/lib/features/split_tunneling/split_tunneling.dart index 7125d2f7dd..3a6982d9d9 100644 --- a/lib/features/split_tunneling/split_tunneling.dart +++ b/lib/features/split_tunneling/split_tunneling.dart @@ -42,14 +42,14 @@ class SplitTunneling extends HookConsumerWidget { tileTextStyle: AppTextStyles.bodyMedium.copyWith( fontWeight: FontWeight.w600, fontSize: 16, - color: AppColors.gray9, + color: context.textPrimary, ), subtitle: Text( 'add_apps_websites_bypass_vpn'.i18n, maxLines: 1, overflow: TextOverflow.ellipsis, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, letterSpacing: 0.0, ), ), diff --git a/lib/features/split_tunneling/split_tunneling_info.dart b/lib/features/split_tunneling/split_tunneling_info.dart index 7f5f693ef7..0d0ece223c 100644 --- a/lib/features/split_tunneling/split_tunneling_info.dart +++ b/lib/features/split_tunneling/split_tunneling_info.dart @@ -50,7 +50,7 @@ class SplitTunnelingInfo extends HookConsumerWidget { 'split_tunneling_description'.i18n, style: AppTextStyles.bodyLarge.copyWith( height: 1.625, - color: AppColors.gray9, + color: context.textPrimary, ), ), ), @@ -62,7 +62,7 @@ class SplitTunnelingInfo extends HookConsumerWidget { 'location_based_rules'.i18n, style: AppTextStyles.bodyLarge.copyWith( height: 1.625, - color: AppColors.gray9, + color: context.textPrimary, ), ), ), @@ -73,10 +73,10 @@ class SplitTunnelingInfo extends HookConsumerWidget { 'unblocked_sites_bypass'.i18n, ], textStyle: AppTextStyles.bodyMedium.copyWith( - color: AppColors.gray8, + color: context.textSecondary, height: 1.5, ), - bulletColor: AppColors.gray7, + bulletColor: context.textTertiary, ), SubsectionTitle(icon: "✅", text: 'uncensored_regions'.i18n), @@ -86,10 +86,10 @@ class SplitTunnelingInfo extends HookConsumerWidget { 'examples_of_bypassed_sites'.i18n, ], textStyle: AppTextStyles.bodyMedium.copyWith( - color: AppColors.gray8, + color: context.textSecondary, height: 1.5, ), - bulletColor: AppColors.gray7, + bulletColor: context.textTertiary, ), SizedBox(height: 16.0), LinkText( @@ -139,7 +139,7 @@ class SubsectionTitle extends StatelessWidget { ? Theme.of(context).textTheme.titleLarge! : AppTextStyles.labelMedium.copyWith( fontSize: 16, - color: AppColors.gray9, + color: context.textPrimary, fontWeight: FontWeight.w600, ); diff --git a/lib/features/split_tunneling/website_domain_input.dart b/lib/features/split_tunneling/website_domain_input.dart index 6d114c9bc8..045d884b5b 100644 --- a/lib/features/split_tunneling/website_domain_input.dart +++ b/lib/features/split_tunneling/website_domain_input.dart @@ -99,7 +99,7 @@ class WebsiteDomainInput extends HookConsumerWidget { ), AppTextButton( label: 'add'.i18n, - textColor: AppColors.black, + textColor: context.textPrimary, onPressed: validateAndExtractDomain, ), ], @@ -109,7 +109,7 @@ class WebsiteDomainInput extends HookConsumerWidget { child: Text( 'use_commas'.i18n, style: AppTextStyles.bodyMedium.copyWith( - color: AppColors.gray7, + color: context.textTertiary, height: 1.6, fontSize: 12, fontWeight: FontWeight.w500, diff --git a/lib/features/split_tunneling/website_split_tunneling.dart b/lib/features/split_tunneling/website_split_tunneling.dart index 477c3a5173..972df1615d 100644 --- a/lib/features/split_tunneling/website_split_tunneling.dart +++ b/lib/features/split_tunneling/website_split_tunneling.dart @@ -56,7 +56,7 @@ class WebsiteSplitTunneling extends HookConsumerWidget { child: Text( 'no_websites_selected'.i18n, style: textTheme.bodyLarge!.copyWith( - color: AppColors.gray9, + color: context.textPrimary, ), ), ) @@ -99,7 +99,7 @@ class WebsiteRow extends StatelessWidget { contentPadding: EdgeInsets.only(left: 16), label: website.domain, tileTextStyle: AppTextStyles.labelLarge.copyWith( - color: AppColors.gray8, + color: context.textSecondary, fontSize: 14, fontWeight: FontWeight.w500, ), diff --git a/lib/features/support/app_version.dart b/lib/features/support/app_version.dart index 144953d249..6364671d10 100644 --- a/lib/features/support/app_version.dart +++ b/lib/features/support/app_version.dart @@ -16,11 +16,11 @@ class AppVersion extends StatelessWidget { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), decoration: BoxDecoration( - color: AppColors.gray1, + color: context.bgSurface, borderRadius: BorderRadius.circular(8), border: Border( - top: BorderSide(color: AppColors.gray2, width: 1), - bottom: BorderSide(color: AppColors.gray2, width: 1), + top: BorderSide(color: context.borderDefault, width: 1), + bottom: BorderSide(color: context.borderDefault, width: 1), ), ), child: Row( @@ -28,7 +28,7 @@ class AppVersion extends StatelessWidget { children: [ Text('lantern_version'.i18n, style: theme.bodyMedium), Text(label, - style: theme.titleSmall!.copyWith(color: AppColors.blue7)), + style: theme.titleSmall!.copyWith(color: context.textLink)), ], ), ); diff --git a/lib/features/vpn/server_desktop_view.dart b/lib/features/vpn/server_desktop_view.dart index 04da819b59..7c0290bb7b 100644 --- a/lib/features/vpn/server_desktop_view.dart +++ b/lib/features/vpn/server_desktop_view.dart @@ -32,13 +32,13 @@ class _ServerDesktopViewState extends State { turns: isExpanded ? .25 : 0.0, child: Icon( Icons.arrow_forward_ios_rounded, - color: AppColors.gray9, + color: context.textPrimary, size: 20, ), ), title: Text( 'Korea', - style: textTheme.bodyLarge!.copyWith(color: AppColors.gray9), + style: textTheme.bodyLarge!.copyWith(color: context.textPrimary), ), shape: RoundedRectangleBorder(side: BorderSide.none), leading: AppImage(path: AppImagePaths.location), @@ -49,10 +49,10 @@ class _ServerDesktopViewState extends State { contentPadding: EdgeInsets.only(left: 46), label: 'USA - New Jersey', tileTextStyle: - textTheme.bodyMedium!.copyWith(color: AppColors.gray9), + textTheme.bodyMedium!.copyWith(color: context.textPrimary), trailing: Radio( visualDensity: VisualDensity.compact, - activeColor: AppColors.gray9, + activeColor: context.textPrimary, value: true, groupValue: false, onChanged: (value) {}, diff --git a/lib/features/vpn/server_selection.dart b/lib/features/vpn/server_selection.dart index 8e7f0183ae..7ee4e0f01e 100644 --- a/lib/features/vpn/server_selection.dart +++ b/lib/features/vpn/server_selection.dart @@ -58,7 +58,7 @@ class _ServerSelectionState extends ConsumerState { child: Text( 'automatically_chooses_fastest_location'.i18n, style: _textTheme?.bodyMedium!.copyWith( - color: AppColors.gray8, + color: context.textSecondary, ), ), ), @@ -81,7 +81,7 @@ class _ServerSelectionState extends ConsumerState { padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( 'automatically_chooses_fastest_location'.i18n, - style: _textTheme?.bodyMedium!.copyWith(color: AppColors.gray8), + style: _textTheme?.bodyMedium!.copyWith(color: context.textSecondary), ), ), SizedBox(height: size24), @@ -99,7 +99,7 @@ class _ServerSelectionState extends ConsumerState { labelPadding: EdgeInsets.zero, indicatorPadding: EdgeInsets.symmetric(horizontal: size24), indicator: BoxDecoration( - color: AppColors.blue2, + color: context.textLink, borderRadius: BorderRadius.circular(40), shape: BoxShape.rectangle, border: Border.all(color: AppColors.blue3, width: 1), @@ -138,7 +138,7 @@ class _ServerSelectionState extends ConsumerState { padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( 'smart_location'.i18n, - style: _textTheme?.labelLarge!.copyWith(color: AppColors.gray8), + style: _textTheme?.labelLarge!.copyWith(color: context.textSecondary), ), ), AppCard( @@ -155,7 +155,7 @@ class _ServerSelectionState extends ConsumerState { : Text( protocol.capitalize, style: _textTheme!.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), trailing: Row( @@ -189,7 +189,7 @@ class _ServerSelectionState extends ConsumerState { : Text( serverLocation.protocol.capitalize, style: _textTheme!.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ); case ServerLocationType.privateServer: @@ -201,7 +201,7 @@ class _ServerSelectionState extends ConsumerState { child: Text( serverLocation.displayName, style: _textTheme!.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), ), @@ -209,7 +209,7 @@ class _ServerSelectionState extends ConsumerState { Text( serverLocation.protocol.capitalize, style: _textTheme!.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), ], @@ -383,7 +383,7 @@ class _ServerLocationListViewState if (!widget.userPro) Positioned.fill( child: Container( - color: AppColors.white.withValues(alpha: 0.72), + color: context.bgElevated.withValues(alpha: 0.72), alignment: Alignment.center, ), ), @@ -496,7 +496,7 @@ class _CountryCityListViewState extends State<_CountryCityListView> { country, style: Theme.of( context, - ).textTheme.bodyLarge!.copyWith(color: AppColors.gray9), + ).textTheme.bodyLarge!.copyWith(color: context.textPrimary), ), onExpansionChanged: (expanded) { setState(() => _isExpanded = expanded); @@ -516,11 +516,11 @@ class _CountryCityListViewState extends State<_CountryCityListView> { maxLines: 1, style: Theme.of( context, - ).textTheme.labelMedium!.copyWith(color: AppColors.gray7), + ).textTheme.labelMedium!.copyWith(color: context.textTertiary), ), tileTextStyle: Theme.of( context, - ).textTheme.bodyMedium!.copyWith(color: AppColors.gray9), + ).textTheme.bodyMedium!.copyWith(color: context.textPrimary), onPressed: () => _onLocationSelected(context, loc), ); }).toList(), @@ -533,7 +533,7 @@ class _CountryCityListViewState extends State<_CountryCityListView> { trailing: AppImage( path: AppImagePaths.arrowForward, height: 20.0, - color: AppColors.gray9, + color: context.textPrimary, ), onPressed: () => _showCountryBottomSheet(context), ); @@ -605,7 +605,7 @@ class _PrivateServerLocationListViewState Text( 'no_private_server_setup_yet'.i18n, textAlign: TextAlign.center, - style: _textTheme!.titleSmall!.copyWith(color: AppColors.gray8), + style: _textTheme!.titleSmall!.copyWith(color: context.textSecondary), ), SizedBox(height: 16), PrimaryButton( @@ -662,7 +662,7 @@ class _PrivateServerLocationListViewState child: Text( '${server.serverLocationName.locationName} - ${server.externalIp}', style: _textTheme!.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), ), @@ -670,7 +670,7 @@ class _PrivateServerLocationListViewState Text( server.protocol.capitalize, style: _textTheme!.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), ], @@ -709,7 +709,7 @@ class _PrivateServerLocationListViewState child: Text( '${server.serverLocationName} - ${server.externalIp}', style: _textTheme!.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), ), diff --git a/lib/features/vpn/single_city_server_view.dart b/lib/features/vpn/single_city_server_view.dart index 803a3f6c43..899f9b368b 100644 --- a/lib/features/vpn/single_city_server_view.dart +++ b/lib/features/vpn/single_city_server_view.dart @@ -38,7 +38,7 @@ class _SingleCityServerViewState extends State { : Text( widget.location.protocol.capitalize, style: textTheme.labelMedium!.copyWith( - color: AppColors.gray7, + color: context.textTertiary, ), ), icon: Flag(countryCode: widget.location.countryCode), diff --git a/lib/features/vpn/vpn_status.dart b/lib/features/vpn/vpn_status.dart index 612628b917..90d157cf87 100644 --- a/lib/features/vpn/vpn_status.dart +++ b/lib/features/vpn/vpn_status.dart @@ -33,7 +33,7 @@ class VpnStatus extends HookConsumerWidget { : null, actions: [ if (isExtensionNeeded(systemExtensionStatus)) - AppImage(path: AppImagePaths.warning, color: AppColors.red6) + AppImage(path: AppImagePaths.warning, color: context.borderError) else VPNStatusIndicator(status: vpnStatus), ], @@ -43,23 +43,23 @@ class VpnStatus extends HookConsumerWidget { if (isExtensionNeeded(systemExtensionStatus)) Text( 'network_extension_required'.i18n, - style: textTheme.titleMedium!.copyWith(color: AppColors.gray9), + style: textTheme.titleMedium!.copyWith(color: context.textPrimary), ) else Text(vpnStatus.name.capitalize, style: textTheme.titleMedium! - .copyWith(color: getStatusColor(vpnStatus))), + .copyWith(color: getStatusColor(vpnStatus, context))), if (vpnStatus == VPNStatus.connecting) AnimatedTextKit( animatedTexts: [ TyperAnimatedText( '... ', textStyle: - textTheme.titleMedium!.copyWith(color: AppColors.gray9), + textTheme.titleMedium!.copyWith(color: context.textPrimary), ), TyperAnimatedText('...', textStyle: textTheme.titleMedium! - .copyWith(color: AppColors.gray9)), + .copyWith(color: context.textPrimary)), ], repeatForever: true, ) @@ -77,10 +77,10 @@ class VpnStatus extends HookConsumerWidget { systemExtensionStatus.status != SystemExtensionStatus.activated); } - Color getStatusColor(VPNStatus vpnStatus) { + Color getStatusColor(VPNStatus vpnStatus, BuildContext context) { if (vpnStatus == VPNStatus.connected) { - return AppColors.green6; + return context.statusSuccessBorder; } - return AppColors.gray9; + return context.textPrimary; } } diff --git a/lib/features/vpn/vpn_switch.dart b/lib/features/vpn/vpn_switch.dart index 72fd13d9b9..71b0f34ff3 100644 --- a/lib/features/vpn/vpn_switch.dart +++ b/lib/features/vpn/vpn_switch.dart @@ -53,7 +53,7 @@ class VPNSwitch extends HookConsumerWidget { padding: const EdgeInsets.all(8.0), child: CircularProgressIndicator( strokeWidth: 8.r, - color: AppColors.gray1, + color: context.bgSurface, ), ), ); @@ -65,7 +65,7 @@ class VPNSwitch extends HookConsumerWidget { }, child: Container( decoration: BoxDecoration( - color: AppColors.gray1, + color: context.actionToggleKnobBg, borderRadius: BorderRadius.circular(30.r), ), ), @@ -75,7 +75,7 @@ class VPNSwitch extends HookConsumerWidget { return Container( padding: EdgeInsets.all(5.r), decoration: BoxDecoration( - color: _wrapperColor(vpnStatus), + color: _wrapperColor(vpnStatus, context), borderRadius: BorderRadius.circular(50.r), ), child: child, @@ -106,19 +106,19 @@ class VPNSwitch extends HookConsumerWidget { ); } - Color _wrapperColor(VPNStatus vpnStatus) { + Color _wrapperColor(VPNStatus vpnStatus, BuildContext context) { switch (vpnStatus) { case VPNStatus.connected: return AppColors.blue4; case VPNStatus.connecting: case VPNStatus.disconnected: - return AppColors.gray7; + return context.textTertiary; case VPNStatus.disconnecting: - return AppColors.gray7; + return context.textTertiary; case VPNStatus.missingPermission: - return AppColors.gray7; + return context.textTertiary; case VPNStatus.error: - return AppColors.gray7; + return context.textTertiary; } } } diff --git a/lib/lantern_app.dart b/lib/lantern_app.dart index 01a36fef07..aee6b51a44 100644 --- a/lib/lantern_app.dart +++ b/lib/lantern_app.dart @@ -181,7 +181,7 @@ class _LanternAppState extends ConsumerState { child: MaterialApp.router( locale: locale.toLocale, debugShowCheckedModeBanner: false, - theme: AppTheme.appTheme(), + theme: AppTheme.darkTheme(), themeMode: ThemeMode.light, darkTheme: AppTheme.darkTheme(), From adf9488a10f78e20335a2b9412e5d8bfc26dc5af Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 14:01:21 +0530 Subject: [PATCH 02/14] More dark mode changes --- lib/core/common/app_buttons.dart | 6 ++++++ lib/core/widgets/app_tile.dart | 13 +++++++++---- lib/core/widgets/oauth_login.dart | 2 ++ lib/features/plans/plan_item.dart | 4 ++-- lib/features/setting/setting.dart | 1 + lib/features/support/support.dart | 1 + 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/core/common/app_buttons.dart b/lib/core/common/app_buttons.dart index f2a833604f..351ee1a3a1 100644 --- a/lib/core/common/app_buttons.dart +++ b/lib/core/common/app_buttons.dart @@ -148,6 +148,8 @@ class SecondaryButton extends StatelessWidget { final Color? bgColor; final bool? isTaller; + final bool? useThemeColor; + final Color? iconColor; const SecondaryButton({ super.key, @@ -158,6 +160,8 @@ class SecondaryButton extends StatelessWidget { required this.onPressed, this.icon, this.bgColor, + this.useThemeColor, + this.iconColor, }); @override @@ -178,6 +182,8 @@ class SecondaryButton extends StatelessWidget { icon: AppImage( path: icon!, height: iconHeight, + color: iconColor, + useThemeColor: useThemeColor??false, ), label: Text(label), style: _buildButtonStyle(context, button!, iconSz), diff --git a/lib/core/widgets/app_tile.dart b/lib/core/widgets/app_tile.dart index d1c5a2ef24..3824514f4d 100644 --- a/lib/core/widgets/app_tile.dart +++ b/lib/core/widgets/app_tile.dart @@ -33,6 +33,7 @@ class AppTile extends StatelessWidget { final BorderRadius? borderRadius; final VisualDensity? visualDensity; final ListTileTitleAlignment? titleAlignment; + final bool? iconUseThemeColor; const AppTile({ super.key, @@ -59,6 +60,7 @@ class AppTile extends StatelessWidget { this.borderRadius, this.visualDensity, this.titleAlignment, + this.iconUseThemeColor, }); factory AppTile.link({ @@ -93,8 +95,8 @@ class AppTile extends StatelessWidget { final textStyle = tileTextStyle ?? theme.textTheme.labelLarge!.copyWith( color: enabled - ? context.textPrimary // text.primary - : context.textPrimary.withValues(alpha: 0.38), // text.disabled + ? context.textPrimary // text.primary + : context.textPrimary.withValues(alpha: 0.38), // text.disabled fontWeight: FontWeight.w400, fontSize: 16, ); @@ -105,7 +107,10 @@ class AppTile extends StatelessWidget { computedLeading = SizedBox( width: 24, height: 24, - child: AppImage(path: icon as String), + child: AppImage( + path: icon as String, + useThemeColor: iconUseThemeColor ?? true, + ), ); } else if (icon is IconData) { computedLeading = Icon( @@ -131,7 +136,7 @@ class AppTile extends StatelessWidget { enabled: enabled && !loading, minVerticalPadding: 0, selected: selected, - titleAlignment: titleAlignment??ListTileTitleAlignment.center, + titleAlignment: titleAlignment ?? ListTileTitleAlignment.center, enableFeedback: true, // hoverColor: hoverColor ?? AppColors.blue1, hoverColor: hoverColor ?? theme.hoverColor, diff --git a/lib/core/widgets/oauth_login.dart b/lib/core/widgets/oauth_login.dart index 4a720b5c9b..14bf4f7374 100644 --- a/lib/core/widgets/oauth_login.dart +++ b/lib/core/widgets/oauth_login.dart @@ -29,6 +29,7 @@ class OAuthLogin extends HookConsumerWidget { label: 'continue_with_apple'.i18n, icon: AppImagePaths.apple, isTaller: true, + iconColor: context.textPrimary, onPressed: () => _handleSignIn(SignUpMethodType.apple, ref, context), ); } @@ -36,6 +37,7 @@ class OAuthLogin extends HookConsumerWidget { label: 'continue_with_google'.i18n, icon: AppImagePaths.google, isTaller: true, + useThemeColor: false, onPressed: () => _handleSignIn(SignUpMethodType.google, ref, context), ); } diff --git a/lib/features/plans/plan_item.dart b/lib/features/plans/plan_item.dart index edbf17d015..56d4a1da44 100644 --- a/lib/features/plans/plan_item.dart +++ b/lib/features/plans/plan_item.dart @@ -34,11 +34,11 @@ class PlanItem extends StatelessWidget { badgeStyle: badges.BadgeStyle( shape: badges.BadgeShape.square, borderSide: BorderSide( - color: AppColors.yellow4, + color: context.statusWarningText, width: 1, ), borderRadius: BorderRadius.circular(16), - badgeColor: AppColors.yellow3, + badgeColor: context.statusWarningBgDot, padding: EdgeInsets.symmetric(horizontal: 10, vertical: 6), ), badgeContent: Text( diff --git a/lib/features/setting/setting.dart b/lib/features/setting/setting.dart index 66de649c3a..37a29ea557 100644 --- a/lib/features/setting/setting.dart +++ b/lib/features/setting/setting.dart @@ -207,6 +207,7 @@ class _SettingState extends ConsumerState { child: AppTile( minHeight: 72, icon: AppImagePaths.lanternLogoRounded, + iconUseThemeColor: false, trailing: AppImage(path: AppImagePaths.outsideBrowser), label: 'unbounded'.i18n, subtitle: Text( diff --git a/lib/features/support/support.dart b/lib/features/support/support.dart index 08c528e3b2..644c58aaaf 100644 --- a/lib/features/support/support.dart +++ b/lib/features/support/support.dart @@ -21,6 +21,7 @@ class Support extends StatelessWidget { Center( child: AppImage( path: AppImagePaths.supportIllustration, + useThemeColor: false, type: AssetType.svg, height: 180.h, width: 180.w, From a92fd736fc0e2c01f4b6f211d6a0bbb8c393c6ca Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 14:14:48 +0530 Subject: [PATCH 03/14] aded new appearance ui --- .../models/entity/app_setting_entity.dart | 4 + lib/core/router/router.dart | 4 + lib/core/router/router.gr.dart | 621 ++++++------ lib/core/services/db/objectbox-model.json | 195 ++-- lib/core/services/db/objectbox.g.dart | 900 +++++++++--------- .../home/provider/app_setting_notifier.dart | 15 + .../home/provider/app_setting_notifier.g.dart | 2 +- lib/features/setting/appearance.dart | 92 ++ lib/features/setting/setting.dart | 23 +- .../provider/system_tray_notifier.g.dart | 2 +- lib/lantern_app.dart | 8 +- pubspec.lock | 4 +- 12 files changed, 1039 insertions(+), 831 deletions(-) create mode 100644 lib/features/setting/appearance.dart diff --git a/lib/core/models/entity/app_setting_entity.dart b/lib/core/models/entity/app_setting_entity.dart index b24a0de20d..05fa5d49fa 100644 --- a/lib/core/models/entity/app_setting_entity.dart +++ b/lib/core/models/entity/app_setting_entity.dart @@ -20,6 +20,7 @@ class AppSetting { String routingModeRaw; String dataCapThreshold; bool onboardingCompleted; + String themeMode; AppSetting({ this.id = 0, @@ -37,6 +38,7 @@ class AppSetting { this.routingModeRaw = 'full_tunnel', this.dataCapThreshold = '', this.onboardingCompleted = false, + this.themeMode = 'system', }); AppSetting copyWith({ @@ -54,6 +56,7 @@ class AppSetting { String? routingModeRaw, String? dataCapThreshold, bool? onboardingCompleted, + String? themeMode, }) { return AppSetting( id: id, @@ -71,6 +74,7 @@ class AppSetting { routingModeRaw: routingModeRaw ?? this.routingModeRaw, dataCapThreshold: dataCapThreshold ?? this.dataCapThreshold, onboardingCompleted: onboardingCompleted ?? this.onboardingCompleted, + themeMode: themeMode ?? this.themeMode, ); } diff --git a/lib/core/router/router.dart b/lib/core/router/router.dart index 17cdd8b5ad..6bb8c84719 100644 --- a/lib/core/router/router.dart +++ b/lib/core/router/router.dart @@ -176,6 +176,10 @@ class AppRouter extends RootStackRouter { path: '/developer-mode', page: DeveloperMode.page, ), + AutoRoute( + path: '/appearance', + page: Appearance.page, + ), AutoRoute( path: '/smart-routing', page: SmartRouting.page, diff --git a/lib/core/router/router.gr.dart b/lib/core/router/router.gr.dart index 65e33ae03e..f2e685b236 100644 --- a/lib/core/router/router.gr.dart +++ b/lib/core/router/router.gr.dart @@ -9,75 +9,76 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i43; -import 'package:collection/collection.dart' as _i47; -import 'package:flutter/material.dart' as _i44; -import 'package:lantern/core/common/common.dart' as _i45; +import 'package:auto_route/auto_route.dart' as _i44; +import 'package:collection/collection.dart' as _i48; +import 'package:flutter/material.dart' as _i45; +import 'package:lantern/core/common/common.dart' as _i46; import 'package:lantern/core/widgets/app_webview.dart' as _i3; import 'package:lantern/features/account/account.dart' as _i1; -import 'package:lantern/features/account/delete_account.dart' as _i8; +import 'package:lantern/features/account/delete_account.dart' as _i9; import 'package:lantern/features/auth/add_email.dart' as _i2; -import 'package:lantern/features/auth/choose_payment_method.dart' as _i5; -import 'package:lantern/features/auth/confirm_email.dart' as _i6; -import 'package:lantern/features/auth/create_password.dart' as _i7; -import 'package:lantern/features/auth/device_limit_reached.dart' as _i10; -import 'package:lantern/features/auth/lantern_pro_license.dart' as _i17; -import 'package:lantern/features/auth/reset_password.dart' as _i31; -import 'package:lantern/features/auth/reset_password_email.dart' as _i32; -import 'package:lantern/features/auth/sign_in_email.dart' as _i35; -import 'package:lantern/features/auth/sign_in_password.dart' as _i36; -import 'package:lantern/features/developer/developer_mode.dart' as _i9; -import 'package:lantern/features/home/home.dart' as _i13; -import 'package:lantern/features/language/language.dart' as _i16; -import 'package:lantern/features/logs/logs.dart' as _i18; +import 'package:lantern/features/auth/choose_payment_method.dart' as _i6; +import 'package:lantern/features/auth/confirm_email.dart' as _i7; +import 'package:lantern/features/auth/create_password.dart' as _i8; +import 'package:lantern/features/auth/device_limit_reached.dart' as _i11; +import 'package:lantern/features/auth/lantern_pro_license.dart' as _i18; +import 'package:lantern/features/auth/reset_password.dart' as _i32; +import 'package:lantern/features/auth/reset_password_email.dart' as _i33; +import 'package:lantern/features/auth/sign_in_email.dart' as _i36; +import 'package:lantern/features/auth/sign_in_password.dart' as _i37; +import 'package:lantern/features/developer/developer_mode.dart' as _i10; +import 'package:lantern/features/home/home.dart' as _i14; +import 'package:lantern/features/language/language.dart' as _i17; +import 'package:lantern/features/logs/logs.dart' as _i19; import 'package:lantern/features/macos_extension/macos_extension_dialog.dart' - as _i19; -import 'package:lantern/features/onboarding/onboarding.dart' as _i22; -import 'package:lantern/features/plans/plans.dart' as _i23; + as _i20; +import 'package:lantern/features/onboarding/onboarding.dart' as _i23; +import 'package:lantern/features/plans/plans.dart' as _i24; import 'package:lantern/features/private_server/join_private_server.dart' - as _i15; + as _i16; import 'package:lantern/features/private_server/manage_private_server.dart' - as _i20; -import 'package:lantern/features/private_server/manually_server_setup.dart' as _i21; +import 'package:lantern/features/private_server/manually_server_setup.dart' + as _i22; import 'package:lantern/features/private_server/private_server_add_billing.dart' - as _i24; -import 'package:lantern/features/private_server/private_server_deploy.dart' as _i25; -import 'package:lantern/features/private_server/private_server_locations.dart' +import 'package:lantern/features/private_server/private_server_deploy.dart' as _i26; -import 'package:lantern/features/private_server/private_server_setup.dart' +import 'package:lantern/features/private_server/private_server_locations.dart' as _i27; -import 'package:lantern/features/private_server/private_sever_details.dart' +import 'package:lantern/features/private_server/private_server_setup.dart' as _i28; -import 'package:lantern/features/qr_scanner/qr_code_scanner.dart' as _i29; -import 'package:lantern/features/report_Issue/report_issue.dart' as _i30; -import 'package:lantern/features/setting/download_links.dart' as _i11; -import 'package:lantern/features/setting/follow_us.dart' as _i12; -import 'package:lantern/features/setting/invite_friends.dart' as _i14; -import 'package:lantern/features/setting/setting.dart' as _i34; -import 'package:lantern/features/setting/smart_routing.dart' as _i37; -import 'package:lantern/features/setting/vpn_setting.dart' as _i41; +import 'package:lantern/features/private_server/private_sever_details.dart' + as _i29; +import 'package:lantern/features/qr_scanner/qr_code_scanner.dart' as _i30; +import 'package:lantern/features/report_Issue/report_issue.dart' as _i31; +import 'package:lantern/features/setting/appearance.dart' as _i4; +import 'package:lantern/features/setting/download_links.dart' as _i12; +import 'package:lantern/features/setting/follow_us.dart' as _i13; +import 'package:lantern/features/setting/invite_friends.dart' as _i15; +import 'package:lantern/features/setting/setting.dart' as _i35; +import 'package:lantern/features/setting/smart_routing.dart' as _i38; +import 'package:lantern/features/setting/vpn_setting.dart' as _i42; import 'package:lantern/features/split_tunneling/apps_split_tunneling.dart' - as _i4; -import 'package:lantern/features/split_tunneling/split_tunneling.dart' as _i38; + as _i5; +import 'package:lantern/features/split_tunneling/split_tunneling.dart' as _i39; import 'package:lantern/features/split_tunneling/split_tunneling_info.dart' - as _i39; + as _i40; import 'package:lantern/features/split_tunneling/website_split_tunneling.dart' - as _i42; -import 'package:lantern/features/support/support.dart' as _i40; -import 'package:lantern/features/vpn/server_selection.dart' as _i33; -import 'package:lantern/lantern/protos/protos/auth.pb.dart' as _i46; + as _i43; +import 'package:lantern/features/support/support.dart' as _i41; +import 'package:lantern/features/vpn/server_selection.dart' as _i34; +import 'package:lantern/lantern/protos/protos/auth.pb.dart' as _i47; /// generated route for /// [_i1.Account] -class Account extends _i43.PageRouteInfo { - const Account({List<_i43.PageRouteInfo>? children}) +class Account extends _i44.PageRouteInfo { + const Account({List<_i44.PageRouteInfo>? children}) : super(Account.name, initialChildren: children); static const String name = 'Account'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i1.Account(); @@ -87,12 +88,12 @@ class Account extends _i43.PageRouteInfo { /// generated route for /// [_i2.AddEmail] -class AddEmail extends _i43.PageRouteInfo { +class AddEmail extends _i44.PageRouteInfo { AddEmail({ - _i44.Key? key, - _i45.AuthFlow authFlow = _i45.AuthFlow.signUp, + _i45.Key? key, + _i46.AuthFlow authFlow = _i46.AuthFlow.signUp, String? password, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( AddEmail.name, args: AddEmailArgs(key: key, authFlow: authFlow, password: password), @@ -101,7 +102,7 @@ class AddEmail extends _i43.PageRouteInfo { static const String name = 'AddEmail'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs( @@ -119,13 +120,13 @@ class AddEmail extends _i43.PageRouteInfo { class AddEmailArgs { const AddEmailArgs({ this.key, - this.authFlow = _i45.AuthFlow.signUp, + this.authFlow = _i46.AuthFlow.signUp, this.password, }); - final _i44.Key? key; + final _i45.Key? key; - final _i45.AuthFlow authFlow; + final _i46.AuthFlow authFlow; final String? password; @@ -149,12 +150,12 @@ class AddEmailArgs { /// generated route for /// [_i3.AppWebView] -class AppWebview extends _i43.PageRouteInfo { +class AppWebview extends _i44.PageRouteInfo { AppWebview({ - _i44.Key? key, + _i45.Key? key, required String title, required String url, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( AppWebview.name, args: AppWebviewArgs(key: key, title: title, url: url), @@ -163,7 +164,7 @@ class AppWebview extends _i43.PageRouteInfo { static const String name = 'AppWebview'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); @@ -175,7 +176,7 @@ class AppWebview extends _i43.PageRouteInfo { class AppWebviewArgs { const AppWebviewArgs({this.key, required this.title, required this.url}); - final _i44.Key? key; + final _i45.Key? key; final String title; @@ -198,30 +199,46 @@ class AppWebviewArgs { } /// generated route for -/// [_i4.AppsSplitTunneling] -class AppsSplitTunneling extends _i43.PageRouteInfo { - const AppsSplitTunneling({List<_i43.PageRouteInfo>? children}) +/// [_i4.Appearance] +class Appearance extends _i44.PageRouteInfo { + const Appearance({List<_i44.PageRouteInfo>? children}) + : super(Appearance.name, initialChildren: children); + + static const String name = 'Appearance'; + + static _i44.PageInfo page = _i44.PageInfo( + name, + builder: (data) { + return const _i4.Appearance(); + }, + ); +} + +/// generated route for +/// [_i5.AppsSplitTunneling] +class AppsSplitTunneling extends _i44.PageRouteInfo { + const AppsSplitTunneling({List<_i44.PageRouteInfo>? children}) : super(AppsSplitTunneling.name, initialChildren: children); static const String name = 'AppsSplitTunneling'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i4.AppsSplitTunneling(); + return const _i5.AppsSplitTunneling(); }, ); } /// generated route for -/// [_i5.ChoosePaymentMethod] -class ChoosePaymentMethod extends _i43.PageRouteInfo { +/// [_i6.ChoosePaymentMethod] +class ChoosePaymentMethod extends _i44.PageRouteInfo { ChoosePaymentMethod({ - _i44.Key? key, + _i45.Key? key, required String email, String? code, - required _i45.AuthFlow authFlow, - List<_i43.PageRouteInfo>? children, + required _i46.AuthFlow authFlow, + List<_i44.PageRouteInfo>? children, }) : super( ChoosePaymentMethod.name, args: ChoosePaymentMethodArgs( @@ -235,11 +252,11 @@ class ChoosePaymentMethod extends _i43.PageRouteInfo { static const String name = 'ChoosePaymentMethod'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i5.ChoosePaymentMethod( + return _i6.ChoosePaymentMethod( key: args.key, email: args.email, code: args.code, @@ -257,13 +274,13 @@ class ChoosePaymentMethodArgs { required this.authFlow, }); - final _i44.Key? key; + final _i45.Key? key; final String email; final String? code; - final _i45.AuthFlow authFlow; + final _i46.AuthFlow authFlow; @override String toString() { @@ -286,14 +303,14 @@ class ChoosePaymentMethodArgs { } /// generated route for -/// [_i6.ConfirmEmail] -class ConfirmEmail extends _i43.PageRouteInfo { +/// [_i7.ConfirmEmail] +class ConfirmEmail extends _i44.PageRouteInfo { ConfirmEmail({ - _i44.Key? key, + _i45.Key? key, required String email, String? password, - _i45.AuthFlow authFlow = _i45.AuthFlow.signUp, - List<_i43.PageRouteInfo>? children, + _i46.AuthFlow authFlow = _i46.AuthFlow.signUp, + List<_i44.PageRouteInfo>? children, }) : super( ConfirmEmail.name, args: ConfirmEmailArgs( @@ -307,11 +324,11 @@ class ConfirmEmail extends _i43.PageRouteInfo { static const String name = 'ConfirmEmail'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i6.ConfirmEmail( + return _i7.ConfirmEmail( key: args.key, email: args.email, password: args.password, @@ -326,16 +343,16 @@ class ConfirmEmailArgs { this.key, required this.email, this.password, - this.authFlow = _i45.AuthFlow.signUp, + this.authFlow = _i46.AuthFlow.signUp, }); - final _i44.Key? key; + final _i45.Key? key; final String email; final String? password; - final _i45.AuthFlow authFlow; + final _i46.AuthFlow authFlow; @override String toString() { @@ -358,14 +375,14 @@ class ConfirmEmailArgs { } /// generated route for -/// [_i7.CreatePassword] -class CreatePassword extends _i43.PageRouteInfo { +/// [_i8.CreatePassword] +class CreatePassword extends _i44.PageRouteInfo { CreatePassword({ - _i44.Key? key, + _i45.Key? key, required String email, - required _i45.AuthFlow authFlow, + required _i46.AuthFlow authFlow, required String code, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( CreatePassword.name, args: CreatePasswordArgs( @@ -379,11 +396,11 @@ class CreatePassword extends _i43.PageRouteInfo { static const String name = 'CreatePassword'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i7.CreatePassword( + return _i8.CreatePassword( key: args.key, email: args.email, authFlow: args.authFlow, @@ -401,11 +418,11 @@ class CreatePasswordArgs { required this.code, }); - final _i44.Key? key; + final _i45.Key? key; final String email; - final _i45.AuthFlow authFlow; + final _i46.AuthFlow authFlow; final String code; @@ -430,44 +447,44 @@ class CreatePasswordArgs { } /// generated route for -/// [_i8.DeleteAccount] -class DeleteAccount extends _i43.PageRouteInfo { - const DeleteAccount({List<_i43.PageRouteInfo>? children}) +/// [_i9.DeleteAccount] +class DeleteAccount extends _i44.PageRouteInfo { + const DeleteAccount({List<_i44.PageRouteInfo>? children}) : super(DeleteAccount.name, initialChildren: children); static const String name = 'DeleteAccount'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i8.DeleteAccount(); + return const _i9.DeleteAccount(); }, ); } /// generated route for -/// [_i9.DeveloperMode] -class DeveloperMode extends _i43.PageRouteInfo { - const DeveloperMode({List<_i43.PageRouteInfo>? children}) +/// [_i10.DeveloperMode] +class DeveloperMode extends _i44.PageRouteInfo { + const DeveloperMode({List<_i44.PageRouteInfo>? children}) : super(DeveloperMode.name, initialChildren: children); static const String name = 'DeveloperMode'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i9.DeveloperMode(); + return const _i10.DeveloperMode(); }, ); } /// generated route for -/// [_i10.DeviceLimitReached] -class DeviceLimitReached extends _i43.PageRouteInfo { +/// [_i11.DeviceLimitReached] +class DeviceLimitReached extends _i44.PageRouteInfo { DeviceLimitReached({ - _i44.Key? key, - required List<_i46.UserResponse_Device> devices, - List<_i43.PageRouteInfo>? children, + _i45.Key? key, + required List<_i47.UserResponse_Device> devices, + List<_i44.PageRouteInfo>? children, }) : super( DeviceLimitReached.name, args: DeviceLimitReachedArgs(key: key, devices: devices), @@ -476,11 +493,11 @@ class DeviceLimitReached extends _i43.PageRouteInfo { static const String name = 'DeviceLimitReached'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i10.DeviceLimitReached(key: args.key, devices: args.devices); + return _i11.DeviceLimitReached(key: args.key, devices: args.devices); }, ); } @@ -488,9 +505,9 @@ class DeviceLimitReached extends _i43.PageRouteInfo { class DeviceLimitReachedArgs { const DeviceLimitReachedArgs({this.key, required this.devices}); - final _i44.Key? key; + final _i45.Key? key; - final List<_i46.UserResponse_Device> devices; + final List<_i47.UserResponse_Device> devices; @override String toString() { @@ -502,7 +519,7 @@ class DeviceLimitReachedArgs { if (identical(this, other)) return true; if (other is! DeviceLimitReachedArgs) return false; return key == other.key && - const _i47.ListEquality<_i46.UserResponse_Device>().equals( + const _i48.ListEquality<_i47.UserResponse_Device>().equals( devices, other.devices, ); @@ -511,80 +528,80 @@ class DeviceLimitReachedArgs { @override int get hashCode => key.hashCode ^ - const _i47.ListEquality<_i46.UserResponse_Device>().hash(devices); + const _i48.ListEquality<_i47.UserResponse_Device>().hash(devices); } /// generated route for -/// [_i11.DownloadLinks] -class DownloadLinks extends _i43.PageRouteInfo { - const DownloadLinks({List<_i43.PageRouteInfo>? children}) +/// [_i12.DownloadLinks] +class DownloadLinks extends _i44.PageRouteInfo { + const DownloadLinks({List<_i44.PageRouteInfo>? children}) : super(DownloadLinks.name, initialChildren: children); static const String name = 'DownloadLinks'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i11.DownloadLinks(); + return const _i12.DownloadLinks(); }, ); } /// generated route for -/// [_i12.FollowUs] -class FollowUs extends _i43.PageRouteInfo { - const FollowUs({List<_i43.PageRouteInfo>? children}) +/// [_i13.FollowUs] +class FollowUs extends _i44.PageRouteInfo { + const FollowUs({List<_i44.PageRouteInfo>? children}) : super(FollowUs.name, initialChildren: children); static const String name = 'FollowUs'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i12.FollowUs(); + return const _i13.FollowUs(); }, ); } /// generated route for -/// [_i13.Home] -class Home extends _i43.PageRouteInfo { - const Home({List<_i43.PageRouteInfo>? children}) +/// [_i14.Home] +class Home extends _i44.PageRouteInfo { + const Home({List<_i44.PageRouteInfo>? children}) : super(Home.name, initialChildren: children); static const String name = 'Home'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i13.Home(); + return const _i14.Home(); }, ); } /// generated route for -/// [_i14.InviteFriends] -class InviteFriends extends _i43.PageRouteInfo { - const InviteFriends({List<_i43.PageRouteInfo>? children}) +/// [_i15.InviteFriends] +class InviteFriends extends _i44.PageRouteInfo { + const InviteFriends({List<_i44.PageRouteInfo>? children}) : super(InviteFriends.name, initialChildren: children); static const String name = 'InviteFriends'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i14.InviteFriends(); + return const _i15.InviteFriends(); }, ); } /// generated route for -/// [_i15.JoinPrivateServer] -class JoinPrivateServer extends _i43.PageRouteInfo { +/// [_i16.JoinPrivateServer] +class JoinPrivateServer extends _i44.PageRouteInfo { JoinPrivateServer({ - _i44.Key? key, + _i45.Key? key, Map? deepLinkData, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( JoinPrivateServer.name, args: JoinPrivateServerArgs(key: key, deepLinkData: deepLinkData), @@ -593,13 +610,13 @@ class JoinPrivateServer extends _i43.PageRouteInfo { static const String name = 'JoinPrivateServer'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const JoinPrivateServerArgs(), ); - return _i15.JoinPrivateServer( + return _i16.JoinPrivateServer( key: args.key, deepLinkData: args.deepLinkData, ); @@ -610,7 +627,7 @@ class JoinPrivateServer extends _i43.PageRouteInfo { class JoinPrivateServerArgs { const JoinPrivateServerArgs({this.key, this.deepLinkData}); - final _i44.Key? key; + final _i45.Key? key; final Map? deepLinkData; @@ -624,7 +641,7 @@ class JoinPrivateServerArgs { if (identical(this, other)) return true; if (other is! JoinPrivateServerArgs) return false; return key == other.key && - const _i47.MapEquality().equals( + const _i48.MapEquality().equals( deepLinkData, other.deepLinkData, ); @@ -633,33 +650,33 @@ class JoinPrivateServerArgs { @override int get hashCode => key.hashCode ^ - const _i47.MapEquality().hash(deepLinkData); + const _i48.MapEquality().hash(deepLinkData); } /// generated route for -/// [_i16.Language] -class Language extends _i43.PageRouteInfo { - const Language({List<_i43.PageRouteInfo>? children}) +/// [_i17.Language] +class Language extends _i44.PageRouteInfo { + const Language({List<_i44.PageRouteInfo>? children}) : super(Language.name, initialChildren: children); static const String name = 'Language'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i16.Language(); + return const _i17.Language(); }, ); } /// generated route for -/// [_i17.LanternProLicense] -class LanternProLicense extends _i43.PageRouteInfo { +/// [_i18.LanternProLicense] +class LanternProLicense extends _i44.PageRouteInfo { LanternProLicense({ - _i44.Key? key, + _i45.Key? key, required String email, required String code, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( LanternProLicense.name, args: LanternProLicenseArgs(key: key, email: email, code: code), @@ -668,11 +685,11 @@ class LanternProLicense extends _i43.PageRouteInfo { static const String name = 'LanternProLicense'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i17.LanternProLicense( + return _i18.LanternProLicense( key: args.key, email: args.email, code: args.code, @@ -688,7 +705,7 @@ class LanternProLicenseArgs { required this.code, }); - final _i44.Key? key; + final _i45.Key? key; final String email; @@ -711,124 +728,124 @@ class LanternProLicenseArgs { } /// generated route for -/// [_i18.Logs] -class Logs extends _i43.PageRouteInfo { - const Logs({List<_i43.PageRouteInfo>? children}) +/// [_i19.Logs] +class Logs extends _i44.PageRouteInfo { + const Logs({List<_i44.PageRouteInfo>? children}) : super(Logs.name, initialChildren: children); static const String name = 'Logs'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i18.Logs(); + return const _i19.Logs(); }, ); } /// generated route for -/// [_i19.MacOSExtensionDialog] -class MacOSExtensionDialog extends _i43.PageRouteInfo { - const MacOSExtensionDialog({List<_i43.PageRouteInfo>? children}) +/// [_i20.MacOSExtensionDialog] +class MacOSExtensionDialog extends _i44.PageRouteInfo { + const MacOSExtensionDialog({List<_i44.PageRouteInfo>? children}) : super(MacOSExtensionDialog.name, initialChildren: children); static const String name = 'MacOSExtensionDialog'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i19.MacOSExtensionDialog(); + return const _i20.MacOSExtensionDialog(); }, ); } /// generated route for -/// [_i20.ManagePrivateServer] -class ManagePrivateServer extends _i43.PageRouteInfo { - const ManagePrivateServer({List<_i43.PageRouteInfo>? children}) +/// [_i21.ManagePrivateServer] +class ManagePrivateServer extends _i44.PageRouteInfo { + const ManagePrivateServer({List<_i44.PageRouteInfo>? children}) : super(ManagePrivateServer.name, initialChildren: children); static const String name = 'ManagePrivateServer'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i20.ManagePrivateServer(); + return const _i21.ManagePrivateServer(); }, ); } /// generated route for -/// [_i21.ManuallyServerSetup] -class ManuallyServerSetup extends _i43.PageRouteInfo { - const ManuallyServerSetup({List<_i43.PageRouteInfo>? children}) +/// [_i22.ManuallyServerSetup] +class ManuallyServerSetup extends _i44.PageRouteInfo { + const ManuallyServerSetup({List<_i44.PageRouteInfo>? children}) : super(ManuallyServerSetup.name, initialChildren: children); static const String name = 'ManuallyServerSetup'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i21.ManuallyServerSetup(); + return const _i22.ManuallyServerSetup(); }, ); } /// generated route for -/// [_i22.Onboarding] -class Onboarding extends _i43.PageRouteInfo { - const Onboarding({List<_i43.PageRouteInfo>? children}) +/// [_i23.Onboarding] +class Onboarding extends _i44.PageRouteInfo { + const Onboarding({List<_i44.PageRouteInfo>? children}) : super(Onboarding.name, initialChildren: children); static const String name = 'Onboarding'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i22.Onboarding(); + return const _i23.Onboarding(); }, ); } /// generated route for -/// [_i23.Plans] -class Plans extends _i43.PageRouteInfo { - const Plans({List<_i43.PageRouteInfo>? children}) +/// [_i24.Plans] +class Plans extends _i44.PageRouteInfo { + const Plans({List<_i44.PageRouteInfo>? children}) : super(Plans.name, initialChildren: children); static const String name = 'Plans'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i23.Plans(); + return const _i24.Plans(); }, ); } /// generated route for -/// [_i24.PrivateServerAddBilling] -class PrivateServerAddBilling extends _i43.PageRouteInfo { - const PrivateServerAddBilling({List<_i43.PageRouteInfo>? children}) +/// [_i25.PrivateServerAddBilling] +class PrivateServerAddBilling extends _i44.PageRouteInfo { + const PrivateServerAddBilling({List<_i44.PageRouteInfo>? children}) : super(PrivateServerAddBilling.name, initialChildren: children); static const String name = 'PrivateServerAddBilling'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i24.PrivateServerAddBilling(); + return const _i25.PrivateServerAddBilling(); }, ); } /// generated route for -/// [_i25.PrivateServerDeploy] -class PrivateServerDeploy extends _i43.PageRouteInfo { +/// [_i26.PrivateServerDeploy] +class PrivateServerDeploy extends _i44.PageRouteInfo { PrivateServerDeploy({ - _i44.Key? key, + _i45.Key? key, required String serverName, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( PrivateServerDeploy.name, args: PrivateServerDeployArgs(key: key, serverName: serverName), @@ -837,11 +854,11 @@ class PrivateServerDeploy extends _i43.PageRouteInfo { static const String name = 'PrivateServerDeploy'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i25.PrivateServerDeploy( + return _i26.PrivateServerDeploy( key: args.key, serverName: args.serverName, ); @@ -852,7 +869,7 @@ class PrivateServerDeploy extends _i43.PageRouteInfo { class PrivateServerDeployArgs { const PrivateServerDeployArgs({this.key, required this.serverName}); - final _i44.Key? key; + final _i45.Key? key; final String serverName; @@ -873,16 +890,16 @@ class PrivateServerDeployArgs { } /// generated route for -/// [_i26.PrivateServerLocation] +/// [_i27.PrivateServerLocation] class PrivateServerLocation - extends _i43.PageRouteInfo { + extends _i44.PageRouteInfo { PrivateServerLocation({ - _i44.Key? key, + _i45.Key? key, required List location, required String? selectedLocation, required dynamic Function(String) onLocationSelected, - required _i45.CloudProvider provider, - List<_i43.PageRouteInfo>? children, + required _i46.CloudProvider provider, + List<_i44.PageRouteInfo>? children, }) : super( PrivateServerLocation.name, args: PrivateServerLocationArgs( @@ -897,11 +914,11 @@ class PrivateServerLocation static const String name = 'PrivateServerLocation'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i26.PrivateServerLocation( + return _i27.PrivateServerLocation( key: args.key, location: args.location, selectedLocation: args.selectedLocation, @@ -921,7 +938,7 @@ class PrivateServerLocationArgs { required this.provider, }); - final _i44.Key? key; + final _i45.Key? key; final List location; @@ -929,7 +946,7 @@ class PrivateServerLocationArgs { final dynamic Function(String) onLocationSelected; - final _i45.CloudProvider provider; + final _i46.CloudProvider provider; @override String toString() { @@ -941,7 +958,7 @@ class PrivateServerLocationArgs { if (identical(this, other)) return true; if (other is! PrivateServerLocationArgs) return false; return key == other.key && - const _i47.ListEquality().equals(location, other.location) && + const _i48.ListEquality().equals(location, other.location) && selectedLocation == other.selectedLocation && provider == other.provider; } @@ -949,37 +966,37 @@ class PrivateServerLocationArgs { @override int get hashCode => key.hashCode ^ - const _i47.ListEquality().hash(location) ^ + const _i48.ListEquality().hash(location) ^ selectedLocation.hashCode ^ provider.hashCode; } /// generated route for -/// [_i27.PrivateServerSetup] -class PrivateServerSetup extends _i43.PageRouteInfo { - const PrivateServerSetup({List<_i43.PageRouteInfo>? children}) +/// [_i28.PrivateServerSetup] +class PrivateServerSetup extends _i44.PageRouteInfo { + const PrivateServerSetup({List<_i44.PageRouteInfo>? children}) : super(PrivateServerSetup.name, initialChildren: children); static const String name = 'PrivateServerSetup'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i27.PrivateServerSetup(); + return const _i28.PrivateServerSetup(); }, ); } /// generated route for -/// [_i28.PrivateSeverDetails] +/// [_i29.PrivateSeverDetails] class PrivateServerDetails - extends _i43.PageRouteInfo { + extends _i44.PageRouteInfo { PrivateServerDetails({ - _i44.Key? key, + _i45.Key? key, required List accounts, - required _i45.CloudProvider provider, + required _i46.CloudProvider provider, bool isPreFilled = false, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( PrivateServerDetails.name, args: PrivateServerDetailsArgs( @@ -993,11 +1010,11 @@ class PrivateServerDetails static const String name = 'PrivateServerDetails'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i28.PrivateSeverDetails( + return _i29.PrivateSeverDetails( key: args.key, accounts: args.accounts, provider: args.provider, @@ -1015,11 +1032,11 @@ class PrivateServerDetailsArgs { this.isPreFilled = false, }); - final _i44.Key? key; + final _i45.Key? key; final List accounts; - final _i45.CloudProvider provider; + final _i46.CloudProvider provider; final bool isPreFilled; @@ -1033,7 +1050,7 @@ class PrivateServerDetailsArgs { if (identical(this, other)) return true; if (other is! PrivateServerDetailsArgs) return false; return key == other.key && - const _i47.ListEquality().equals(accounts, other.accounts) && + const _i48.ListEquality().equals(accounts, other.accounts) && provider == other.provider && isPreFilled == other.isPreFilled; } @@ -1041,35 +1058,35 @@ class PrivateServerDetailsArgs { @override int get hashCode => key.hashCode ^ - const _i47.ListEquality().hash(accounts) ^ + const _i48.ListEquality().hash(accounts) ^ provider.hashCode ^ isPreFilled.hashCode; } /// generated route for -/// [_i29.QrCodeScanner] -class QrCodeScanner extends _i43.PageRouteInfo { - const QrCodeScanner({List<_i43.PageRouteInfo>? children}) +/// [_i30.QrCodeScanner] +class QrCodeScanner extends _i44.PageRouteInfo { + const QrCodeScanner({List<_i44.PageRouteInfo>? children}) : super(QrCodeScanner.name, initialChildren: children); static const String name = 'QrCodeScanner'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i29.QrCodeScanner(); + return const _i30.QrCodeScanner(); }, ); } /// generated route for -/// [_i30.ReportIssue] -class ReportIssue extends _i43.PageRouteInfo { +/// [_i31.ReportIssue] +class ReportIssue extends _i44.PageRouteInfo { ReportIssue({ - _i44.Key? key, + _i45.Key? key, String? description, String? type, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( ReportIssue.name, args: ReportIssueArgs(key: key, description: description, type: type), @@ -1078,13 +1095,13 @@ class ReportIssue extends _i43.PageRouteInfo { static const String name = 'ReportIssue'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const ReportIssueArgs(), ); - return _i30.ReportIssue( + return _i31.ReportIssue( key: args.key, description: args.description, type: args.type, @@ -1096,7 +1113,7 @@ class ReportIssue extends _i43.PageRouteInfo { class ReportIssueArgs { const ReportIssueArgs({this.key, this.description, this.type}); - final _i44.Key? key; + final _i45.Key? key; final String? description; @@ -1121,13 +1138,13 @@ class ReportIssueArgs { } /// generated route for -/// [_i31.ResetPassword] -class ResetPassword extends _i43.PageRouteInfo { +/// [_i32.ResetPassword] +class ResetPassword extends _i44.PageRouteInfo { ResetPassword({ - _i44.Key? key, + _i45.Key? key, required String email, required String code, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( ResetPassword.name, args: ResetPasswordArgs(key: key, email: email, code: code), @@ -1136,11 +1153,11 @@ class ResetPassword extends _i43.PageRouteInfo { static const String name = 'ResetPassword'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i31.ResetPassword( + return _i32.ResetPassword( key: args.key, email: args.email, code: args.code, @@ -1152,7 +1169,7 @@ class ResetPassword extends _i43.PageRouteInfo { class ResetPasswordArgs { const ResetPasswordArgs({this.key, required this.email, required this.code}); - final _i44.Key? key; + final _i45.Key? key; final String email; @@ -1175,12 +1192,12 @@ class ResetPasswordArgs { } /// generated route for -/// [_i32.ResetPasswordEmail] -class ResetPasswordEmail extends _i43.PageRouteInfo { +/// [_i33.ResetPasswordEmail] +class ResetPasswordEmail extends _i44.PageRouteInfo { ResetPasswordEmail({ - _i44.Key? key, + _i45.Key? key, String? email, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( ResetPasswordEmail.name, args: ResetPasswordEmailArgs(key: key, email: email), @@ -1189,13 +1206,13 @@ class ResetPasswordEmail extends _i43.PageRouteInfo { static const String name = 'ResetPasswordEmail'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const ResetPasswordEmailArgs(), ); - return _i32.ResetPasswordEmail(key: args.key, email: args.email); + return _i33.ResetPasswordEmail(key: args.key, email: args.email); }, ); } @@ -1203,7 +1220,7 @@ class ResetPasswordEmail extends _i43.PageRouteInfo { class ResetPasswordEmailArgs { const ResetPasswordEmailArgs({this.key, this.email}); - final _i44.Key? key; + final _i45.Key? key; final String? email; @@ -1224,61 +1241,61 @@ class ResetPasswordEmailArgs { } /// generated route for -/// [_i33.ServerSelection] -class ServerSelection extends _i43.PageRouteInfo { - const ServerSelection({List<_i43.PageRouteInfo>? children}) +/// [_i34.ServerSelection] +class ServerSelection extends _i44.PageRouteInfo { + const ServerSelection({List<_i44.PageRouteInfo>? children}) : super(ServerSelection.name, initialChildren: children); static const String name = 'ServerSelection'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i33.ServerSelection(); + return const _i34.ServerSelection(); }, ); } /// generated route for -/// [_i34.Setting] -class Setting extends _i43.PageRouteInfo { - const Setting({List<_i43.PageRouteInfo>? children}) +/// [_i35.Setting] +class Setting extends _i44.PageRouteInfo { + const Setting({List<_i44.PageRouteInfo>? children}) : super(Setting.name, initialChildren: children); static const String name = 'Setting'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i34.Setting(); + return const _i35.Setting(); }, ); } /// generated route for -/// [_i35.SignInEmail] -class SignInEmail extends _i43.PageRouteInfo { - const SignInEmail({List<_i43.PageRouteInfo>? children}) +/// [_i36.SignInEmail] +class SignInEmail extends _i44.PageRouteInfo { + const SignInEmail({List<_i44.PageRouteInfo>? children}) : super(SignInEmail.name, initialChildren: children); static const String name = 'SignInEmail'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i35.SignInEmail(); + return const _i36.SignInEmail(); }, ); } /// generated route for -/// [_i36.SignInPassword] -class SignInPassword extends _i43.PageRouteInfo { +/// [_i37.SignInPassword] +class SignInPassword extends _i44.PageRouteInfo { SignInPassword({ - _i44.Key? key, + _i45.Key? key, required String email, bool fromChangeEmail = false, - List<_i43.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( SignInPassword.name, args: SignInPasswordArgs( @@ -1291,11 +1308,11 @@ class SignInPassword extends _i43.PageRouteInfo { static const String name = 'SignInPassword'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); - return _i36.SignInPassword( + return _i37.SignInPassword( key: args.key, email: args.email, fromChangeEmail: args.fromChangeEmail, @@ -1311,7 +1328,7 @@ class SignInPasswordArgs { this.fromChangeEmail = false, }); - final _i44.Key? key; + final _i45.Key? key; final String email; @@ -1336,97 +1353,97 @@ class SignInPasswordArgs { } /// generated route for -/// [_i37.SmartRouting] -class SmartRouting extends _i43.PageRouteInfo { - const SmartRouting({List<_i43.PageRouteInfo>? children}) +/// [_i38.SmartRouting] +class SmartRouting extends _i44.PageRouteInfo { + const SmartRouting({List<_i44.PageRouteInfo>? children}) : super(SmartRouting.name, initialChildren: children); static const String name = 'SmartRouting'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i37.SmartRouting(); + return const _i38.SmartRouting(); }, ); } /// generated route for -/// [_i38.SplitTunneling] -class SplitTunneling extends _i43.PageRouteInfo { - const SplitTunneling({List<_i43.PageRouteInfo>? children}) +/// [_i39.SplitTunneling] +class SplitTunneling extends _i44.PageRouteInfo { + const SplitTunneling({List<_i44.PageRouteInfo>? children}) : super(SplitTunneling.name, initialChildren: children); static const String name = 'SplitTunneling'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i38.SplitTunneling(); + return const _i39.SplitTunneling(); }, ); } /// generated route for -/// [_i39.SplitTunnelingInfo] -class SplitTunnelingInfo extends _i43.PageRouteInfo { - const SplitTunnelingInfo({List<_i43.PageRouteInfo>? children}) +/// [_i40.SplitTunnelingInfo] +class SplitTunnelingInfo extends _i44.PageRouteInfo { + const SplitTunnelingInfo({List<_i44.PageRouteInfo>? children}) : super(SplitTunnelingInfo.name, initialChildren: children); static const String name = 'SplitTunnelingInfo'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i39.SplitTunnelingInfo(); + return const _i40.SplitTunnelingInfo(); }, ); } /// generated route for -/// [_i40.Support] -class Support extends _i43.PageRouteInfo { - const Support({List<_i43.PageRouteInfo>? children}) +/// [_i41.Support] +class Support extends _i44.PageRouteInfo { + const Support({List<_i44.PageRouteInfo>? children}) : super(Support.name, initialChildren: children); static const String name = 'Support'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i40.Support(); + return const _i41.Support(); }, ); } /// generated route for -/// [_i41.VPNSetting] -class VPNSetting extends _i43.PageRouteInfo { - const VPNSetting({List<_i43.PageRouteInfo>? children}) +/// [_i42.VPNSetting] +class VPNSetting extends _i44.PageRouteInfo { + const VPNSetting({List<_i44.PageRouteInfo>? children}) : super(VPNSetting.name, initialChildren: children); static const String name = 'VPNSetting'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i41.VPNSetting(); + return const _i42.VPNSetting(); }, ); } /// generated route for -/// [_i42.WebsiteSplitTunneling] -class WebsiteSplitTunneling extends _i43.PageRouteInfo { - const WebsiteSplitTunneling({List<_i43.PageRouteInfo>? children}) +/// [_i43.WebsiteSplitTunneling] +class WebsiteSplitTunneling extends _i44.PageRouteInfo { + const WebsiteSplitTunneling({List<_i44.PageRouteInfo>? children}) : super(WebsiteSplitTunneling.name, initialChildren: children); static const String name = 'WebsiteSplitTunneling'; - static _i43.PageInfo page = _i43.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { - return const _i42.WebsiteSplitTunneling(); + return const _i43.WebsiteSplitTunneling(); }, ); } diff --git a/lib/core/services/db/objectbox-model.json b/lib/core/services/db/objectbox-model.json index 55d7ed9144..7ee88d1949 100644 --- a/lib/core/services/db/objectbox-model.json +++ b/lib/core/services/db/objectbox-model.json @@ -57,90 +57,6 @@ ], "relations": [] }, - { - "id": "2:687217704776011576", - "lastPropertyId": "21:1946758950007753981", - "name": "AppSetting", - "properties": [ - { - "id": "1:3510248969077851513", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "2:9205281046748929972", - "name": "isPro", - "type": 1 - }, - { - "id": "3:3039149514872679626", - "name": "isSplitTunnelingOn", - "type": 1 - }, - { - "id": "4:8380353672446932820", - "name": "locale", - "type": 9 - }, - { - "id": "5:2654649825181931771", - "name": "oAuthToken", - "type": 9 - }, - { - "id": "6:6744815296056712828", - "name": "userLoggedIn", - "type": 1 - }, - { - "id": "7:7437540425271471596", - "name": "blockAds", - "type": 1 - }, - { - "id": "8:2584154697741095523", - "name": "email", - "type": 9 - }, - { - "id": "9:4176228116314272090", - "name": "showSplashScreen", - "type": 1 - }, - { - "id": "13:8918901309223826671", - "name": "telemetryConsent", - "type": 1 - }, - { - "id": "14:2408270352417603228", - "name": "telemetryDialogDismissed", - "type": 1 - }, - { - "id": "15:2605651149110192739", - "name": "successfulConnection", - "type": 1 - }, - { - "id": "17:557133969672494375", - "name": "routingModeRaw", - "type": 9 - }, - { - "id": "20:4262300231135451242", - "name": "dataCapThreshold", - "type": 9 - }, - { - "id": "21:1946758950007753981", - "name": "onboardingCompleted", - "type": 1 - } - ], - "relations": [] - }, { "id": "3:4249170330039132700", "lastPropertyId": "4:4534248771562227303", @@ -685,9 +601,98 @@ } ], "relations": [] + }, + { + "id": "17:8661061886838292286", + "lastPropertyId": "16:8049257509815119733", + "name": "AppSetting", + "properties": [ + { + "id": "1:8037386487668546069", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:1591384077759803365", + "name": "isPro", + "type": 1 + }, + { + "id": "3:5292415584449464820", + "name": "isSplitTunnelingOn", + "type": 1 + }, + { + "id": "4:3266138521563130663", + "name": "locale", + "type": 9 + }, + { + "id": "5:8115799101639218498", + "name": "oAuthToken", + "type": 9 + }, + { + "id": "6:8211717273441765679", + "name": "userLoggedIn", + "type": 1 + }, + { + "id": "7:8907045160547700789", + "name": "blockAds", + "type": 1 + }, + { + "id": "8:567693350846855659", + "name": "email", + "type": 9 + }, + { + "id": "9:456902696178716206", + "name": "showSplashScreen", + "type": 1 + }, + { + "id": "10:7148545157010430280", + "name": "telemetryDialogDismissed", + "type": 1 + }, + { + "id": "11:4439176666553164584", + "name": "telemetryConsent", + "type": 1 + }, + { + "id": "12:3699987776229950970", + "name": "successfulConnection", + "type": 1 + }, + { + "id": "13:91293558085631614", + "name": "routingModeRaw", + "type": 9 + }, + { + "id": "14:6638341417583612329", + "name": "dataCapThreshold", + "type": 9 + }, + { + "id": "15:5612718988166415962", + "name": "onboardingCompleted", + "type": 1 + }, + { + "id": "16:8049257509815119733", + "name": "themeMode", + "type": 9 + } + ], + "relations": [] } ], - "lastEntityId": "16:7100413957344193553", + "lastEntityId": "17:8661061886838292286", "lastIndexId": "3:1452151582306513699", "lastRelationId": "3:5180174885065282242", "lastSequenceId": "0:0", @@ -695,7 +700,8 @@ "modelVersionParserMinimum": 5, "retiredEntityUids": [ 2570208090016598017, - 893519286503285129 + 893519286503285129, + 687217704776011576 ], "retiredIndexUids": [], "retiredPropertyUids": [ @@ -715,7 +721,22 @@ 6825758662513353714, 4485043618273916447, 1036551397142037630, - 1521778634983396518 + 1521778634983396518, + 3510248969077851513, + 9205281046748929972, + 3039149514872679626, + 8380353672446932820, + 2654649825181931771, + 6744815296056712828, + 7437540425271471596, + 2584154697741095523, + 4176228116314272090, + 8918901309223826671, + 2408270352417603228, + 2605651149110192739, + 557133969672494375, + 4262300231135451242, + 1946758950007753981 ], "retiredRelationUids": [], "version": 1 diff --git a/lib/core/services/db/objectbox.g.dart b/lib/core/services/db/objectbox.g.dart index 55954c3232..9d426550d7 100644 --- a/lib/core/services/db/objectbox.g.dart +++ b/lib/core/services/db/objectbox.g.dart @@ -90,106 +90,6 @@ final _entities = [ relations: [], backlinks: [], ), - obx_int.ModelEntity( - id: const obx_int.IdUid(2, 687217704776011576), - name: 'AppSetting', - lastPropertyId: const obx_int.IdUid(21, 1946758950007753981), - flags: 0, - properties: [ - obx_int.ModelProperty( - id: const obx_int.IdUid(1, 3510248969077851513), - name: 'id', - type: 6, - flags: 1, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(2, 9205281046748929972), - name: 'isPro', - type: 1, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(3, 3039149514872679626), - name: 'isSplitTunnelingOn', - type: 1, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(4, 8380353672446932820), - name: 'locale', - type: 9, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(5, 2654649825181931771), - name: 'oAuthToken', - type: 9, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(6, 6744815296056712828), - name: 'userLoggedIn', - type: 1, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(7, 7437540425271471596), - name: 'blockAds', - type: 1, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(8, 2584154697741095523), - name: 'email', - type: 9, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(9, 4176228116314272090), - name: 'showSplashScreen', - type: 1, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(13, 8918901309223826671), - name: 'telemetryConsent', - type: 1, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(14, 2408270352417603228), - name: 'telemetryDialogDismissed', - type: 1, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(15, 2605651149110192739), - name: 'successfulConnection', - type: 1, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(17, 557133969672494375), - name: 'routingModeRaw', - type: 9, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(20, 4262300231135451242), - name: 'dataCapThreshold', - type: 9, - flags: 0, - ), - obx_int.ModelProperty( - id: const obx_int.IdUid(21, 1946758950007753981), - name: 'onboardingCompleted', - type: 1, - flags: 0, - ), - ], - relations: [], - backlinks: [], - ), obx_int.ModelEntity( id: const obx_int.IdUid(3, 4249170330039132700), name: 'DeviceEntity', @@ -826,6 +726,112 @@ final _entities = [ relations: [], backlinks: [], ), + obx_int.ModelEntity( + id: const obx_int.IdUid(17, 8661061886838292286), + name: 'AppSetting', + lastPropertyId: const obx_int.IdUid(16, 8049257509815119733), + flags: 0, + properties: [ + obx_int.ModelProperty( + id: const obx_int.IdUid(1, 8037386487668546069), + name: 'id', + type: 6, + flags: 1, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(2, 1591384077759803365), + name: 'isPro', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(3, 5292415584449464820), + name: 'isSplitTunnelingOn', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(4, 3266138521563130663), + name: 'locale', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(5, 8115799101639218498), + name: 'oAuthToken', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(6, 8211717273441765679), + name: 'userLoggedIn', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(7, 8907045160547700789), + name: 'blockAds', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(8, 567693350846855659), + name: 'email', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(9, 456902696178716206), + name: 'showSplashScreen', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(10, 7148545157010430280), + name: 'telemetryDialogDismissed', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(11, 4439176666553164584), + name: 'telemetryConsent', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(12, 3699987776229950970), + name: 'successfulConnection', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(13, 91293558085631614), + name: 'routingModeRaw', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(14, 6638341417583612329), + name: 'dataCapThreshold', + type: 9, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(15, 5612718988166415962), + name: 'onboardingCompleted', + type: 1, + flags: 0, + ), + obx_int.ModelProperty( + id: const obx_int.IdUid(16, 8049257509815119733), + name: 'themeMode', + type: 9, + flags: 0, + ), + ], + relations: [], + backlinks: [], + ), ]; /// Shortcut for [obx.Store.new] that passes [getObjectBoxModel] and for Flutter @@ -866,11 +872,15 @@ Future openStore({ obx_int.ModelDefinition getObjectBoxModel() { final model = obx_int.ModelInfo( entities: _entities, - lastEntityId: const obx_int.IdUid(16, 7100413957344193553), + lastEntityId: const obx_int.IdUid(17, 8661061886838292286), lastIndexId: const obx_int.IdUid(3, 1452151582306513699), lastRelationId: const obx_int.IdUid(3, 5180174885065282242), lastSequenceId: const obx_int.IdUid(0, 0), - retiredEntityUids: const [2570208090016598017, 893519286503285129], + retiredEntityUids: const [ + 2570208090016598017, + 893519286503285129, + 687217704776011576, + ], retiredIndexUids: const [], retiredPropertyUids: const [ 4825495648663424466, @@ -890,6 +900,21 @@ obx_int.ModelDefinition getObjectBoxModel() { 4485043618273916447, 1036551397142037630, 1521778634983396518, + 3510248969077851513, + 9205281046748929972, + 3039149514872679626, + 8380353672446932820, + 2654649825181931771, + 6744815296056712828, + 7437540425271471596, + 2584154697741095523, + 4176228116314272090, + 8918901309223826671, + 2408270352417603228, + 2605651149110192739, + 557133969672494375, + 4262300231135451242, + 1946758950007753981, ], retiredRelationUids: const [], modelVersion: 5, @@ -986,36 +1011,22 @@ obx_int.ModelDefinition getObjectBoxModel() { return object; }, ), - AppSetting: obx_int.EntityDefinition( + DeviceEntity: obx_int.EntityDefinition( model: _entities[1], - toOneRelations: (AppSetting object) => [], - toManyRelations: (AppSetting object) => {}, - getId: (AppSetting object) => object.id, - setId: (AppSetting object, int id) { + toOneRelations: (DeviceEntity object) => [], + toManyRelations: (DeviceEntity object) => {}, + getId: (DeviceEntity object) => object.id, + setId: (DeviceEntity object, int id) { object.id = id; }, - objectToFB: (AppSetting object, fb.Builder fbb) { - final localeOffset = fbb.writeString(object.locale); - final oAuthTokenOffset = fbb.writeString(object.oAuthToken); - final emailOffset = fbb.writeString(object.email); - final routingModeRawOffset = fbb.writeString(object.routingModeRaw); - final dataCapThresholdOffset = fbb.writeString(object.dataCapThreshold); - fbb.startTable(22); + objectToFB: (DeviceEntity object, fb.Builder fbb) { + final deviceIdOffset = fbb.writeString(object.deviceId); + final nameOffset = fbb.writeString(object.name); + fbb.startTable(5); fbb.addInt64(0, object.id); - fbb.addBool(1, object.isPro); - fbb.addBool(2, object.isSplitTunnelingOn); - fbb.addOffset(3, localeOffset); - fbb.addOffset(4, oAuthTokenOffset); - fbb.addBool(5, object.userLoggedIn); - fbb.addBool(6, object.blockAds); - fbb.addOffset(7, emailOffset); - fbb.addBool(8, object.showSplashScreen); - fbb.addBool(12, object.telemetryConsent); - fbb.addBool(13, object.telemetryDialogDismissed); - fbb.addBool(14, object.successfulConnection); - fbb.addOffset(16, routingModeRawOffset); - fbb.addOffset(19, dataCapThresholdOffset); - fbb.addBool(20, object.onboardingCompleted); + fbb.addOffset(1, deviceIdOffset); + fbb.addOffset(2, nameOffset); + fbb.addInt64(3, object.created); fbb.finish(fbb.endTable()); return object.id; }, @@ -1028,148 +1039,30 @@ obx_int.ModelDefinition getObjectBoxModel() { 4, 0, ); - final isProParam = const fb.BoolReader().vTableGet( - buffer, - rootOffset, - 6, - false, - ); - final isSplitTunnelingOnParam = const fb.BoolReader().vTableGet( - buffer, - rootOffset, - 8, - false, - ); - final userLoggedInParam = const fb.BoolReader().vTableGet( - buffer, - rootOffset, - 14, - false, - ); - final oAuthTokenParam = const fb.StringReader( - asciiOptimization: true, - ).vTableGet(buffer, rootOffset, 12, ''); - final blockAdsParam = const fb.BoolReader().vTableGet( - buffer, - rootOffset, - 16, - false, - ); - final emailParam = const fb.StringReader( + final deviceIdParam = const fb.StringReader( asciiOptimization: true, - ).vTableGet(buffer, rootOffset, 18, ''); - final localeParam = const fb.StringReader( + ).vTableGet(buffer, rootOffset, 6, ''); + final nameParam = const fb.StringReader( asciiOptimization: true, - ).vTableGet(buffer, rootOffset, 10, ''); - final showSplashScreenParam = const fb.BoolReader().vTableGet( + ).vTableGet(buffer, rootOffset, 8, ''); + final createdParam = const fb.Int64Reader().vTableGet( buffer, rootOffset, - 20, - false, + 10, + 0, ); - final telemetryDialogDismissedParam = const fb.BoolReader().vTableGet( - buffer, - rootOffset, - 30, - false, - ); - final telemetryConsentParam = const fb.BoolReader().vTableGet( - buffer, - rootOffset, - 28, - false, - ); - final successfulConnectionParam = const fb.BoolReader().vTableGet( - buffer, - rootOffset, - 32, - false, - ); - final routingModeRawParam = const fb.StringReader( - asciiOptimization: true, - ).vTableGet(buffer, rootOffset, 36, ''); - final dataCapThresholdParam = const fb.StringReader( - asciiOptimization: true, - ).vTableGet(buffer, rootOffset, 42, ''); - final onboardingCompletedParam = const fb.BoolReader().vTableGet( - buffer, - rootOffset, - 44, - false, - ); - final object = AppSetting( - id: idParam, - isPro: isProParam, - isSplitTunnelingOn: isSplitTunnelingOnParam, - userLoggedIn: userLoggedInParam, - oAuthToken: oAuthTokenParam, - blockAds: blockAdsParam, - email: emailParam, - locale: localeParam, - showSplashScreen: showSplashScreenParam, - telemetryDialogDismissed: telemetryDialogDismissedParam, - telemetryConsent: telemetryConsentParam, - successfulConnection: successfulConnectionParam, - routingModeRaw: routingModeRawParam, - dataCapThreshold: dataCapThresholdParam, - onboardingCompleted: onboardingCompletedParam, - ); - - return object; - }, - ), - DeviceEntity: obx_int.EntityDefinition( - model: _entities[2], - toOneRelations: (DeviceEntity object) => [], - toManyRelations: (DeviceEntity object) => {}, - getId: (DeviceEntity object) => object.id, - setId: (DeviceEntity object, int id) { - object.id = id; - }, - objectToFB: (DeviceEntity object, fb.Builder fbb) { - final deviceIdOffset = fbb.writeString(object.deviceId); - final nameOffset = fbb.writeString(object.name); - fbb.startTable(5); - fbb.addInt64(0, object.id); - fbb.addOffset(1, deviceIdOffset); - fbb.addOffset(2, nameOffset); - fbb.addInt64(3, object.created); - fbb.finish(fbb.endTable()); - return object.id; - }, - objectFromFB: (obx.Store store, ByteData fbData) { - final buffer = fb.BufferContext(fbData); - final rootOffset = buffer.derefObject(0); - final idParam = const fb.Int64Reader().vTableGet( - buffer, - rootOffset, - 4, - 0, - ); - final deviceIdParam = const fb.StringReader( - asciiOptimization: true, - ).vTableGet(buffer, rootOffset, 6, ''); - final nameParam = const fb.StringReader( - asciiOptimization: true, - ).vTableGet(buffer, rootOffset, 8, ''); - final createdParam = const fb.Int64Reader().vTableGet( - buffer, - rootOffset, - 10, - 0, - ); - final object = DeviceEntity( - id: idParam, - deviceId: deviceIdParam, - name: nameParam, - created: createdParam, + final object = DeviceEntity( + id: idParam, + deviceId: deviceIdParam, + name: nameParam, + created: createdParam, ); return object; }, ), PlanEntity: obx_int.EntityDefinition( - model: _entities[3], + model: _entities[2], toOneRelations: (PlanEntity object) => [], toManyRelations: (PlanEntity object) => {}, getId: (PlanEntity object) => object.id, @@ -1233,7 +1126,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), PlansDataEntity: obx_int.EntityDefinition( - model: _entities[4], + model: _entities[3], toOneRelations: (PlansDataEntity object) => [object.providers], toManyRelations: (PlansDataEntity object) => { obx_int.RelInfo.toMany(1, object.id): object.plans, @@ -1271,7 +1164,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), PrivateServerEntity: obx_int.EntityDefinition( - model: _entities[5], + model: _entities[4], toOneRelations: (PrivateServerEntity object) => [], toManyRelations: (PrivateServerEntity object) => {}, getId: (PrivateServerEntity object) => object.id, @@ -1356,7 +1249,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), ProvidersEntity: obx_int.EntityDefinition( - model: _entities[6], + model: _entities[5], toOneRelations: (ProvidersEntity object) => [], toManyRelations: (ProvidersEntity object) => {}, getId: (ProvidersEntity object) => object.id, @@ -1391,7 +1284,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), PurchaseEntity: obx_int.EntityDefinition( - model: _entities[7], + model: _entities[6], toOneRelations: (PurchaseEntity object) => [], toManyRelations: (PurchaseEntity object) => {}, getId: (PurchaseEntity object) => object.id, @@ -1424,7 +1317,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), SubscriptionDataEntity: obx_int.EntityDefinition( - model: _entities[8], + model: _entities[7], toOneRelations: (SubscriptionDataEntity object) => [], toManyRelations: (SubscriptionDataEntity object) => {}, getId: (SubscriptionDataEntity object) => object.id, @@ -1516,7 +1409,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), UserDataEntity: obx_int.EntityDefinition( - model: _entities[9], + model: _entities[8], toOneRelations: (UserDataEntity object) => [object.subscriptionData], toManyRelations: (UserDataEntity object) => { obx_int.RelInfo.toMany(2, object.id): object.devices, @@ -1696,7 +1589,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), UserResponseEntity: obx_int.EntityDefinition( - model: _entities[10], + model: _entities[9], toOneRelations: (UserResponseEntity object) => [object.legacyUserData], toManyRelations: (UserResponseEntity object) => { obx_int.RelInfo.toMany(3, object.id): @@ -1771,7 +1664,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), Website: obx_int.EntityDefinition( - model: _entities[11], + model: _entities[10], toOneRelations: (Website object) => [], toManyRelations: (Website object) => {}, getId: (Website object) => object.id, @@ -1804,7 +1697,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), ServerLocationEntity: obx_int.EntityDefinition( - model: _entities[12], + model: _entities[11], toOneRelations: (ServerLocationEntity object) => [], toManyRelations: (ServerLocationEntity object) => {}, getId: (ServerLocationEntity object) => object.id, @@ -1876,7 +1769,7 @@ obx_int.ModelDefinition getObjectBoxModel() { }, ), DeveloperModeEntity: obx_int.EntityDefinition( - model: _entities[13], + model: _entities[12], toOneRelations: (DeveloperModeEntity object) => [], toManyRelations: (DeveloperModeEntity object) => {}, getId: (DeveloperModeEntity object) => object.id, @@ -1911,6 +1804,144 @@ obx_int.ModelDefinition getObjectBoxModel() { testPlayPurchaseEnabled: testPlayPurchaseEnabledParam, )..id = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); + return object; + }, + ), + AppSetting: obx_int.EntityDefinition( + model: _entities[13], + toOneRelations: (AppSetting object) => [], + toManyRelations: (AppSetting object) => {}, + getId: (AppSetting object) => object.id, + setId: (AppSetting object, int id) { + object.id = id; + }, + objectToFB: (AppSetting object, fb.Builder fbb) { + final localeOffset = fbb.writeString(object.locale); + final oAuthTokenOffset = fbb.writeString(object.oAuthToken); + final emailOffset = fbb.writeString(object.email); + final routingModeRawOffset = fbb.writeString(object.routingModeRaw); + final dataCapThresholdOffset = fbb.writeString(object.dataCapThreshold); + final themeModeOffset = fbb.writeString(object.themeMode); + fbb.startTable(17); + fbb.addInt64(0, object.id); + fbb.addBool(1, object.isPro); + fbb.addBool(2, object.isSplitTunnelingOn); + fbb.addOffset(3, localeOffset); + fbb.addOffset(4, oAuthTokenOffset); + fbb.addBool(5, object.userLoggedIn); + fbb.addBool(6, object.blockAds); + fbb.addOffset(7, emailOffset); + fbb.addBool(8, object.showSplashScreen); + fbb.addBool(9, object.telemetryDialogDismissed); + fbb.addBool(10, object.telemetryConsent); + fbb.addBool(11, object.successfulConnection); + fbb.addOffset(12, routingModeRawOffset); + fbb.addOffset(13, dataCapThresholdOffset); + fbb.addBool(14, object.onboardingCompleted); + fbb.addOffset(15, themeModeOffset); + fbb.finish(fbb.endTable()); + return object.id; + }, + objectFromFB: (obx.Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + final idParam = const fb.Int64Reader().vTableGet( + buffer, + rootOffset, + 4, + 0, + ); + final isProParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 6, + false, + ); + final isSplitTunnelingOnParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 8, + false, + ); + final userLoggedInParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 14, + false, + ); + final oAuthTokenParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGet(buffer, rootOffset, 12, ''); + final blockAdsParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 16, + false, + ); + final emailParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGet(buffer, rootOffset, 18, ''); + final localeParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGet(buffer, rootOffset, 10, ''); + final showSplashScreenParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 20, + false, + ); + final telemetryDialogDismissedParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 22, + false, + ); + final telemetryConsentParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 24, + false, + ); + final successfulConnectionParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 26, + false, + ); + final routingModeRawParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGet(buffer, rootOffset, 28, ''); + final dataCapThresholdParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGet(buffer, rootOffset, 30, ''); + final onboardingCompletedParam = const fb.BoolReader().vTableGet( + buffer, + rootOffset, + 32, + false, + ); + final themeModeParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGet(buffer, rootOffset, 34, ''); + final object = AppSetting( + id: idParam, + isPro: isProParam, + isSplitTunnelingOn: isSplitTunnelingOnParam, + userLoggedIn: userLoggedInParam, + oAuthToken: oAuthTokenParam, + blockAds: blockAdsParam, + email: emailParam, + locale: localeParam, + showSplashScreen: showSplashScreenParam, + telemetryDialogDismissed: telemetryDialogDismissedParam, + telemetryConsent: telemetryConsentParam, + successfulConnection: successfulConnectionParam, + routingModeRaw: routingModeRawParam, + dataCapThreshold: dataCapThresholdParam, + onboardingCompleted: onboardingCompletedParam, + themeMode: themeModeParam, + ); + return object; }, ), @@ -1967,104 +1998,26 @@ class AppData_ { ); } -/// [AppSetting] entity fields to define ObjectBox queries. -class AppSetting_ { - /// See [AppSetting.id]. - static final id = obx.QueryIntegerProperty( - _entities[1].properties[0], - ); - - /// See [AppSetting.isPro]. - static final isPro = obx.QueryBooleanProperty( - _entities[1].properties[1], - ); - - /// See [AppSetting.isSplitTunnelingOn]. - static final isSplitTunnelingOn = obx.QueryBooleanProperty( - _entities[1].properties[2], - ); - - /// See [AppSetting.locale]. - static final locale = obx.QueryStringProperty( - _entities[1].properties[3], - ); - - /// See [AppSetting.oAuthToken]. - static final oAuthToken = obx.QueryStringProperty( - _entities[1].properties[4], - ); - - /// See [AppSetting.userLoggedIn]. - static final userLoggedIn = obx.QueryBooleanProperty( - _entities[1].properties[5], - ); - - /// See [AppSetting.blockAds]. - static final blockAds = obx.QueryBooleanProperty( - _entities[1].properties[6], - ); - - /// See [AppSetting.email]. - static final email = obx.QueryStringProperty( - _entities[1].properties[7], - ); - - /// See [AppSetting.showSplashScreen]. - static final showSplashScreen = obx.QueryBooleanProperty( - _entities[1].properties[8], - ); - - /// See [AppSetting.telemetryConsent]. - static final telemetryConsent = obx.QueryBooleanProperty( - _entities[1].properties[9], - ); - - /// See [AppSetting.telemetryDialogDismissed]. - static final telemetryDialogDismissed = obx.QueryBooleanProperty( - _entities[1].properties[10], - ); - - /// See [AppSetting.successfulConnection]. - static final successfulConnection = obx.QueryBooleanProperty( - _entities[1].properties[11], - ); - - /// See [AppSetting.routingModeRaw]. - static final routingModeRaw = obx.QueryStringProperty( - _entities[1].properties[12], - ); - - /// See [AppSetting.dataCapThreshold]. - static final dataCapThreshold = obx.QueryStringProperty( - _entities[1].properties[13], - ); - - /// See [AppSetting.onboardingCompleted]. - static final onboardingCompleted = obx.QueryBooleanProperty( - _entities[1].properties[14], - ); -} - /// [DeviceEntity] entity fields to define ObjectBox queries. class DeviceEntity_ { /// See [DeviceEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[2].properties[0], + _entities[1].properties[0], ); /// See [DeviceEntity.deviceId]. static final deviceId = obx.QueryStringProperty( - _entities[2].properties[1], + _entities[1].properties[1], ); /// See [DeviceEntity.name]. static final name = obx.QueryStringProperty( - _entities[2].properties[2], + _entities[1].properties[2], ); /// See [DeviceEntity.created]. static final created = obx.QueryIntegerProperty( - _entities[2].properties[3], + _entities[1].properties[3], ); } @@ -2072,37 +2025,37 @@ class DeviceEntity_ { class PlanEntity_ { /// See [PlanEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[3].properties[0], + _entities[2].properties[0], ); /// See [PlanEntity.planId]. static final planId = obx.QueryStringProperty( - _entities[3].properties[1], + _entities[2].properties[1], ); /// See [PlanEntity.description]. static final description = obx.QueryStringProperty( - _entities[3].properties[2], + _entities[2].properties[2], ); /// See [PlanEntity.usdPrice]. static final usdPrice = obx.QueryIntegerProperty( - _entities[3].properties[3], + _entities[2].properties[3], ); /// See [PlanEntity.priceJson]. static final priceJson = obx.QueryStringProperty( - _entities[3].properties[4], + _entities[2].properties[4], ); /// See [PlanEntity.expectedMonthlyPriceJson]. static final expectedMonthlyPriceJson = obx.QueryStringProperty( - _entities[3].properties[5], + _entities[2].properties[5], ); /// See [PlanEntity.bestValue]. static final bestValue = obx.QueryBooleanProperty( - _entities[3].properties[6], + _entities[2].properties[6], ); } @@ -2110,18 +2063,18 @@ class PlanEntity_ { class PlansDataEntity_ { /// See [PlansDataEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[4].properties[0], + _entities[3].properties[0], ); /// See [PlansDataEntity.providers]. static final providers = obx.QueryRelationToOne( - _entities[4].properties[1], + _entities[3].properties[1], ); /// see [PlansDataEntity.plans] static final plans = obx.QueryRelationToMany( - _entities[4].relations[0], + _entities[3].relations[0], ); } @@ -2129,51 +2082,51 @@ class PlansDataEntity_ { class PrivateServerEntity_ { /// See [PrivateServerEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[5].properties[0], + _entities[4].properties[0], ); /// See [PrivateServerEntity.serverName]. static final serverName = obx.QueryStringProperty( - _entities[5].properties[1], + _entities[4].properties[1], ); /// See [PrivateServerEntity.externalIp]. static final externalIp = obx.QueryStringProperty( - _entities[5].properties[2], + _entities[4].properties[2], ); /// See [PrivateServerEntity.port]. static final port = obx.QueryStringProperty( - _entities[5].properties[3], + _entities[4].properties[3], ); /// See [PrivateServerEntity.accessToken]. static final accessToken = obx.QueryStringProperty( - _entities[5].properties[4], + _entities[4].properties[4], ); /// See [PrivateServerEntity.isJoined]. static final isJoined = obx.QueryBooleanProperty( - _entities[5].properties[5], + _entities[4].properties[5], ); /// See [PrivateServerEntity.userSelected]. static final userSelected = obx.QueryBooleanProperty( - _entities[5].properties[6], + _entities[4].properties[6], ); /// See [PrivateServerEntity.serverLocationName]. static final serverLocationName = - obx.QueryStringProperty(_entities[5].properties[7]); + obx.QueryStringProperty(_entities[4].properties[7]); /// See [PrivateServerEntity.serverCountryCode]. static final serverCountryCode = obx.QueryStringProperty( - _entities[5].properties[8], + _entities[4].properties[8], ); /// See [PrivateServerEntity.protocol]. static final protocol = obx.QueryStringProperty( - _entities[5].properties[9], + _entities[4].properties[9], ); } @@ -2181,17 +2134,17 @@ class PrivateServerEntity_ { class ProvidersEntity_ { /// See [ProvidersEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[6].properties[0], + _entities[5].properties[0], ); /// See [ProvidersEntity.androidJson]. static final androidJson = obx.QueryStringProperty( - _entities[6].properties[1], + _entities[5].properties[1], ); /// See [ProvidersEntity.desktopJson]. static final desktopJson = obx.QueryStringProperty( - _entities[6].properties[2], + _entities[5].properties[2], ); } @@ -2199,12 +2152,12 @@ class ProvidersEntity_ { class PurchaseEntity_ { /// See [PurchaseEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[7].properties[0], + _entities[6].properties[0], ); /// See [PurchaseEntity.plan]. static final plan = obx.QueryStringProperty( - _entities[7].properties[1], + _entities[6].properties[1], ); } @@ -2212,58 +2165,58 @@ class PurchaseEntity_ { class SubscriptionDataEntity_ { /// See [SubscriptionDataEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[8].properties[0], + _entities[7].properties[0], ); /// See [SubscriptionDataEntity.planID]. static final planID = obx.QueryStringProperty( - _entities[8].properties[1], + _entities[7].properties[1], ); /// See [SubscriptionDataEntity.stripeCustomerID]. static final stripeCustomerID = obx.QueryStringProperty( - _entities[8].properties[2], + _entities[7].properties[2], ); /// See [SubscriptionDataEntity.startAt]. static final startAt = obx.QueryStringProperty( - _entities[8].properties[3], + _entities[7].properties[3], ); /// See [SubscriptionDataEntity.cancelledAt]. static final cancelledAt = obx.QueryStringProperty( - _entities[8].properties[4], + _entities[7].properties[4], ); /// See [SubscriptionDataEntity.autoRenew]. static final autoRenew = obx.QueryBooleanProperty( - _entities[8].properties[5], + _entities[7].properties[5], ); /// See [SubscriptionDataEntity.subscriptionID]. static final subscriptionID = obx.QueryStringProperty( - _entities[8].properties[6], + _entities[7].properties[6], ); /// See [SubscriptionDataEntity.status]. static final status = obx.QueryStringProperty( - _entities[8].properties[7], + _entities[7].properties[7], ); /// See [SubscriptionDataEntity.provider]. static final provider = obx.QueryStringProperty( - _entities[8].properties[8], + _entities[7].properties[8], ); /// See [SubscriptionDataEntity.createdAt]. static final createdAt = obx.QueryStringProperty( - _entities[8].properties[9], + _entities[7].properties[9], ); /// See [SubscriptionDataEntity.endAt]. static final endAt = obx.QueryStringProperty( - _entities[8].properties[10], + _entities[7].properties[10], ); } @@ -2271,123 +2224,123 @@ class SubscriptionDataEntity_ { class UserDataEntity_ { /// See [UserDataEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[9].properties[0], + _entities[8].properties[0], ); /// See [UserDataEntity.userId]. static final userId = obx.QueryIntegerProperty( - _entities[9].properties[1], + _entities[8].properties[1], ); /// See [UserDataEntity.code]. static final code = obx.QueryStringProperty( - _entities[9].properties[2], + _entities[8].properties[2], ); /// See [UserDataEntity.token]. static final token = obx.QueryStringProperty( - _entities[9].properties[3], + _entities[8].properties[3], ); /// See [UserDataEntity.referral]. static final referral = obx.QueryStringProperty( - _entities[9].properties[4], + _entities[8].properties[4], ); /// See [UserDataEntity.phone]. static final phone = obx.QueryStringProperty( - _entities[9].properties[5], + _entities[8].properties[5], ); /// See [UserDataEntity.email]. static final email = obx.QueryStringProperty( - _entities[9].properties[6], + _entities[8].properties[6], ); /// See [UserDataEntity.userStatus]. static final userStatus = obx.QueryStringProperty( - _entities[9].properties[7], + _entities[8].properties[7], ); /// See [UserDataEntity.userLevel]. static final userLevel = obx.QueryStringProperty( - _entities[9].properties[8], + _entities[8].properties[8], ); /// See [UserDataEntity.locale]. static final locale = obx.QueryStringProperty( - _entities[9].properties[9], + _entities[8].properties[9], ); /// See [UserDataEntity.expiration]. static final expiration = obx.QueryIntegerProperty( - _entities[9].properties[10], + _entities[8].properties[10], ); /// See [UserDataEntity.subscription]. static final subscription = obx.QueryStringProperty( - _entities[9].properties[11], + _entities[8].properties[11], ); /// See [UserDataEntity.bonusDays]. static final bonusDays = obx.QueryStringProperty( - _entities[9].properties[12], + _entities[8].properties[12], ); /// See [UserDataEntity.bonusMonths]. static final bonusMonths = obx.QueryStringProperty( - _entities[9].properties[13], + _entities[8].properties[13], ); /// See [UserDataEntity.yinbiEnabled]. static final yinbiEnabled = obx.QueryBooleanProperty( - _entities[9].properties[14], + _entities[8].properties[14], ); /// See [UserDataEntity.servers]. static final servers = obx.QueryStringProperty( - _entities[9].properties[15], + _entities[8].properties[15], ); /// See [UserDataEntity.inviters]. static final inviters = obx.QueryStringProperty( - _entities[9].properties[16], + _entities[8].properties[16], ); /// See [UserDataEntity.invitees]. static final invitees = obx.QueryStringProperty( - _entities[9].properties[17], + _entities[8].properties[17], ); /// See [UserDataEntity.purchases]. static final purchases = obx.QueryStringProperty( - _entities[9].properties[18], + _entities[8].properties[18], ); /// See [UserDataEntity.subscriptionData]. static final subscriptionData = obx.QueryRelationToOne( - _entities[9].properties[19], + _entities[8].properties[19], ); /// See [UserDataEntity.deviceID]. static final deviceID = obx.QueryStringProperty( - _entities[9].properties[20], + _entities[8].properties[20], ); /// See [UserDataEntity.unpassRegistered]. static final unpassRegistered = obx.QueryBooleanProperty( - _entities[9].properties[21], + _entities[8].properties[21], ); /// See [UserDataEntity.lastExpiredOn]. static final lastExpiredOn = obx.QueryIntegerProperty( - _entities[9].properties[22], + _entities[8].properties[22], ); /// see [UserDataEntity.devices] static final devices = obx.QueryRelationToMany( - _entities[9].relations[0], + _entities[8].relations[0], ); } @@ -2395,39 +2348,39 @@ class UserDataEntity_ { class UserResponseEntity_ { /// See [UserResponseEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[10].properties[0], + _entities[9].properties[0], ); /// See [UserResponseEntity.legacyID]. static final legacyID = obx.QueryIntegerProperty( - _entities[10].properties[1], + _entities[9].properties[1], ); /// See [UserResponseEntity.legacyToken]. static final legacyToken = obx.QueryStringProperty( - _entities[10].properties[2], + _entities[9].properties[2], ); /// See [UserResponseEntity.emailConfirmed]. static final emailConfirmed = obx.QueryBooleanProperty( - _entities[10].properties[3], + _entities[9].properties[3], ); /// See [UserResponseEntity.success]. static final success = obx.QueryBooleanProperty( - _entities[10].properties[4], + _entities[9].properties[4], ); /// See [UserResponseEntity.legacyUserData]. static final legacyUserData = obx.QueryRelationToOne( - _entities[10].properties[5], + _entities[9].properties[5], ); /// see [UserResponseEntity.devices] static final devices = obx.QueryRelationToMany( - _entities[10].relations[0], + _entities[9].relations[0], ); } @@ -2435,12 +2388,12 @@ class UserResponseEntity_ { class Website_ { /// See [Website.id]. static final id = obx.QueryIntegerProperty( - _entities[11].properties[0], + _entities[10].properties[0], ); /// See [Website.domain]. static final domain = obx.QueryStringProperty( - _entities[11].properties[1], + _entities[10].properties[1], ); } @@ -2448,47 +2401,47 @@ class Website_ { class ServerLocationEntity_ { /// See [ServerLocationEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[12].properties[0], + _entities[11].properties[0], ); /// See [ServerLocationEntity.serverName]. static final serverName = obx.QueryStringProperty( - _entities[12].properties[1], + _entities[11].properties[1], ); /// See [ServerLocationEntity.serverType]. static final serverType = obx.QueryStringProperty( - _entities[12].properties[2], + _entities[11].properties[2], ); /// See [ServerLocationEntity.countryCode]. static final countryCode = obx.QueryStringProperty( - _entities[12].properties[3], + _entities[11].properties[3], ); /// See [ServerLocationEntity.country]. static final country = obx.QueryStringProperty( - _entities[12].properties[4], + _entities[11].properties[4], ); /// See [ServerLocationEntity.city]. static final city = obx.QueryStringProperty( - _entities[12].properties[5], + _entities[11].properties[5], ); /// See [ServerLocationEntity.displayName]. static final displayName = obx.QueryStringProperty( - _entities[12].properties[6], + _entities[11].properties[6], ); /// See [ServerLocationEntity.autoLocationJson]. static final autoLocationJson = obx.QueryStringProperty( - _entities[12].properties[7], + _entities[11].properties[7], ); /// See [ServerLocationEntity.protocol]. static final protocol = obx.QueryStringProperty( - _entities[12].properties[8], + _entities[11].properties[8], ); } @@ -2496,18 +2449,101 @@ class ServerLocationEntity_ { class DeveloperModeEntity_ { /// See [DeveloperModeEntity.id]. static final id = obx.QueryIntegerProperty( - _entities[13].properties[0], + _entities[12].properties[0], ); /// See [DeveloperModeEntity.testPlayPurchaseEnabled]. static final testPlayPurchaseEnabled = obx.QueryBooleanProperty( - _entities[13].properties[1], + _entities[12].properties[1], ); /// See [DeveloperModeEntity.testStripePurchaseEnabled]. static final testStripePurchaseEnabled = obx.QueryBooleanProperty( - _entities[13].properties[2], + _entities[12].properties[2], ); } + +/// [AppSetting] entity fields to define ObjectBox queries. +class AppSetting_ { + /// See [AppSetting.id]. + static final id = obx.QueryIntegerProperty( + _entities[13].properties[0], + ); + + /// See [AppSetting.isPro]. + static final isPro = obx.QueryBooleanProperty( + _entities[13].properties[1], + ); + + /// See [AppSetting.isSplitTunnelingOn]. + static final isSplitTunnelingOn = obx.QueryBooleanProperty( + _entities[13].properties[2], + ); + + /// See [AppSetting.locale]. + static final locale = obx.QueryStringProperty( + _entities[13].properties[3], + ); + + /// See [AppSetting.oAuthToken]. + static final oAuthToken = obx.QueryStringProperty( + _entities[13].properties[4], + ); + + /// See [AppSetting.userLoggedIn]. + static final userLoggedIn = obx.QueryBooleanProperty( + _entities[13].properties[5], + ); + + /// See [AppSetting.blockAds]. + static final blockAds = obx.QueryBooleanProperty( + _entities[13].properties[6], + ); + + /// See [AppSetting.email]. + static final email = obx.QueryStringProperty( + _entities[13].properties[7], + ); + + /// See [AppSetting.showSplashScreen]. + static final showSplashScreen = obx.QueryBooleanProperty( + _entities[13].properties[8], + ); + + /// See [AppSetting.telemetryDialogDismissed]. + static final telemetryDialogDismissed = obx.QueryBooleanProperty( + _entities[13].properties[9], + ); + + /// See [AppSetting.telemetryConsent]. + static final telemetryConsent = obx.QueryBooleanProperty( + _entities[13].properties[10], + ); + + /// See [AppSetting.successfulConnection]. + static final successfulConnection = obx.QueryBooleanProperty( + _entities[13].properties[11], + ); + + /// See [AppSetting.routingModeRaw]. + static final routingModeRaw = obx.QueryStringProperty( + _entities[13].properties[12], + ); + + /// See [AppSetting.dataCapThreshold]. + static final dataCapThreshold = obx.QueryStringProperty( + _entities[13].properties[13], + ); + + /// See [AppSetting.onboardingCompleted]. + static final onboardingCompleted = obx.QueryBooleanProperty( + _entities[13].properties[14], + ); + + /// See [AppSetting.themeMode]. + static final themeMode = obx.QueryStringProperty( + _entities[13].properties[15], + ); +} diff --git a/lib/features/home/provider/app_setting_notifier.dart b/lib/features/home/provider/app_setting_notifier.dart index 5c90fa8097..dba9e1bdc3 100644 --- a/lib/features/home/provider/app_setting_notifier.dart +++ b/lib/features/home/provider/app_setting_notifier.dart @@ -117,6 +117,21 @@ class AppSettingNotifier extends _$AppSettingNotifier { update(state.copyWith(onboardingCompleted: value)); } + void setThemeMode(String mode) { + update(state.copyWith(themeMode: mode)); + } + + static ThemeMode resolveThemeMode(String raw) { + switch (raw) { + case 'light': + return ThemeMode.light; + case 'dark': + return ThemeMode.dark; + default: + return ThemeMode.system; + } + } + Locale _detectDeviceLocale() { final deviceLocale = PlatformDispatcher.instance.locale; return deviceLocale.languageCode == 'en' diff --git a/lib/features/home/provider/app_setting_notifier.g.dart b/lib/features/home/provider/app_setting_notifier.g.dart index ea5e7252b9..d2179455d2 100644 --- a/lib/features/home/provider/app_setting_notifier.g.dart +++ b/lib/features/home/provider/app_setting_notifier.g.dart @@ -42,7 +42,7 @@ final class AppSettingNotifierProvider } String _$appSettingNotifierHash() => - r'df70844cb02db440708d70e7ecb7c2e1bb353cae'; + r'be98c54ab91e84f9cc74e31fb163cfedd0b75b6e'; abstract class _$AppSettingNotifier extends $Notifier { AppSetting build(); diff --git a/lib/features/setting/appearance.dart b/lib/features/setting/appearance.dart new file mode 100644 index 0000000000..2bba1e3752 --- /dev/null +++ b/lib/features/setting/appearance.dart @@ -0,0 +1,92 @@ +import 'package:auto_route/annotations.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:lantern/core/common/common.dart'; +import 'package:lantern/features/home/provider/app_setting_notifier.dart'; + +@RoutePage(name: 'Appearance') +class Appearance extends StatelessWidget { + const Appearance({super.key}); + + @override + Widget build(BuildContext context) { + return BaseScreen( + title: 'appearance'.i18n, + body: Card( + child: AppearanceListView(), + ), + ); + } +} + +class AppearanceListView extends ConsumerWidget { + final ScrollController? scrollController; + + const AppearanceListView({super.key, this.scrollController}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final currentMode = ref.watch(appSettingProvider).themeMode; + + final options = [ + ('system', 'system'.i18n), + ('light', 'light'.i18n), + ('dark', 'dark'.i18n), + ]; + + return ListView.separated( + controller: scrollController, + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: options.length, + separatorBuilder: (_, __) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: DividerSpace(), + ), + itemBuilder: (context, index) { + final (value, label) = options[index]; + return AppTile( + label: label, + minHeight: 56, + trailing: Radio( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + value: value, + groupValue: currentMode, + onChanged: (selected) => _onSelect(selected!, ref, context), + activeColor: AppColors.blue7, + ), + onPressed: () => _onSelect(value, ref, context), + ); + }, + ); + } + + void _onSelect(String mode, WidgetRef ref, BuildContext context) { + ref.read(appSettingProvider.notifier).setThemeMode(mode); + appRouter.maybePop(); + } +} + +void showAppearanceBottomSheet({required BuildContext context}) { + showAppBottomSheet( + context: context, + title: 'appearance'.i18n, + scrollControlDisabledMaxHeightRatio: 0.35, + builder: (context, scrollController) { + return Flexible( + child: AppearanceListView(scrollController: scrollController), + ); + }, + ); +} + +String appearanceModeLabel(String mode) { + switch (mode) { + case 'light': + return 'light'.i18n; + case 'dark': + return 'dark'.i18n; + default: + return 'system'.i18n; + } +} diff --git a/lib/features/setting/setting.dart b/lib/features/setting/setting.dart index 37a29ea557..9a3b9646aa 100644 --- a/lib/features/setting/setting.dart +++ b/lib/features/setting/setting.dart @@ -11,6 +11,8 @@ import 'package:lantern/core/utils/pro_utils.dart'; import 'package:lantern/core/widgets/subscription_tags.dart'; import 'package:lantern/features/home/provider/app_setting_notifier.dart'; import 'package:lantern/features/home/provider/home_notifier.dart'; +import 'package:lantern/features/setting/appearance.dart' + show appearanceModeLabel, showAppearanceBottomSheet; import 'package:lantern/features/setting/follow_us.dart' show showFollowUsBottomSheet; @@ -49,6 +51,7 @@ class _SettingState extends ConsumerState { localIsPro && (localUser?.legacyUserData.unpassRegistered ?? false); final isAuthenticated = appSetting.userLoggedIn || hasProSession; final locale = appSetting.locale; + final themeMode = appSetting.themeMode; final textTheme = Theme.of(context).textTheme; final isUserPro = ref.watch(isUserProProvider); final user = ref.watch(homeProvider).value; @@ -138,6 +141,18 @@ class _SettingState extends ConsumerState { onPressed: () => settingMenuTap(_SettingType.language), ), DividerSpace(), + AppTile( + label: 'appearance'.i18n, + icon: AppImagePaths.theme, + trailing: Text( + appearanceModeLabel(themeMode), + style: textTheme.titleMedium!.copyWith( + color: context.textLink, + ), + ), + onPressed: () => settingMenuTap(_SettingType.appearance), + ), + DividerSpace(), if (PlatformUtils.isDesktop) AppTile( label: 'check_for_updates'.i18n, @@ -236,8 +251,12 @@ class _SettingState extends ConsumerState { appRouter.push(Language()); return; case _SettingType.appearance: - // TODO: Handle this case. - throw UnimplementedError(); + if (PlatformUtils.isDesktop) { + appRouter.push(const Appearance()); + return; + } + showAppearanceBottomSheet(context: context); + break; case _SettingType.support: appRouter.push(Support()); break; diff --git a/lib/features/system_tray/provider/system_tray_notifier.g.dart b/lib/features/system_tray/provider/system_tray_notifier.g.dart index 4bf2317da3..a0588dc96c 100644 --- a/lib/features/system_tray/provider/system_tray_notifier.g.dart +++ b/lib/features/system_tray/provider/system_tray_notifier.g.dart @@ -34,7 +34,7 @@ final class SystemTrayNotifierProvider } String _$systemTrayNotifierHash() => - r'dad25bb4331883026fb102a3a09821284461e4a9'; + r'7f8eea38f12db238a7749f8f51eaa87688b18e7e'; abstract class _$SystemTrayNotifier extends $AsyncNotifier { FutureOr build(); diff --git a/lib/lantern_app.dart b/lib/lantern_app.dart index aee6b51a44..7a40dc6b0e 100644 --- a/lib/lantern_app.dart +++ b/lib/lantern_app.dart @@ -158,7 +158,8 @@ class _LanternAppState extends ConsumerState { @override Widget build(BuildContext context) { - final locale = ref.watch(appSettingProvider).locale; + final appSetting = ref.watch(appSettingProvider); + final locale = appSetting.locale; Localization.defaultLocale = locale; return GlobalLoaderOverlay( overlayColor: Colors.black.withOpacity(0.5), @@ -181,10 +182,9 @@ class _LanternAppState extends ConsumerState { child: MaterialApp.router( locale: locale.toLocale, debugShowCheckedModeBanner: false, - theme: AppTheme.darkTheme(), - - themeMode: ThemeMode.light, + theme: AppTheme.appTheme(), darkTheme: AppTheme.darkTheme(), + themeMode: AppSettingNotifier.resolveThemeMode(appSetting.themeMode), supportedLocales: languages .map((lang) => Locale(lang.split('_').first, lang.split('_').last)) diff --git a/pubspec.lock b/pubspec.lock index 092c70130c..8ad7171fcd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1693,8 +1693,8 @@ packages: dependency: "direct main" description: path: "packages/tray_manager" - ref: "7987b6f3aea4fc6e512e91de150c8a6ce87df98d" - resolved-ref: "7987b6f3aea4fc6e512e91de150c8a6ce87df98d" + ref: e4f69663ca467c1108c1ccad9f55cf5a2154adc2 + resolved-ref: e4f69663ca467c1108c1ccad9f55cf5a2154adc2 url: "https://github.com/getlantern/tray_manager.git" source: git version: "0.5.1" From ea04e51f221c1a936ec12aac4729b11c39989c0c Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 15:19:23 +0530 Subject: [PATCH 04/14] connect with system UI and db --- assets/locales/en.po | 14 +++++++- lib/core/widgets/email_tag.dart | 2 +- lib/core/widgets/lantern_logo.dart | 1 + lib/core/widgets/subscription_tags.dart | 6 ++-- lib/core/widgets/vpn_status_indicator.dart | 1 + lib/features/auth/sign_in_password.dart | 4 +-- lib/features/onboarding/onboarding.dart | 21 +++++------ lib/features/vpn/location_setting.dart | 2 +- lib/features/vpn/vpn_status.dart | 1 + lib/features/vpn/vpn_switch.dart | 6 ++-- macos/Podfile.lock | 42 +++++++++++----------- 11 files changed, 58 insertions(+), 42 deletions(-) diff --git a/assets/locales/en.po b/assets/locales/en.po index cb8c8b02e7..2c38dd9cfc 100644 --- a/assets/locales/en.po +++ b/assets/locales/en.po @@ -1466,10 +1466,22 @@ msgstr "Your Pro plan was purchased through Google Play. Please manage your subs msgid "manage_subscription_apple_app_store" msgstr "Your Pro plan was purchased through the Apple App Store. Please manage your subscription from your Apple ID account settings." - msgid "create_account_error" msgstr "Create Account Error" +msgid "appearance" +msgstr "Appearance" + +msgid "light" +msgstr "Light" + +msgid "dark" +msgstr "Dark" + +msgid "system" +msgstr "System" + + diff --git a/lib/core/widgets/email_tag.dart b/lib/core/widgets/email_tag.dart index 9185059974..d62117e941 100644 --- a/lib/core/widgets/email_tag.dart +++ b/lib/core/widgets/email_tag.dart @@ -14,7 +14,7 @@ class EmailTag extends StatelessWidget { @override Widget build(BuildContext context) { return Chip( - color: WidgetStatePropertyAll(AppColors.blue1), + color: WidgetStatePropertyAll(context.bgCallout), elevation: 0, avatar: AppImage( path: AppImagePaths.email, diff --git a/lib/core/widgets/lantern_logo.dart b/lib/core/widgets/lantern_logo.dart index 94b41f601a..9269520d1c 100644 --- a/lib/core/widgets/lantern_logo.dart +++ b/lib/core/widgets/lantern_logo.dart @@ -34,6 +34,7 @@ class LanternLogo extends StatelessWidget { height: height, width: width, fit: BoxFit.contain, + ); } } diff --git a/lib/core/widgets/subscription_tags.dart b/lib/core/widgets/subscription_tags.dart index ae19beaf98..0f59e1222a 100644 --- a/lib/core/widgets/subscription_tags.dart +++ b/lib/core/widgets/subscription_tags.dart @@ -25,15 +25,15 @@ class SubscriptionTags extends StatelessWidget { vertical: 4, ), decoration: BoxDecoration( - color: isExpired ? AppColors.red2 : AppColors.green2, + color: isExpired ? context.statusErrorBg : context.statusSuccessBg, border: Border.all( - color: isExpired ? AppColors.red4 : AppColors.green4, + color: isExpired ? context.statusErrorBorder : context.statusSuccessBorder, ), borderRadius: BorderRadius.circular(8)), child: Text( isExpired ? 'subscription_expired'.i18n : 'pro'.i18n, style: textTheme.labelMedium!.copyWith( - color: isExpired ? AppColors.red8 : AppColors.green8, + color: isExpired ? context.statusErrorText : context.statusSuccessText, ), ), ); diff --git a/lib/core/widgets/vpn_status_indicator.dart b/lib/core/widgets/vpn_status_indicator.dart index 134a7c42d1..69647027a5 100644 --- a/lib/core/widgets/vpn_status_indicator.dart +++ b/lib/core/widgets/vpn_status_indicator.dart @@ -28,6 +28,7 @@ class VPNStatusIndicator extends StatelessWidget { return AppImage( path: indicator, + useThemeColor: false, color: status == VPNStatus.disconnected ? AppColors.gray3 : null, ); } diff --git a/lib/features/auth/sign_in_password.dart b/lib/features/auth/sign_in_password.dart index 0e2b2badf3..8e41e10184 100644 --- a/lib/features/auth/sign_in_password.dart +++ b/lib/features/auth/sign_in_password.dart @@ -59,7 +59,7 @@ class _SignInPasswordState extends ConsumerState { signInWithPassword(passwordController.text.trim()), onChanged: (value) {}, ), - SizedBox(height: 4), + SizedBox(height: 8), if (!widget.fromChangeEmail) Padding( padding: const EdgeInsets.symmetric(horizontal: defaultSize), @@ -104,7 +104,7 @@ class _SignInPasswordState extends ConsumerState { Widget _buildSuffix(ValueNotifier obscureText) { return AppImage( - color: context.textPromoIcon, + color: context.textPrimary, path: obscureText.value ? AppImagePaths.eyeHide : AppImagePaths.eye, onPressed: () { obscureText.value = !obscureText.value; diff --git a/lib/features/onboarding/onboarding.dart b/lib/features/onboarding/onboarding.dart index c35441d957..49bb8a9de8 100644 --- a/lib/features/onboarding/onboarding.dart +++ b/lib/features/onboarding/onboarding.dart @@ -46,7 +46,7 @@ class _OnboardingState extends ConsumerState { appBar: AppBar( leading: const SizedBox.shrink(), backgroundColor: context.bgElevated, - title: const LanternLogo(), + title: LanternLogo(color: context.textPrimary), bottom: PreferredSize( preferredSize: Size.fromHeight(0), child: DividerSpace(padding: EdgeInsets.zero), @@ -91,6 +91,7 @@ class _OnboardingState extends ConsumerState { children: [ AppImage( path: AppImagePaths.appIconSVG, + useThemeColor: false, ), SizedBox(height: 48), Text( @@ -164,7 +165,7 @@ class _OnboardingState extends ConsumerState { AppTile( icon: Padding( padding: const EdgeInsets.only(top: 5.0), - child: AppImage(path: AppImagePaths.smartRouteMode), + child: AppImage(path: AppImagePaths.smartRouteMode,useThemeColor: false,), ), label: '', titleAlignment: ListTileTitleAlignment.top, @@ -185,7 +186,7 @@ class _OnboardingState extends ConsumerState { AppTile( icon: Padding( padding: const EdgeInsets.only(top: 5.0), - child: AppImage(path: AppImagePaths.advanceProtocol), + child: AppImage(path: AppImagePaths.advanceProtocol,useThemeColor: false), ), label: '', titleAlignment: ListTileTitleAlignment.top, @@ -206,7 +207,7 @@ class _OnboardingState extends ConsumerState { AppTile( icon: Padding( padding: const EdgeInsets.only(top: 5.0), - child: AppImage(path: AppImagePaths.privateServerIntro), + child: AppImage(path: AppImagePaths.privateServerIntro,useThemeColor: false), ), label: '', titleAlignment: ListTileTitleAlignment.top, @@ -227,7 +228,7 @@ class _OnboardingState extends ConsumerState { AppTile( icon: Padding( padding: const EdgeInsets.only(top: 5.0), - child: AppImage(path: AppImagePaths.nonProfit), + child: AppImage(path: AppImagePaths.nonProfit,useThemeColor: false), ), label: '', titleAlignment: ListTileTitleAlignment.top, @@ -328,10 +329,10 @@ class RouteModeContainer extends StatelessWidget { duration: Duration(milliseconds: 250), padding: EdgeInsets.all(16.0), decoration: BoxDecoration( - color: isSelected ? AppColors.blue1 : context.bgSurface, + color: isSelected ? context.bgHover : context.bgElevated, borderRadius: BorderRadius.circular(16.0), border: isSelected - ? Border.all(color: context.textLink, width: 3.0) + ? Border.all(color: context.borderInputFocus, width: 3.0) : Border.all(color: context.borderDefault, width: 1.0), ), child: Column( @@ -356,13 +357,13 @@ class RouteModeContainer extends StatelessWidget { EdgeInsets.symmetric(horizontal: 10.0, vertical: 3.0), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), - border: Border.all(color: AppColors.blue4), - color: context.textLink, + border: Border.all(color: context.statusInfoBorder), + color: context.statusInfoBg, ), child: Text( tags(), style: - textTheme.labelMedium!.copyWith(color: context.borderInputFocus), + textTheme.labelMedium!.copyWith(color: context.statusInfoText), )) ], ), diff --git a/lib/features/vpn/location_setting.dart b/lib/features/vpn/location_setting.dart index a23061e459..70be915849 100644 --- a/lib/features/vpn/location_setting.dart +++ b/lib/features/vpn/location_setting.dart @@ -55,7 +55,7 @@ class LocationSetting extends HookConsumerWidget { icon: flag.isEmpty ? AppImagePaths.location : Flag(countryCode: flag), actions: [ if (serverType == ServerLocationType.auto) - AppImage(path: AppImagePaths.blot), + AppImage(path: AppImagePaths.blot,color: context.statusWarningBgDot,), const SizedBox(width: 8), IconButton( onPressed: () => appRouter.push(const ServerSelection()), diff --git a/lib/features/vpn/vpn_status.dart b/lib/features/vpn/vpn_status.dart index 90d157cf87..f759984e12 100644 --- a/lib/features/vpn/vpn_status.dart +++ b/lib/features/vpn/vpn_status.dart @@ -26,6 +26,7 @@ class VpnStatus extends HookConsumerWidget { label: 'vpn_status'.i18n, value: vpnStatus.name.capitalize, icon: AppImagePaths.glob, + onTap: isExtensionNeeded(systemExtensionStatus) ? () { appRouter.push(const MacOSExtensionDialog()); diff --git a/lib/features/vpn/vpn_switch.dart b/lib/features/vpn/vpn_switch.dart index 71b0f34ff3..fc8803617a 100644 --- a/lib/features/vpn/vpn_switch.dart +++ b/lib/features/vpn/vpn_switch.dart @@ -53,7 +53,7 @@ class VPNSwitch extends HookConsumerWidget { padding: const EdgeInsets.all(8.0), child: CircularProgressIndicator( strokeWidth: 8.r, - color: context.bgSurface, + color: context.actionToggleKnobBg, ), ), ); @@ -109,10 +109,10 @@ class VPNSwitch extends HookConsumerWidget { Color _wrapperColor(VPNStatus vpnStatus, BuildContext context) { switch (vpnStatus) { case VPNStatus.connected: - return AppColors.blue4; + return context.actionToggleBrandActiveBg; case VPNStatus.connecting: case VPNStatus.disconnected: - return context.textTertiary; + return context.actionToggleDisabledBg; case VPNStatus.disconnecting: return context.textTertiary; case VPNStatus.missingPermission: diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 244cd3ffbb..f629918279 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -135,32 +135,32 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: - app_links: 05a6ec2341985eb05e9f97dc63f5837c39895c3f - auto_updater_macos: 3a42f1a06be6981f1a18be37e6e7bf86aa732118 - desktop_webview_window: 7e37af677d6d19294cb433d9b1d878ef78dffa4d - device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76 - flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d - flutter_local_notifications: 4bf37a31afde695b56091b4ae3e4d9c7a7e6cda0 - flutter_timezone: d272288c69082ad571630e0d17140b3d6b93dc0c + app_links: c3185399a5cabc2e610ee5ad52fb7269b84ff869 + auto_updater_macos: 3e3462c418fe4e731917eacd8d28eef7af84086d + desktop_webview_window: d4365e71bcd4e1aa0c14cf0377aa24db0c16a7e2 + device_info_plus: 1b14eed9bf95428983aed283a8d51cce3d8c4215 + flutter_inappwebview_macos: bdf207b8f4ebd58e86ae06cd96b147de99a67c9b + flutter_local_notifications: 4ccab5b7a22835214a6672e3f9c5e8ae207dab36 + flutter_timezone: b3bc0c587d8780d395651284a1ff46eb1e5753ac FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 - in_app_purchase_storekit: d1a48cb0f8b29dbf5f85f782f5dd79b21b90a5e6 - mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93 + in_app_purchase_storekit: a1ce04056e23eecc666b086040239da7619cd783 + mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e ObjectBox: a60820ec1c903702350585d8cc99c1268c99e688 - objectbox_flutter_libs: 013bbc27a57c5120e1408c0b33386c78cd0b5847 - objective_c: ec13431e45ba099cb734eb2829a5c1cd37986cba + objectbox_flutter_libs: fdba3af52a244037417fe170952a3dd819fee1af + objective_c: e5f8194456e8fc943e034d1af00510a1bc29c067 OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 - package_info_plus: f0052d280d17aa382b932f399edf32507174e870 - path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 - screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f + package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b + path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba + screen_retriever_macos: 776e0fa5d42c6163d2bf772d22478df4b302b161 Sentry: b53951377b78e21a734f5dc8318e333dbfc682d7 - sentry_flutter: 4c33648b7e83310aa1fdb1b10c5491027d9643f0 - share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc - shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb + sentry_flutter: f074f75557daea0e1dd9607381a05cc0e3e456fe + share_plus: 1fa619de8392a4398bfaf176d441853922614e89 + shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 Sparkle: a346a4341537c625955751ed3ae4b340b68551fa - store_checker: 0b5120a0f0a0f36af7b4be01a049e6006151dc16 - tray_manager: a104b5c81b578d83f3c3d0f40a997c8b10810166 - url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd - window_manager: b729e31d38fb04905235df9ea896128991cad99e + store_checker: 387169de0dffe57b6370d54cc027e9f95051b57f + tray_manager: 9064e219c56d75c476e46b9a21182087930baf90 + url_launcher_macos: 175a54c831f4375a6cf895875f716ee5af3888ce + window_manager: e25faf20d88283a0d46e7b1a759d07261ca27575 PODFILE CHECKSUM: b1a5a5e815560a377d8b3e64b4f3f97e2bd372ba From 32fb92ea91e00886c340b15fb9d1ba5232432dea Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 16:54:40 +0530 Subject: [PATCH 05/14] Moved some setting to support --- lib/features/setting/follow_us.dart | 15 +--------- lib/features/setting/setting.dart | 41 +++++++------------------- lib/features/support/support.dart | 45 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 45 deletions(-) diff --git a/lib/features/setting/follow_us.dart b/lib/features/setting/follow_us.dart index b62b0ba839..d3f37e2e19 100644 --- a/lib/features/setting/follow_us.dart +++ b/lib/features/setting/follow_us.dart @@ -116,17 +116,4 @@ class FollowUsListView extends HookWidget { } } -void showFollowUsBottomSheet({required BuildContext context}) { - showAppBottomSheet( - context: context, - title: 'follow_us'.i18n, - scrollControlDisabledMaxHeightRatio: context.isSmallDevice ? 0.39.h : 0.3.h, - builder: (context, scrollController) { - return Flexible( - child: FollowUsListView( - scrollController: scrollController, - ), - ); - }, - ); -} + diff --git a/lib/features/setting/setting.dart b/lib/features/setting/setting.dart index 9a3b9646aa..3b9409ee45 100644 --- a/lib/features/setting/setting.dart +++ b/lib/features/setting/setting.dart @@ -13,8 +13,6 @@ import 'package:lantern/features/home/provider/app_setting_notifier.dart'; import 'package:lantern/features/home/provider/home_notifier.dart'; import 'package:lantern/features/setting/appearance.dart' show appearanceModeLabel, showAppearanceBottomSheet; -import 'package:lantern/features/setting/follow_us.dart' - show showFollowUsBottomSheet; import '../../core/services/injection_container.dart'; @@ -25,7 +23,6 @@ enum _SettingType { language, appearance, support, - followUs, getPro, downloadLinks, checkForUpdates, @@ -152,14 +149,6 @@ class _SettingState extends ConsumerState { ), onPressed: () => settingMenuTap(_SettingType.appearance), ), - DividerSpace(), - if (PlatformUtils.isDesktop) - AppTile( - label: 'check_for_updates'.i18n, - icon: AppImagePaths.update, - onPressed: () async => - await settingMenuTap(_SettingType.checkForUpdates), - ), ], ), ), @@ -173,18 +162,15 @@ class _SettingState extends ConsumerState { icon: AppImagePaths.support, onPressed: () => settingMenuTap(_SettingType.support), ), - DividerSpace(), - AppTile( - label: 'download_links'.i18n, - icon: AppImagePaths.desktop, - onPressed: () => settingMenuTap(_SettingType.downloadLinks), - ), - DividerSpace(), - AppTile( - label: 'follow_us'.i18n, - icon: AppImagePaths.thumb, - onPressed: () => settingMenuTap(_SettingType.followUs), - ), + if (PlatformUtils.isDesktop) ...{ + DividerSpace(), + AppTile( + label: 'check_for_updates'.i18n, + icon: AppImagePaths.update, + onPressed: () async => + await settingMenuTap(_SettingType.checkForUpdates), + ), + }, DividerSpace(), AppTile( label: 'get_30_days_of_pro_free'.i18n, @@ -260,18 +246,11 @@ class _SettingState extends ConsumerState { case _SettingType.support: appRouter.push(Support()); break; - case _SettingType.followUs: - if (PlatformUtils.isDesktop) { - appRouter.push(FollowUs()); - return; - } - showFollowUsBottomSheet(context: context); - break; + case _SettingType.getPro: appRouter.push(InviteFriends()); break; case _SettingType.downloadLinks: - appRouter.push(DownloadLinks()); break; case _SettingType.checkForUpdates: await checkForUpdates(); diff --git a/lib/features/support/support.dart b/lib/features/support/support.dart index 644c58aaaf..8facefa771 100644 --- a/lib/features/support/support.dart +++ b/lib/features/support/support.dart @@ -4,6 +4,8 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:intl/intl.dart'; import 'package:lantern/core/common/common.dart'; import 'package:lantern/core/utils/route_utils.dart'; +import 'package:lantern/core/utils/screen_utils.dart'; +import 'package:lantern/features/setting/follow_us.dart' hide FollowUs; import 'package:lantern/features/support/app_version.dart'; @RoutePage(name: 'Support') @@ -92,6 +94,34 @@ class Support extends StatelessWidget { ), ), const SizedBox(height: defaultSize), + AppCard( + padding: EdgeInsets.zero, + child: Column( + children: [ + DividerSpace(), + AppTile( + label: 'download_links'.i18n, + icon: AppImagePaths.desktop, + onPressed: () { + appRouter.push(DownloadLinks()); + }, + ), + DividerSpace(), + AppTile( + label: 'follow_us'.i18n, + icon: AppImagePaths.thumb, + onPressed: () { + if (PlatformUtils.isDesktop) { + appRouter.push(FollowUs()); + return; + } + showFollowUsBottomSheet(context: context); + }, + ), + ], + ), + ), + const SizedBox(height: defaultSize), const AppVersion(), const SizedBox(height: size24), ], @@ -99,4 +129,19 @@ class Support extends StatelessWidget { ), ); } + + void showFollowUsBottomSheet({required BuildContext context}) { + showAppBottomSheet( + context: context, + title: 'follow_us'.i18n, + scrollControlDisabledMaxHeightRatio: context.isSmallDevice ? 0.39.h : 0.3.h, + builder: (context, scrollController) { + return Flexible( + child: FollowUsListView( + scrollController: scrollController, + ), + ); + }, + ); + } } From d954084323194b1d401c89d725feaa44c5a71abd Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 17:17:38 +0530 Subject: [PATCH 06/14] more dark mode changes --- lib/core/common/app_buttons.dart | 6 ++++-- lib/core/widgets/pro_button.dart | 1 + lib/features/private_server/manually_server_setup.dart | 3 --- lib/features/private_server/private_server_setup.dart | 1 + lib/features/private_server/provider_card.dart | 3 ++- lib/features/setting/invite_friends.dart | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/core/common/app_buttons.dart b/lib/core/common/app_buttons.dart index 351ee1a3a1..8623a523ca 100644 --- a/lib/core/common/app_buttons.dart +++ b/lib/core/common/app_buttons.dart @@ -22,6 +22,7 @@ class PrimaryButton extends StatelessWidget { final Color? bgColor; final Color? textColor; final bool? isTaller; + final bool? useThemeColor; // Default constructor for button without an icon const PrimaryButton({ @@ -34,6 +35,7 @@ class PrimaryButton extends StatelessWidget { this.expanded = true, this.isTaller = false, this.showBorder = false, + this.useThemeColor, this.icon, super.key, }); @@ -57,7 +59,7 @@ class PrimaryButton extends StatelessWidget { path: icon!, height: iconHeight, color: iconColor, - useThemeColor: false, + useThemeColor: useThemeColor ?? true, ), label: Text(label), style: _buildButtonStyle(context, button!, iconSz), @@ -183,7 +185,7 @@ class SecondaryButton extends StatelessWidget { path: icon!, height: iconHeight, color: iconColor, - useThemeColor: useThemeColor??false, + useThemeColor: useThemeColor ?? false, ), label: Text(label), style: _buildButtonStyle(context, button!, iconSz), diff --git a/lib/core/widgets/pro_button.dart b/lib/core/widgets/pro_button.dart index b07b6047b5..2f45ae8e8f 100644 --- a/lib/core/widgets/pro_button.dart +++ b/lib/core/widgets/pro_button.dart @@ -18,6 +18,7 @@ class ProButton extends StatelessWidget { icon: AppImagePaths.crown, expanded: true, isTaller: true, + useThemeColor: false, onPressed: onPressed, ); } diff --git a/lib/features/private_server/manually_server_setup.dart b/lib/features/private_server/manually_server_setup.dart index 1bb4f1f1fc..b79b80cf6c 100644 --- a/lib/features/private_server/manually_server_setup.dart +++ b/lib/features/private_server/manually_server_setup.dart @@ -6,7 +6,6 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:lantern/core/common/common.dart'; import 'package:lantern/core/models/entity/private_server_entity.dart'; -import 'package:lantern/core/models/private_server_status.dart'; import 'package:lantern/features/private_server/provider/private_server_notifier.dart'; import '../../core/services/injection_container.dart'; @@ -62,7 +61,6 @@ class _ManuallyServerSetupState extends ConsumerState { SizedBox(height: 16), PrimaryButton( icon: AppImagePaths.github, - iconColor: context.textInverse, isTaller: true, label: 'view_instructions_github'.i18n, onPressed: () { @@ -197,7 +195,6 @@ class _ManuallyServerSetupState extends ConsumerState { ); } - void showSuccessDialog() { final textTheme = Theme.of(context).textTheme; AppDialog.customDialog( diff --git a/lib/features/private_server/private_server_setup.dart b/lib/features/private_server/private_server_setup.dart index 12cc7486aa..365247c98e 100644 --- a/lib/features/private_server/private_server_setup.dart +++ b/lib/features/private_server/private_server_setup.dart @@ -134,6 +134,7 @@ class _PrivateServerSetupState extends ConsumerState { path: AppImagePaths.serverRack, type: AssetType.svg, height: PlatformUtils.isDesktop ? 190.h : 160.h, + useThemeColor: false, ), const SizedBox(height: defaultSize), ProviderCarousel( diff --git a/lib/features/private_server/provider_card.dart b/lib/features/private_server/provider_card.dart index ccba221d4b..f823c0475f 100644 --- a/lib/features/private_server/provider_card.dart +++ b/lib/features/private_server/provider_card.dart @@ -40,7 +40,7 @@ class ProviderCard extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - AppImage(path: icon, width: 20, height: 20), + AppImage(path: icon, width: 20, height: 20,useThemeColor: false,), const SizedBox(width: defaultSize), Expanded( child: Text( @@ -107,6 +107,7 @@ class CheckmarkTile extends StatelessWidget { path: iconPath ?? AppImagePaths.checkmark, width: 24, height: 24, + useThemeColor: false, ), const SizedBox(width: 16), Expanded( diff --git a/lib/features/setting/invite_friends.dart b/lib/features/setting/invite_friends.dart index fbb32a4626..c0ddfcb4b1 100644 --- a/lib/features/setting/invite_friends.dart +++ b/lib/features/setting/invite_friends.dart @@ -27,7 +27,7 @@ class InviteFriends extends HookConsumerWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Center(child: AppImage(path: AppImagePaths.startIllustration)), + Center(child: AppImage(path: AppImagePaths.startIllustration,useThemeColor: false,)), SizedBox(height: defaultSize), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), From 42952388dd759184bdac89f898c5440680e239ec Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 18:29:03 +0530 Subject: [PATCH 07/14] more dark mode fixes --- lib/core/common/app_buttons.dart | 2 +- lib/features/language/language.dart | 5 ++--- lib/features/setting/download_links.dart | 1 + lib/features/vpn/server_selection.dart | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/core/common/app_buttons.dart b/lib/core/common/app_buttons.dart index 8623a523ca..98a4f04332 100644 --- a/lib/core/common/app_buttons.dart +++ b/lib/core/common/app_buttons.dart @@ -343,7 +343,6 @@ class AppRadioButton extends StatelessWidget { @override Widget build(BuildContext context) { final sz = hCap(context, 24); - return SizedBox( width: sz, height: sz, @@ -351,6 +350,7 @@ class AppRadioButton extends StatelessWidget { value: value, groupValue: groupValue, onChanged: onChanged, + activeColor: context.textLink, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: VisualDensity.compact, ), diff --git a/lib/features/language/language.dart b/lib/features/language/language.dart index 243bcee5ff..dc8bdcfb0f 100644 --- a/lib/features/language/language.dart +++ b/lib/features/language/language.dart @@ -74,14 +74,13 @@ class LanguageListView extends HookConsumerWidget { AppTile( label: displayLanguage(langCode), onPressed: () => onLanguageTap(langCode), - trailing: Radio( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + trailing: AppRadioButton( value: langCode, groupValue: locale.toString(), onChanged: (value) { onLanguageTap(value!); }, - activeColor: AppColors.blue7, + // activeColor: AppColors.blue7, ), minHeight: 56, ), diff --git a/lib/features/setting/download_links.dart b/lib/features/setting/download_links.dart index f27446a110..1abe5d0c01 100644 --- a/lib/features/setting/download_links.dart +++ b/lib/features/setting/download_links.dart @@ -38,6 +38,7 @@ class DownloadLinks extends StatelessWidget { Card( child: AppTile( icon: AppImagePaths.lanternLogoRounded, + iconUseThemeColor: false, trailing: AppImage(path: AppImagePaths.outsideBrowser), label: 'lantern_io'.i18n, onPressed: () { diff --git a/lib/features/vpn/server_selection.dart b/lib/features/vpn/server_selection.dart index 7ee4e0f01e..e7ce803e49 100644 --- a/lib/features/vpn/server_selection.dart +++ b/lib/features/vpn/server_selection.dart @@ -160,7 +160,7 @@ class _ServerSelectionState extends ConsumerState { ), trailing: Row( mainAxisSize: MainAxisSize.min, - children: [AppImage(path: AppImagePaths.blot)], + children: [AppImage(path: AppImagePaths.blot,color: context.statusWarningBgDot,)], ), ), ), From 39eb253fe8c27c4e47fccaf46139b10942598681 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 21:17:40 +0530 Subject: [PATCH 08/14] UI fixs for dark mode --- assets/images/automatic.svg | 10 ++ assets/images/dark_mode.svg | 3 + assets/images/light_mode.svg | 3 + lib/core/common/app_image_paths.dart | 3 + lib/core/widgets/info_row.dart | 2 +- lib/core/widgets/search_bar.dart | 37 ++--- lib/features/account/account.dart | 204 ++++++++++++++------------- lib/features/logs/log_line.dart | 3 +- lib/features/logs/logs.dart | 4 +- lib/features/setting/appearance.dart | 16 +-- 10 files changed, 155 insertions(+), 130 deletions(-) create mode 100644 assets/images/automatic.svg create mode 100644 assets/images/dark_mode.svg create mode 100644 assets/images/light_mode.svg diff --git a/assets/images/automatic.svg b/assets/images/automatic.svg new file mode 100644 index 0000000000..ee487024f6 --- /dev/null +++ b/assets/images/automatic.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/dark_mode.svg b/assets/images/dark_mode.svg new file mode 100644 index 0000000000..425ef43d1f --- /dev/null +++ b/assets/images/dark_mode.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/light_mode.svg b/assets/images/light_mode.svg new file mode 100644 index 0000000000..695071f8fb --- /dev/null +++ b/assets/images/light_mode.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/core/common/app_image_paths.dart b/lib/core/common/app_image_paths.dart index 51224a9dc4..547e35420b 100644 --- a/lib/core/common/app_image_paths.dart +++ b/lib/core/common/app_image_paths.dart @@ -108,6 +108,9 @@ class AppImagePaths { static const nonProfit = 'assets/images/non_profit.svg'; static const privateServerIntro = 'assets/images/private_server_intro.svg'; static const smartRouteMode = 'assets/images/smart_route_mode.svg'; + static const automatic = 'assets/images/automatic.svg'; + static const lightMode = 'assets/images/light_mode.svg'; + static const darkMode = 'assets/images/dark_mode.svg'; /// Validates and returns a safe flag path for the given country code. diff --git a/lib/core/widgets/info_row.dart b/lib/core/widgets/info_row.dart index 65ea012a9f..8d3158ce2f 100644 --- a/lib/core/widgets/info_row.dart +++ b/lib/core/widgets/info_row.dart @@ -38,7 +38,7 @@ class InfoRow extends StatelessWidget { final textTheme = Theme.of(context).textTheme; return ListTile( minTileHeight: minTileHeight, - tileColor: backgroundColor, + tileColor: backgroundColor?? context.bgElevated, onTap: onPressed, contentPadding: padding ?? EdgeInsets.symmetric(horizontal: 16, vertical: 4), diff --git a/lib/core/widgets/search_bar.dart b/lib/core/widgets/search_bar.dart index d9b86861c9..fb1b09886f 100644 --- a/lib/core/widgets/search_bar.dart +++ b/lib/core/widgets/search_bar.dart @@ -56,26 +56,29 @@ class _SearchBarContent extends HookConsumerWidget { // Search input or title Expanded( child: isSearching.value - ? TextField( - controller: controller, - autofocus: true, - onChanged: (value) => - ref.read(searchQueryProvider.notifier).setQuery(value), - decoration: InputDecoration( - hintText: hintText, - hintStyle: TextStyle( - color: context.textSecondary, + ? Theme( + data: ThemeData(), + child: TextField( + controller: controller, + autofocus: true, + onChanged: (value) => + ref.read(searchQueryProvider.notifier).setQuery(value), + decoration: InputDecoration( + hintText: hintText, + hintStyle: TextStyle( + color: context.textSecondary, + fontSize: 16, + fontWeight: FontWeight.w400, + ), + border: InputBorder.none, + isDense: true, + contentPadding: const EdgeInsets.symmetric(vertical: 8), + ), + style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, + color: context.textPrimary, ), - border: InputBorder.none, - isDense: true, - contentPadding: const EdgeInsets.symmetric(vertical: 8), - ), - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: context.textPrimary, ), ) : Text( diff --git a/lib/features/account/account.dart b/lib/features/account/account.dart index 30f0d434c3..2b2ffa7ddf 100644 --- a/lib/features/account/account.dart +++ b/lib/features/account/account.dart @@ -32,132 +32,134 @@ class Account extends HookConsumerWidget { final appSettings = ref.watch(appSettingProvider); final theme = Theme.of(buildContext).textTheme; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (isExpired) ...{ - InfoRow( - minTileHeight: 40, - backgroundColor: AppColors.red1, - borderColor: AppColors.red2, - textStyle: theme.labelLarge!.copyWith( - color: buildContext.statusErrorBg, + return SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (isExpired) ...{ + InfoRow( + minTileHeight: 40, + backgroundColor: AppColors.red1, + borderColor: AppColors.red2, + textStyle: theme.labelLarge!.copyWith( + color: buildContext.statusErrorBg, + ), + text: 'pro_subscription_expired_message'.i18n, ), - text: 'pro_subscription_expired_message'.i18n, - ), + SizedBox(height: defaultSize), + ProButton( + label: 'renew_pro_subscription'.i18n, + onPressed: () { + appRouter.push(const Plans()); + }, + ), + }, SizedBox(height: defaultSize), - ProButton( - label: 'renew_pro_subscription'.i18n, - onPressed: () { - appRouter.push(const Plans()); - }, + Padding( + padding: const EdgeInsets.only(left: 16), + child: Text( + 'lantern_pro_email'.i18n, + style: theme.labelLarge!.copyWith( + color: buildContext.textSecondary, + ), + ), ), - }, - SizedBox(height: defaultSize), - Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'lantern_pro_email'.i18n, - style: theme.labelLarge!.copyWith( - color: buildContext.textSecondary, + AppCard( + padding: EdgeInsets.zero, + child: AppTile( + label: appSettings.email.toLowerCase(), + icon: AppImagePaths.email, + contentPadding: EdgeInsets.only(left: 16), + onPressed: kDebugMode + ? () { + copyToClipboard(appSettings.email); + } + : null, + trailing: AppTextButton( + label: 'change_email'.i18n, + onPressed: () { + appRouter.push(SignInPassword( + email: appSettings.email, fromChangeEmail: true)); + }, + ), ), ), - ), - AppCard( - padding: EdgeInsets.zero, - child: AppTile( - label: appSettings.email.toLowerCase(), - icon: AppImagePaths.email, - contentPadding: EdgeInsets.only(left: 16), - onPressed: kDebugMode - ? () { - copyToClipboard(appSettings.email); - } - : null, - trailing: AppTextButton( - label: 'change_email'.i18n, - onPressed: () { - appRouter.push(SignInPassword( - email: appSettings.email, fromChangeEmail: true)); - }, + SizedBox(height: defaultSize), + if (isExpired) + Padding( + padding: const EdgeInsets.only(left: 16), + child: Text( + 'last_subscription_renewal_date'.i18n, + style: theme.labelLarge!.copyWith( + color: buildContext.textSecondary, + ), + ), + ) + else + Padding( + padding: const EdgeInsets.only(left: 16), + child: Text( + user!.legacyUserData.subscriptionData.autoRenew + ? 'subscription_renewal_date'.i18n + : 'pro_account_expiration'.i18n, + style: theme.labelLarge!.copyWith( + color: buildContext.textSecondary, + ), + ), ), + AppCard( + padding: EdgeInsets.zero, + child: AppTile( + label: user!.legacyUserData.toDate(), + contentPadding: EdgeInsets.only(left: 16), + icon: AppImagePaths.autoRenew, + trailing: planTrailingWidget(user, buildContext, ref)), ), - ), - SizedBox(height: defaultSize), - if (isExpired) + SizedBox(height: defaultSize), Padding( padding: const EdgeInsets.only(left: 16), child: Text( - 'last_subscription_renewal_date'.i18n, + 'lantern_pro_devices'.i18n, style: theme.labelLarge!.copyWith( color: buildContext.textSecondary, ), ), - ) - else + ), + UserDevices(), + SizedBox(height: defaultSize), + if (appSettings.userLoggedIn) + AppCard( + padding: EdgeInsets.zero, + child: AppTile( + label: 'logout'.i18n, + icon: AppImagePaths.signIn, + onPressed: () => logoutDialog(buildContext, ref)), + ), + Spacer(), Padding( padding: const EdgeInsets.only(left: 16), child: Text( - user!.legacyUserData.subscriptionData.autoRenew - ? 'subscription_renewal_date'.i18n - : 'pro_account_expiration'.i18n, + 'danger_zone'.i18n, style: theme.labelLarge!.copyWith( color: buildContext.textSecondary, ), ), ), - AppCard( - padding: EdgeInsets.zero, - child: AppTile( - label: user!.legacyUserData.toDate(), - contentPadding: EdgeInsets.only(left: 16), - icon: AppImagePaths.autoRenew, - trailing: planTrailingWidget(user, buildContext, ref)), - ), - SizedBox(height: defaultSize), - Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'lantern_pro_devices'.i18n, - style: theme.labelLarge!.copyWith( - color: buildContext.textSecondary, - ), - ), - ), - UserDevices(), - SizedBox(height: defaultSize), - if (appSettings.userLoggedIn) - AppCard( - padding: EdgeInsets.zero, + Card( child: AppTile( - label: 'logout'.i18n, - icon: AppImagePaths.signIn, - onPressed: () => logoutDialog(buildContext, ref)), - ), - Spacer(), - Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'danger_zone'.i18n, - style: theme.labelLarge!.copyWith( - color: buildContext.textSecondary, - ), - ), - ), - Card( - child: AppTile( - contentPadding: EdgeInsets.only(left: 16), - icon: AppImagePaths.delete, - label: 'delete_account'.i18n, - trailing: AppTextButton( - label: 'delete'.i18n, - textColor: buildContext.statusErrorBg, - onPressed: _onDeleteTap, + contentPadding: EdgeInsets.only(left: 16), + icon: AppImagePaths.delete, + label: 'delete_account'.i18n, + trailing: AppTextButton( + label: 'delete'.i18n, + textColor: buildContext.statusErrorText, + onPressed: _onDeleteTap, + ), ), ), - ), - SizedBox(height: defaultSize), - ], + SizedBox(height: size24), + ], + ), ); } diff --git a/lib/features/logs/log_line.dart b/lib/features/logs/log_line.dart index eccfb24f5d..fff26b2bec 100644 --- a/lib/features/logs/log_line.dart +++ b/lib/features/logs/log_line.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:lantern/core/common/app_semantic_colors.dart'; import 'package:lantern/core/common/app_text_styles.dart'; import 'package:lantern/features/logs/parsed_log.dart'; @@ -15,7 +16,7 @@ class LogLineWidget extends StatelessWidget { return Text( line, style: AppTextStyles.monospace( - color: Colors.white, + color: context.textPrimary, ), ); } diff --git a/lib/features/logs/logs.dart b/lib/features/logs/logs.dart index b8ca428bac..0b5189a2a4 100644 --- a/lib/features/logs/logs.dart +++ b/lib/features/logs/logs.dart @@ -80,9 +80,9 @@ class Logs extends HookConsumerWidget { Expanded( child: Container( decoration: ShapeDecoration( - color: context.textPrimary, + color: context.bgElevated, shape: RoundedRectangleBorder( - side: BorderSide(width: 1), + side: BorderSide(width: 1,color: context.borderDefault), borderRadius: BorderRadius.circular(16), ), ), diff --git a/lib/features/setting/appearance.dart b/lib/features/setting/appearance.dart index 2bba1e3752..678ffa2e9a 100644 --- a/lib/features/setting/appearance.dart +++ b/lib/features/setting/appearance.dart @@ -1,5 +1,6 @@ import 'package:auto_route/annotations.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:lantern/core/common/common.dart'; import 'package:lantern/features/home/provider/app_setting_notifier.dart'; @@ -29,9 +30,9 @@ class AppearanceListView extends ConsumerWidget { final currentMode = ref.watch(appSettingProvider).themeMode; final options = [ - ('system', 'system'.i18n), - ('light', 'light'.i18n), - ('dark', 'dark'.i18n), + ('system', 'system'.i18n,AppImagePaths.automatic), + ('light', 'light'.i18n,AppImagePaths.lightMode), + ('dark', 'dark'.i18n,AppImagePaths.darkMode), ]; return ListView.separated( @@ -44,16 +45,15 @@ class AppearanceListView extends ConsumerWidget { child: DividerSpace(), ), itemBuilder: (context, index) { - final (value, label) = options[index]; + final (value, label,icon) = options[index]; return AppTile( + icon: icon, label: label, minHeight: 56, - trailing: Radio( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + trailing: AppRadioButton( value: value, groupValue: currentMode, onChanged: (selected) => _onSelect(selected!, ref, context), - activeColor: AppColors.blue7, ), onPressed: () => _onSelect(value, ref, context), ); @@ -71,7 +71,7 @@ void showAppearanceBottomSheet({required BuildContext context}) { showAppBottomSheet( context: context, title: 'appearance'.i18n, - scrollControlDisabledMaxHeightRatio: 0.35, + scrollControlDisabledMaxHeightRatio: 0.32.h, builder: (context, scrollController) { return Flexible( child: AppearanceListView(scrollController: scrollController), From 865f1e1e020034ec56c314eb422c114574cb9a61 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 21:37:22 +0530 Subject: [PATCH 09/14] update toolbar as theme --- .../home/provider/app_setting_notifier.dart | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/features/home/provider/app_setting_notifier.dart b/lib/features/home/provider/app_setting_notifier.dart index dba9e1bdc3..f101e146a8 100644 --- a/lib/features/home/provider/app_setting_notifier.dart +++ b/lib/features/home/provider/app_setting_notifier.dart @@ -10,6 +10,7 @@ import 'package:lantern/core/utils/storage_utils.dart'; import 'package:lantern/lantern/lantern_service.dart'; import 'package:lantern/lantern/lantern_service_notifier.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:window_manager/window_manager.dart'; part 'app_setting_notifier.g.dart'; @@ -23,6 +24,7 @@ class AppSettingNotifier extends _$AppSettingNotifier { final setting = _db.getAppSetting(); if (setting != null && setting.locale.isNotEmpty) { + updateToolThemeMode(); return setting; } // First-time user → use device locale @@ -30,9 +32,21 @@ class AppSettingNotifier extends _$AppSettingNotifier { final initial = AppSetting(locale: fallback.toString()); _db.updateAppSetting(initial); + updateToolThemeMode(); return initial; } + void updateToolThemeMode() { + final setting = _db.getAppSetting(); + final mode = setting?.themeMode ?? 'system'; + final modeEnum = resolveThemeMode(mode); + if (modeEnum == ThemeMode.system || modeEnum == ThemeMode.light) { + windowManager.setBrightness(Brightness.light); + } else { + windowManager.setBrightness(Brightness.dark); + } + } + Future update(AppSetting updated) async { state = updated; _db.updateAppSetting(updated); @@ -104,7 +118,6 @@ class AppSettingNotifier extends _$AppSettingNotifier { update(state.copyWith(dataCapThreshold: threshold)); } - void setSplashScreen(bool value) { update(state.copyWith(showSplashScreen: value)); } @@ -119,6 +132,12 @@ class AppSettingNotifier extends _$AppSettingNotifier { void setThemeMode(String mode) { update(state.copyWith(themeMode: mode)); + final modeEnum = resolveThemeMode(mode); + if (modeEnum == ThemeMode.system || modeEnum == ThemeMode.light) { + windowManager.setBrightness(Brightness.light); + } else { + windowManager.setBrightness(Brightness.dark); + } } static ThemeMode resolveThemeMode(String raw) { @@ -139,7 +158,6 @@ class AppSettingNotifier extends _$AppSettingNotifier { : deviceLocale; } - Future setSplitTunnelingEnabled(bool enabled) async { final LanternService svc = ref.read(lanternServiceProvider); final previous = state.isSplitTunnelingOn; From cead424bfedf885e8546ebd6a39ae00d8dbfc4d4 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Thu, 19 Feb 2026 22:19:23 +0530 Subject: [PATCH 10/14] More dark mode changes --- lib/core/common/common.dart | 22 ++++++++-- lib/core/services/stripe_service.dart | 40 ++++++++++--------- .../home/provider/app_setting_notifier.dart | 29 +++++--------- lib/lantern_app.dart | 2 +- 4 files changed, 52 insertions(+), 41 deletions(-) diff --git a/lib/core/common/common.dart b/lib/core/common/common.dart index 67c3b1d8df..eff34fcf6e 100644 --- a/lib/core/common/common.dart +++ b/lib/core/common/common.dart @@ -3,9 +3,9 @@ import 'dart:math'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; - import 'package:lantern/core/common/app_build_info.dart'; import 'package:lantern/core/common/app_eum.dart'; import 'package:lantern/core/common/app_urls.dart'; @@ -26,16 +26,16 @@ import '../utils/store_utils.dart'; export 'package:lantern/core/common/app_asset.dart'; export 'package:lantern/core/common/app_buttons.dart'; export 'package:lantern/core/common/app_colors.dart'; -export 'package:lantern/core/common/app_semantic_colors.dart'; export 'package:lantern/core/common/app_dialog.dart'; export 'package:lantern/core/common/app_dimens.dart'; export 'package:lantern/core/common/app_eum.dart'; export 'package:lantern/core/common/app_image_paths.dart'; +export 'package:lantern/core/common/app_semantic_colors.dart'; export 'package:lantern/core/common/app_text_field.dart'; export 'package:lantern/core/common/app_theme.dart'; -export 'package:lantern/core/common/date_formatters.dart'; // Utils export 'package:lantern/core/common/app_urls.dart'; +export 'package:lantern/core/common/date_formatters.dart'; //Desktop export export 'package:lantern/core/desktop/app_intent.dart'; export 'package:lantern/core/desktop/app_shortcuts.dart'; @@ -114,7 +114,11 @@ Future pasteFromClipboard() async { /// Check user account status and updates user data if the user has a pro plan Future checkUserAccountStatus(WidgetRef ref, BuildContext context) async { - final delays = [Duration(seconds: 1), Duration(seconds: 2),Duration(seconds: 3)]; + final delays = [ + Duration(seconds: 1), + Duration(seconds: 2), + Duration(seconds: 3) + ]; for (final delay in delays) { appLogger.info("Checking user account status with delay: $delay"); if (delay != Duration.zero) await Future.delayed(delay); @@ -204,3 +208,13 @@ ServerLocationEntity initialServerLocation() { ); } +ThemeMode resolveThemeMode(String raw) { + switch (raw) { + case 'light': + return ThemeMode.light; + case 'dark': + return ThemeMode.dark; + default: + return ThemeMode.system; + } +} diff --git a/lib/core/services/stripe_service.dart b/lib/core/services/stripe_service.dart index 8bab05fd6d..3af9a8a60b 100644 --- a/lib/core/services/stripe_service.dart +++ b/lib/core/services/stripe_service.dart @@ -1,9 +1,10 @@ import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; import 'package:lantern/core/common/app_secrets.dart'; import 'package:lantern/core/common/common.dart'; +import 'injection_container.dart' show sl; + class StripeService { Future initialize() async { try { @@ -35,6 +36,9 @@ class StripeService { required Function(dynamic error) onError, }) async { try { + final theme = + sl().getAppSetting()?.themeMode ?? 'system'; + final themeMode = resolveThemeMode(theme); if (options.publishableKey != null && options.publishableKey!.isNotEmpty) { Stripe.publishableKey = options.publishableKey!; @@ -62,23 +66,23 @@ class StripeService { currencyCode: 'USD', testEnv: kDebugMode, ), - appearance: PaymentSheetAppearance( - colors: PaymentSheetAppearanceColors( - background: AppColors.gray1, - componentBackground: AppColors.white, - primary: AppColors.blue10, - primaryText: AppColors.gray8, - secondaryText: AppColors.black, - icon: AppColors.gray9, - componentBorder: AppColors.gray3, - componentDivider: AppColors.gray2, - componentText: AppColors.gray8, - error: AppColors.red4, - placeholderText: AppColors.gray9, - ), - shapes: PaymentSheetShape(borderRadius: 16), - ), - style: ThemeMode.light, + // appearance: PaymentSheetAppearance( + // colors: PaymentSheetAppearanceColors( + // background: AppColors.gray1, + // componentBackground: AppColors.white, + // primary: AppColors.blue10, + // primaryText: AppColors.gray8, + // secondaryText: AppColors.black, + // icon: AppColors.gray9, + // componentBorder: AppColors.gray3, + // componentDivider: AppColors.gray2, + // componentText: AppColors.gray8, + // error: AppColors.red4, + // placeholderText: AppColors.gray9, + // ), + // shapes: PaymentSheetShape(borderRadius: 16), + // ), + style: themeMode, ), ); diff --git a/lib/features/home/provider/app_setting_notifier.dart b/lib/features/home/provider/app_setting_notifier.dart index f101e146a8..bc467e4658 100644 --- a/lib/features/home/provider/app_setting_notifier.dart +++ b/lib/features/home/provider/app_setting_notifier.dart @@ -24,7 +24,7 @@ class AppSettingNotifier extends _$AppSettingNotifier { final setting = _db.getAppSetting(); if (setting != null && setting.locale.isNotEmpty) { - updateToolThemeMode(); + updateToolbarThemeMode(); return setting; } // First-time user → use device locale @@ -32,11 +32,11 @@ class AppSettingNotifier extends _$AppSettingNotifier { final initial = AppSetting(locale: fallback.toString()); _db.updateAppSetting(initial); - updateToolThemeMode(); + updateToolbarThemeMode(); return initial; } - void updateToolThemeMode() { + void updateToolbarThemeMode() { final setting = _db.getAppSetting(); final mode = setting?.themeMode ?? 'system'; final modeEnum = resolveThemeMode(mode); @@ -132,24 +132,17 @@ class AppSettingNotifier extends _$AppSettingNotifier { void setThemeMode(String mode) { update(state.copyWith(themeMode: mode)); - final modeEnum = resolveThemeMode(mode); - if (modeEnum == ThemeMode.system || modeEnum == ThemeMode.light) { - windowManager.setBrightness(Brightness.light); - } else { - windowManager.setBrightness(Brightness.dark); + if (PlatformUtils.isDesktop) { + final modeEnum = resolveThemeMode(mode); + if (modeEnum == ThemeMode.system || modeEnum == ThemeMode.light) { + windowManager.setBrightness(Brightness.light); + } else { + windowManager.setBrightness(Brightness.dark); + } } } - static ThemeMode resolveThemeMode(String raw) { - switch (raw) { - case 'light': - return ThemeMode.light; - case 'dark': - return ThemeMode.dark; - default: - return ThemeMode.system; - } - } + Locale _detectDeviceLocale() { final deviceLocale = PlatformDispatcher.instance.locale; diff --git a/lib/lantern_app.dart b/lib/lantern_app.dart index 7a40dc6b0e..252338408d 100644 --- a/lib/lantern_app.dart +++ b/lib/lantern_app.dart @@ -184,7 +184,7 @@ class _LanternAppState extends ConsumerState { debugShowCheckedModeBanner: false, theme: AppTheme.appTheme(), darkTheme: AppTheme.darkTheme(), - themeMode: AppSettingNotifier.resolveThemeMode(appSetting.themeMode), + themeMode: resolveThemeMode(appSetting.themeMode), supportedLocales: languages .map((lang) => Locale(lang.split('_').first, lang.split('_').last)) From 48d57897b2cece8ad1e798bff525175811792df9 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Fri, 20 Feb 2026 11:28:45 +0530 Subject: [PATCH 11/14] code review changes --- lib/core/widgets/platform_card.dart | 1 + lib/features/setting/download_links.dart | 135 +++++++++++------------ lib/features/setting/setting.dart | 3 - 3 files changed, 67 insertions(+), 72 deletions(-) diff --git a/lib/core/widgets/platform_card.dart b/lib/core/widgets/platform_card.dart index a3ce1164b5..695889fd40 100644 --- a/lib/core/widgets/platform_card.dart +++ b/lib/core/widgets/platform_card.dart @@ -18,6 +18,7 @@ class PlatformCard extends StatelessWidget { style: IconButton.styleFrom( padding: EdgeInsets.all(15.r), backgroundColor: context.bgElevated, + hoverColor: context.bgHover, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: BorderSide(color: context.borderInput, width: .5), diff --git a/lib/features/setting/download_links.dart b/lib/features/setting/download_links.dart index 1abe5d0c01..c5561f791c 100644 --- a/lib/features/setting/download_links.dart +++ b/lib/features/setting/download_links.dart @@ -22,84 +22,81 @@ class DownloadLinks extends StatelessWidget { Widget _buildBody(BuildContext buildContext) { final theme = Theme.of(buildContext).textTheme; - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: AppImage( - path: AppImagePaths.globIllustration, - type: AssetType.png, - height: 180.h, - width: 180.w, - ), - ), - SizedBox(height: defaultSize), - Card( - child: AppTile( - icon: AppImagePaths.lanternLogoRounded, - iconUseThemeColor: false, - trailing: AppImage(path: AppImagePaths.outsideBrowser), - label: 'lantern_io'.i18n, - onPressed: () { - UrlUtils.openUrl(AppUrls.lanternOfficial); - }, - ), + return ListView( + children: [ + Center( + child: AppImage( + path: AppImagePaths.globIllustration, + type: AssetType.png, + height: 180.h, + width: 180.w, ), - SizedBox(height: defaultSize), - Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'alternative_download_links'.i18n, - style: theme.labelLarge!.copyWith( - color: buildContext.textSecondary, - ), - ), + ), + SizedBox(height: defaultSize), + Card( + child: AppTile( + icon: AppImagePaths.lanternLogoRounded, + iconUseThemeColor: false, + trailing: AppImage(path: AppImagePaths.outsideBrowser), + label: 'lantern_io'.i18n, + onPressed: () { + UrlUtils.openUrl(AppUrls.lanternOfficial); + }, ), - SizedBox(height: 4.0), - Card( - child: Column( - children: [ - AppTile.link( - url: AppUrls.lanternGithub, - icon: AppImagePaths.github, - label: 'github_download_page'.i18n, - ), - DividerSpace(), - AppTile.link( - url: AppUrls.telegramBot, - icon: AppImagePaths.telegram, - label: 'telegram_bot'.i18n, - ), - ], + ), + SizedBox(height: defaultSize), + Padding( + padding: const EdgeInsets.only(left: 16), + child: Text( + 'alternative_download_links'.i18n, + style: theme.labelLarge!.copyWith( + color: buildContext.textSecondary, ), ), - SizedBox(height: defaultSize), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text( - 'if_you_cannot_access_website'.i18n, - style: theme.bodyMedium!.copyWith( - color: buildContext.textSecondary, + ), + SizedBox(height: 4.0), + Card( + child: Column( + children: [ + AppTile.link( + url: AppUrls.lanternGithub, + icon: AppImagePaths.github, + label: 'github_download_page'.i18n, ), + DividerSpace(), + AppTile.link( + url: AppUrls.telegramBot, + icon: AppImagePaths.telegram, + label: 'telegram_bot'.i18n, + ), + ], + ), + ), + SizedBox(height: defaultSize), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + 'if_you_cannot_access_website'.i18n, + style: theme.bodyMedium!.copyWith( + color: buildContext.textSecondary, ), ), - SizedBox(height: defaultSize), - DividerSpace(padding: EdgeInsets.zero), - SizedBox(height: defaultSize), - Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'available_on'.i18n, - style: theme.labelLarge!.copyWith( - color: buildContext.textSecondary, - ), + ), + SizedBox(height: defaultSize), + DividerSpace(padding: EdgeInsets.zero), + SizedBox(height: defaultSize), + Padding( + padding: const EdgeInsets.only(left: 16), + child: Text( + 'available_on'.i18n, + style: theme.labelLarge!.copyWith( + color: buildContext.textSecondary, ), ), - SizedBox(height: 4.0), - _availableRow(), - ], - ), + ), + SizedBox(height: 4.0), + _availableRow(), + ], ); } diff --git a/lib/features/setting/setting.dart b/lib/features/setting/setting.dart index 3b9409ee45..3ef2d7dc6b 100644 --- a/lib/features/setting/setting.dart +++ b/lib/features/setting/setting.dart @@ -24,7 +24,6 @@ enum _SettingType { appearance, support, getPro, - downloadLinks, checkForUpdates, browserUnbounded, } @@ -250,8 +249,6 @@ class _SettingState extends ConsumerState { case _SettingType.getPro: appRouter.push(InviteFriends()); break; - case _SettingType.downloadLinks: - break; case _SettingType.checkForUpdates: await checkForUpdates(); break; From 60d540b634e8ba1aef910a81bafaf67915f0e82b Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Fri, 20 Feb 2026 11:47:12 +0530 Subject: [PATCH 12/14] Fix android app icons issue --- .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 ++++ .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 ++++ lib/core/services/stripe_service.dart | 32 +++++++++---------- lib/features/plans/plans.dart | 5 ++- 4 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..f7258f4601 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..f7258f4601 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/lib/core/services/stripe_service.dart b/lib/core/services/stripe_service.dart index 3af9a8a60b..0e0f815ca2 100644 --- a/lib/core/services/stripe_service.dart +++ b/lib/core/services/stripe_service.dart @@ -66,22 +66,22 @@ class StripeService { currencyCode: 'USD', testEnv: kDebugMode, ), - // appearance: PaymentSheetAppearance( - // colors: PaymentSheetAppearanceColors( - // background: AppColors.gray1, - // componentBackground: AppColors.white, - // primary: AppColors.blue10, - // primaryText: AppColors.gray8, - // secondaryText: AppColors.black, - // icon: AppColors.gray9, - // componentBorder: AppColors.gray3, - // componentDivider: AppColors.gray2, - // componentText: AppColors.gray8, - // error: AppColors.red4, - // placeholderText: AppColors.gray9, - // ), - // shapes: PaymentSheetShape(borderRadius: 16), - // ), + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + background: AppColors.gray1, + componentBackground: AppColors.white, + primary: AppColors.blue10, + primaryText: AppColors.gray8, + secondaryText: AppColors.black, + icon: AppColors.gray9, + componentBorder: AppColors.gray3, + componentDivider: AppColors.gray2, + componentText: AppColors.gray8, + error: AppColors.red4, + placeholderText: AppColors.gray9, + ), + shapes: PaymentSheetShape(borderRadius: 16), + ), style: themeMode, ), ); diff --git a/lib/features/plans/plans.dart b/lib/features/plans/plans.dart index ba2eefdc34..f207a89c55 100644 --- a/lib/features/plans/plans.dart +++ b/lib/features/plans/plans.dart @@ -61,7 +61,10 @@ class _PlansState extends ConsumerState { ], ), title: "", - body: SafeArea(child: _buildBody()), + body: SafeArea( + bottom: !PlatformUtils.isIOS, + child: _buildBody(), + ), ); } From 45635538a4384e6a8c63806e00de2c891b499046 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Fri, 20 Feb 2026 11:54:51 +0530 Subject: [PATCH 13/14] stripe theming --- lib/core/services/stripe_service.dart | 40 ++++++++++---------- lib/features/auth/choose_payment_method.dart | 11 +----- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/lib/core/services/stripe_service.dart b/lib/core/services/stripe_service.dart index 0e0f815ca2..735d98dbcd 100644 --- a/lib/core/services/stripe_service.dart +++ b/lib/core/services/stripe_service.dart @@ -1,10 +1,9 @@ import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; import 'package:lantern/core/common/app_secrets.dart'; import 'package:lantern/core/common/common.dart'; -import 'injection_container.dart' show sl; - class StripeService { Future initialize() async { try { @@ -31,14 +30,29 @@ class StripeService { // It takes the StripeOptions object and a callback function for success and error handling // this is only used by android Future startStripeSDK({ + required BuildContext context, required StripeOptions options, required OnPressed onSuccess, required Function(dynamic error) onError, }) async { try { - final theme = - sl().getAppSetting()?.themeMode ?? 'system'; - final themeMode = resolveThemeMode(theme); + // Extract all context-dependent values before any async gap + final brightness = Theme.of(context).brightness; + final style = + brightness == Brightness.dark ? ThemeMode.dark : ThemeMode.light; + final sheetColors = PaymentSheetAppearanceColors( + background: context.bgSurface, + componentBackground: context.bgElevated, + primary: context.actionPrimaryBg, + primaryText: context.textPrimary, + secondaryText: context.textSecondary, + icon: context.textTertiary, + componentBorder: context.borderInput, + componentDivider: context.borderDefault, + componentText: context.textPrimary, + error: AppColors.red4, + placeholderText: context.textDisabled, + ); if (options.publishableKey != null && options.publishableKey!.isNotEmpty) { Stripe.publishableKey = options.publishableKey!; @@ -67,22 +81,10 @@ class StripeService { testEnv: kDebugMode, ), appearance: PaymentSheetAppearance( - colors: PaymentSheetAppearanceColors( - background: AppColors.gray1, - componentBackground: AppColors.white, - primary: AppColors.blue10, - primaryText: AppColors.gray8, - secondaryText: AppColors.black, - icon: AppColors.gray9, - componentBorder: AppColors.gray3, - componentDivider: AppColors.gray2, - componentText: AppColors.gray8, - error: AppColors.red4, - placeholderText: AppColors.gray9, - ), + colors: sheetColors, shapes: PaymentSheetShape(borderRadius: 16), ), - style: themeMode, + style: style, ), ); diff --git a/lib/features/auth/choose_payment_method.dart b/lib/features/auth/choose_payment_method.dart index 2f497d4017..b6b25faabc 100644 --- a/lib/features/auth/choose_payment_method.dart +++ b/lib/features/auth/choose_payment_method.dart @@ -33,15 +33,7 @@ class ChoosePaymentMethod extends HookConsumerWidget { final planData = ref.watch(plansProvider.notifier).getPlanData(); return BaseScreen( title: '', - appBar: CustomAppBar( - title: Text('choose_payment_method'.i18n), - actions: [ - IconButton( - icon: Icon(Icons.more_vert), - onPressed: () => onMoreOptionsPressed(context), - ), - ], - ), + appBar: CustomAppBar(title: Text('choose_payment_method'.i18n)), body: Column( children: [ SizedBox(height: defaultSize), @@ -176,6 +168,7 @@ class ChoosePaymentMethod extends HookConsumerWidget { /// Start stripe SDK sl().startStripeSDK( + context: context, options: StripeOptions.fromJson(stripeData), onSuccess: () { onPurchaseResult(true, context, ref); From 0c7eb7620616f83e0ae5431fdd17cfd8963a2754 Mon Sep 17 00:00:00 2001 From: Jigar-f Date: Fri, 20 Feb 2026 15:27:17 +0530 Subject: [PATCH 14/14] merged main --- lib/core/services/db/objectbox-model.json | 7 ++++++- lib/core/services/db/objectbox.g.dart | 21 +++++++++++++++++-- lib/features/auth/sign_in_password.dart | 2 +- .../home/provider/app_setting_notifier.g.dart | 2 +- .../home/provider/home_notifier.g.dart | 2 +- .../plans/provider/payment_notifier.g.dart | 2 +- .../provider/system_tray_notifier.g.dart | 2 +- 7 files changed, 30 insertions(+), 8 deletions(-) diff --git a/lib/core/services/db/objectbox-model.json b/lib/core/services/db/objectbox-model.json index 9926100149..064ce660ae 100644 --- a/lib/core/services/db/objectbox-model.json +++ b/lib/core/services/db/objectbox-model.json @@ -59,7 +59,7 @@ }, { "id": "2:687217704776011576", - "lastPropertyId": "22:1798613131332202898", + "lastPropertyId": "23:853140105317312758", "name": "AppSetting", "properties": [ { @@ -142,6 +142,11 @@ "id": "22:1798613131332202898", "name": "environment", "type": 9 + }, + { + "id": "23:853140105317312758", + "name": "themeMode", + "type": 9 } ], "relations": [] diff --git a/lib/core/services/db/objectbox.g.dart b/lib/core/services/db/objectbox.g.dart index e86867a9aa..83066d1841 100644 --- a/lib/core/services/db/objectbox.g.dart +++ b/lib/core/services/db/objectbox.g.dart @@ -93,7 +93,7 @@ final _entities = [ obx_int.ModelEntity( id: const obx_int.IdUid(2, 687217704776011576), name: 'AppSetting', - lastPropertyId: const obx_int.IdUid(22, 1798613131332202898), + lastPropertyId: const obx_int.IdUid(23, 853140105317312758), flags: 0, properties: [ obx_int.ModelProperty( @@ -192,6 +192,12 @@ final _entities = [ type: 9, flags: 0, ), + obx_int.ModelProperty( + id: const obx_int.IdUid(23, 853140105317312758), + name: 'themeMode', + type: 9, + flags: 0, + ), ], relations: [], backlinks: [], @@ -1007,7 +1013,8 @@ obx_int.ModelDefinition getObjectBoxModel() { final routingModeRawOffset = fbb.writeString(object.routingModeRaw); final dataCapThresholdOffset = fbb.writeString(object.dataCapThreshold); final environmentOffset = fbb.writeString(object.environment); - fbb.startTable(23); + final themeModeOffset = fbb.writeString(object.themeMode); + fbb.startTable(24); fbb.addInt64(0, object.id); fbb.addBool(1, object.isPro); fbb.addBool(2, object.isSplitTunnelingOn); @@ -1024,6 +1031,7 @@ obx_int.ModelDefinition getObjectBoxModel() { fbb.addOffset(19, dataCapThresholdOffset); fbb.addBool(20, object.onboardingCompleted); fbb.addOffset(21, environmentOffset); + fbb.addOffset(22, themeModeOffset); fbb.finish(fbb.endTable()); return object.id; }, @@ -1105,6 +1113,9 @@ obx_int.ModelDefinition getObjectBoxModel() { 44, false, ); + final themeModeParam = const fb.StringReader( + asciiOptimization: true, + ).vTableGet(buffer, rootOffset, 48, ''); final environmentParam = const fb.StringReader( asciiOptimization: true, ).vTableGet(buffer, rootOffset, 46, ''); @@ -1124,6 +1135,7 @@ obx_int.ModelDefinition getObjectBoxModel() { routingModeRaw: routingModeRawParam, dataCapThreshold: dataCapThresholdParam, onboardingCompleted: onboardingCompletedParam, + themeMode: themeModeParam, environment: environmentParam, ); @@ -2060,6 +2072,11 @@ class AppSetting_ { static final environment = obx.QueryStringProperty( _entities[1].properties[15], ); + + /// See [AppSetting.themeMode]. + static final themeMode = obx.QueryStringProperty( + _entities[1].properties[16], + ); } /// [DeviceEntity] entity fields to define ObjectBox queries. diff --git a/lib/features/auth/sign_in_password.dart b/lib/features/auth/sign_in_password.dart index 8aa91b52a6..4e44501fa1 100644 --- a/lib/features/auth/sign_in_password.dart +++ b/lib/features/auth/sign_in_password.dart @@ -69,7 +69,7 @@ class _SignInPasswordState extends ConsumerState { style: textTheme.labelMedium!.copyWith( color: context.textDisabled, ), - ), + )), SizedBox(height: 16), if (widget.fromChangeEmail) Text('confirm_password_to_continue'.i18n, diff --git a/lib/features/home/provider/app_setting_notifier.g.dart b/lib/features/home/provider/app_setting_notifier.g.dart index 02ac8fb3d5..5b2f2c05cf 100644 --- a/lib/features/home/provider/app_setting_notifier.g.dart +++ b/lib/features/home/provider/app_setting_notifier.g.dart @@ -42,7 +42,7 @@ final class AppSettingNotifierProvider } String _$appSettingNotifierHash() => - r'49e35afce80b0b7b25c62d647cdf3924ee6cc49a'; + r'355d669c54fd042f337506102347b94dcf12c03f'; abstract class _$AppSettingNotifier extends $Notifier { AppSetting build(); diff --git a/lib/features/home/provider/home_notifier.g.dart b/lib/features/home/provider/home_notifier.g.dart index c36c756f93..ac185b25bf 100644 --- a/lib/features/home/provider/home_notifier.g.dart +++ b/lib/features/home/provider/home_notifier.g.dart @@ -33,7 +33,7 @@ final class HomeNotifierProvider HomeNotifier create() => HomeNotifier(); } -String _$homeNotifierHash() => r'8c1c7e93ef15d1bc9bb6a7adf7422e93423294b8'; +String _$homeNotifierHash() => r'acb597e5a3f386fddf86e5b3f3af742ffa93e2c7'; abstract class _$HomeNotifier extends $AsyncNotifier { FutureOr build(); diff --git a/lib/features/plans/provider/payment_notifier.g.dart b/lib/features/plans/provider/payment_notifier.g.dart index f30196ea47..b999fa1da0 100644 --- a/lib/features/plans/provider/payment_notifier.g.dart +++ b/lib/features/plans/provider/payment_notifier.g.dart @@ -41,7 +41,7 @@ final class PaymentNotifierProvider } } -String _$paymentNotifierHash() => r'4348c0acda395c71a0951848746f98000316ef0f'; +String _$paymentNotifierHash() => r'593bf59110bb4eb70a843d440467573d9b5bb5cd'; abstract class _$PaymentNotifier extends $Notifier { void build(); diff --git a/lib/features/system_tray/provider/system_tray_notifier.g.dart b/lib/features/system_tray/provider/system_tray_notifier.g.dart index 7ecf37290f..463367cc03 100644 --- a/lib/features/system_tray/provider/system_tray_notifier.g.dart +++ b/lib/features/system_tray/provider/system_tray_notifier.g.dart @@ -34,7 +34,7 @@ final class SystemTrayNotifierProvider } String _$systemTrayNotifierHash() => - r'f3b5715f964e92493d2736fbd019bf4b9ed292c5'; + r'ab73408f744c3428316f2022851ddc955ea6cc9c'; abstract class _$SystemTrayNotifier extends $AsyncNotifier { FutureOr build();