mobile bluesky app made with flutter lazurite.stormlightlabs.org/
mobile bluesky flutter
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add custom default

+434 -181
+13 -2
lib/core/theme/app_theme.dart
··· 1 1 import 'package:flutter/material.dart'; 2 2 import 'package:lazurite/core/theme/catppuccin_theme.dart'; 3 + import 'package:lazurite/core/theme/lazurite_theme.dart'; 3 4 import 'package:lazurite/core/theme/nord_theme.dart'; 4 5 import 'package:lazurite/core/theme/oxocarbon_theme.dart'; 5 6 import 'package:lazurite/core/theme/rose_pine_theme.dart'; 6 7 7 - enum AppThemePalette { oxocarbon, catppuccin, nord, rosePine } 8 + enum AppThemePalette { lazurite, oxocarbon, catppuccin, nord, rosePine } 8 9 9 10 enum AppThemeVariant { light, dark } 10 11 ··· 13 14 14 15 static ThemeData getTheme(AppThemePalette palette, AppThemeVariant variant) { 15 16 switch (palette) { 17 + case AppThemePalette.lazurite: 18 + return variant == AppThemeVariant.light ? LazuriteTheme.light() : LazuriteTheme.dark(); 16 19 case AppThemePalette.oxocarbon: 17 20 return variant == AppThemeVariant.light ? OxocarbonTheme.light() : OxocarbonTheme.dark(); 18 21 case AppThemePalette.catppuccin: ··· 26 29 27 30 static String getPaletteName(AppThemePalette palette) { 28 31 switch (palette) { 32 + case AppThemePalette.lazurite: 33 + return 'Lazurite'; 29 34 case AppThemePalette.oxocarbon: 30 35 return 'Oxocarbon'; 31 36 case AppThemePalette.catppuccin: ··· 48 53 49 54 static AppThemePalette parsePalette(String? value) { 50 55 switch (value) { 56 + case 'lazurite': 57 + return AppThemePalette.lazurite; 51 58 case 'oxocarbon': 52 59 return AppThemePalette.oxocarbon; 53 60 case 'catppuccin': ··· 57 64 case 'rosePine': 58 65 return AppThemePalette.rosePine; 59 66 default: 60 - return AppThemePalette.oxocarbon; 67 + return AppThemePalette.lazurite; 61 68 } 62 69 } 63 70 64 71 static String paletteToString(AppThemePalette palette) { 65 72 switch (palette) { 73 + case AppThemePalette.lazurite: 74 + return 'lazurite'; 66 75 case AppThemePalette.oxocarbon: 67 76 return 'oxocarbon'; 68 77 case AppThemePalette.catppuccin: ··· 96 105 97 106 static List<Color> getSwatchColors(AppThemePalette palette) { 98 107 switch (palette) { 108 + case AppThemePalette.lazurite: 109 + return const [Color(0xFF7dafff), Color(0xFF0b63d1), Color(0xFF0073de), Color(0xFFff8080)]; 99 110 case AppThemePalette.oxocarbon: 100 111 return const [Color(0xFF78a9ff), Color(0xFFbe95ff), Color(0xFF08bdba), Color(0xFFee5396)]; 101 112 case AppThemePalette.catppuccin:
+16 -16
lib/core/theme/catppuccin_theme.dart
··· 67 67 backgroundColor: mochaBase, 68 68 foregroundColor: mochaText, 69 69 surfaceTintColor: mochaLavender, 70 - titleTextStyle: AppTypography.dmSans(fontSize: 18, fontWeight: FontWeight.w600, color: mochaText), 70 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: mochaText), 71 71 ), 72 72 cardTheme: const CardThemeData(color: mochaMantle, surfaceTintColor: mochaLavender), 73 73 dividerTheme: const DividerThemeData(color: mochaSurface0), ··· 75 75 listTileTheme: ListTileThemeData( 76 76 textColor: mochaText, 77 77 iconColor: mochaSubtext0, 78 - titleTextStyle: AppTypography.dmSans(fontSize: 16, fontWeight: FontWeight.w500, color: mochaText), 79 - subtitleTextStyle: AppTypography.dmSans(fontSize: 14, color: mochaSubtext0), 78 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: mochaText), 79 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: mochaSubtext0), 80 80 ), 81 81 textTheme: AppTypography.textTheme(bodyColor: mochaText, headlineColor: mochaText, captionColor: mochaSurface1), 82 82 floatingActionButtonTheme: const FloatingActionButtonThemeData( ··· 87 87 style: ElevatedButton.styleFrom( 88 88 backgroundColor: mochaLavender, 89 89 foregroundColor: mochaBase, 90 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 90 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 91 91 ), 92 92 ), 93 93 textButtonTheme: TextButtonThemeData( 94 94 style: TextButton.styleFrom( 95 95 foregroundColor: mochaLavender, 96 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 96 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 97 97 ), 98 98 ), 99 99 inputDecorationTheme: InputDecorationTheme( ··· 102 102 border: const OutlineInputBorder(borderSide: BorderSide(color: mochaSurface0)), 103 103 enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: mochaSurface0)), 104 104 focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: mochaLavender)), 105 - labelStyle: AppTypography.dmSans(color: mochaSurface1), 106 - hintStyle: AppTypography.dmSans(color: mochaSurface1), 105 + labelStyle: AppTypography.googleSans(color: mochaSurface1), 106 + hintStyle: AppTypography.googleSans(color: mochaSurface1), 107 107 ), 108 108 snackBarTheme: SnackBarThemeData( 109 109 backgroundColor: mochaMantle, 110 - contentTextStyle: AppTypography.dmSans(color: mochaText), 110 + contentTextStyle: AppTypography.googleSans(color: mochaText), 111 111 ), 112 112 ); 113 113 } ··· 143 143 backgroundColor: latteBase, 144 144 foregroundColor: latteText, 145 145 surfaceTintColor: latteLavender, 146 - titleTextStyle: AppTypography.dmSans(fontSize: 18, fontWeight: FontWeight.w600, color: latteText), 146 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: latteText), 147 147 ), 148 148 cardTheme: const CardThemeData(color: latteMantle, surfaceTintColor: latteLavender), 149 149 dividerTheme: const DividerThemeData(color: latteSurface0), ··· 151 151 listTileTheme: ListTileThemeData( 152 152 textColor: latteText, 153 153 iconColor: latteSubtext0, 154 - titleTextStyle: AppTypography.dmSans(fontSize: 16, fontWeight: FontWeight.w500, color: latteText), 155 - subtitleTextStyle: AppTypography.dmSans(fontSize: 14, color: latteSubtext0), 154 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: latteText), 155 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: latteSubtext0), 156 156 ), 157 157 textTheme: AppTypography.textTheme(bodyColor: latteText, headlineColor: latteText, captionColor: latteSurface1), 158 158 floatingActionButtonTheme: const FloatingActionButtonThemeData( ··· 163 163 style: ElevatedButton.styleFrom( 164 164 backgroundColor: latteLavender, 165 165 foregroundColor: latteBase, 166 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 166 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 167 167 ), 168 168 ), 169 169 textButtonTheme: TextButtonThemeData( 170 170 style: TextButton.styleFrom( 171 171 foregroundColor: latteLavender, 172 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 172 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 173 173 ), 174 174 ), 175 175 inputDecorationTheme: InputDecorationTheme( ··· 178 178 border: const OutlineInputBorder(borderSide: BorderSide(color: latteSurface0)), 179 179 enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: latteSurface0)), 180 180 focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: latteLavender)), 181 - labelStyle: AppTypography.dmSans(color: latteSurface1), 182 - hintStyle: AppTypography.dmSans(color: latteSurface1), 181 + labelStyle: AppTypography.googleSans(color: latteSurface1), 182 + hintStyle: AppTypography.googleSans(color: latteSurface1), 183 183 ), 184 184 snackBarTheme: SnackBarThemeData( 185 185 backgroundColor: latteMantle, 186 - contentTextStyle: AppTypography.dmSans(color: latteText), 186 + contentTextStyle: AppTypography.googleSans(color: latteText), 187 187 ), 188 188 ); 189 189 }
+226
lib/core/theme/lazurite_theme.dart
··· 1 + import 'package:flutter/material.dart'; 2 + import 'package:lazurite/core/theme/typography.dart'; 3 + 4 + class LazuriteTheme { 5 + LazuriteTheme._(); 6 + 7 + static const Color darkPrimary = Color(0xFF7dafff); 8 + static const Color darkOnPrimary = Color(0xFF05080f); 9 + static const Color darkPrimaryContainer = Color(0xFF0073de); 10 + static const Color darkOnPrimaryContainer = Color(0xFFf4f6fb); 11 + static const Color darkSurface = Color(0xFF0e0e0e); 12 + static const Color darkOnSurface = Color(0xFFf4f6fb); 13 + static const Color darkSurfaceVariant = Color(0xFF191919); 14 + static const Color darkOnSurfaceVariant = Color(0xFFababab); 15 + static const Color darkSurfaceContainerLowest = Color(0xFF000000); 16 + static const Color darkSurfaceContainer = Color(0xFF191919); 17 + static const Color darkSurfaceContainerHigh = Color(0xFF1f1f1f); 18 + static const Color darkSurfaceContainerHighest = Color(0xF5242424); 19 + static const Color darkSurfaceBright = Color(0x0Dffffff); 20 + static const Color darkOutline = Color(0x33ffffff); 21 + static const Color darkOutlineVariant = Color(0x1Affffff); 22 + static const Color darkError = Color(0xFFff8080); 23 + static const Color darkErrorContainer = Color(0xB88a1f1f); 24 + 25 + static const Color lightPrimary = Color(0xFF0b63d1); 26 + static const Color lightOnPrimary = Color(0xFFffffff); 27 + static const Color lightPrimaryContainer = Color(0xFF0953af); 28 + static const Color lightOnPrimaryContainer = Color(0xFFffffff); 29 + static const Color lightSurface = Color(0xFFffffff); 30 + static const Color lightOnSurface = Color(0xFF101418); 31 + static const Color lightSurfaceVariant = Color(0xFFf4f6f9); 32 + static const Color lightOnSurfaceVariant = Color(0xFF45505e); 33 + static const Color lightSurfaceContainerLowest = Color(0xFFeef1f5); 34 + static const Color lightSurfaceContainer = Color(0xFFf4f6f9); 35 + static const Color lightSurfaceContainerHigh = Color(0xFFeceff4); 36 + static const Color lightSurfaceContainerHighest = Color(0xF5f6f8fc); 37 + static const Color lightSurfaceBright = Color(0x0F111827); 38 + static const Color lightOutline = Color(0x3D111827); 39 + static const Color lightOutlineVariant = Color(0x24111827); 40 + static const Color lightError = Color(0xFFb42318); 41 + static const Color lightErrorContainer = Color(0xF2fee2e2); 42 + 43 + static ThemeData dark() { 44 + return ThemeData( 45 + useMaterial3: true, 46 + brightness: Brightness.dark, 47 + colorScheme: const ColorScheme( 48 + brightness: Brightness.dark, 49 + primary: darkPrimary, 50 + onPrimary: darkOnPrimary, 51 + primaryContainer: darkPrimaryContainer, 52 + onPrimaryContainer: darkOnPrimaryContainer, 53 + secondary: darkPrimaryContainer, 54 + onSecondary: darkOnPrimaryContainer, 55 + secondaryContainer: darkSurfaceContainer, 56 + onSecondaryContainer: darkOnSurface, 57 + tertiary: darkPrimary, 58 + onTertiary: darkOnPrimary, 59 + tertiaryContainer: darkSurfaceContainerHigh, 60 + onTertiaryContainer: darkOnSurface, 61 + error: darkError, 62 + onError: darkOnPrimary, 63 + errorContainer: darkErrorContainer, 64 + onErrorContainer: darkOnSurface, 65 + surface: darkSurface, 66 + onSurface: darkOnSurface, 67 + surfaceBright: darkSurfaceBright, 68 + surfaceContainerLowest: darkSurfaceContainerLowest, 69 + surfaceContainerLow: darkSurfaceVariant, 70 + surfaceContainer: darkSurfaceContainer, 71 + surfaceContainerHigh: darkSurfaceContainerHigh, 72 + surfaceContainerHighest: darkSurfaceContainerHighest, 73 + onSurfaceVariant: darkOnSurfaceVariant, 74 + outline: darkOutline, 75 + outlineVariant: darkOutlineVariant, 76 + inverseSurface: lightSurface, 77 + onInverseSurface: lightOnSurface, 78 + inversePrimary: lightPrimary, 79 + surfaceTint: darkPrimary, 80 + ), 81 + scaffoldBackgroundColor: darkSurfaceContainerLowest, 82 + appBarTheme: AppBarTheme( 83 + backgroundColor: darkSurfaceContainerLowest, 84 + foregroundColor: darkOnSurface, 85 + surfaceTintColor: darkPrimary, 86 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: darkOnSurface), 87 + ), 88 + cardTheme: const CardThemeData(color: darkSurfaceContainer, surfaceTintColor: darkPrimary), 89 + dividerTheme: const DividerThemeData(color: darkOutlineVariant), 90 + iconTheme: const IconThemeData(color: darkOnSurfaceVariant), 91 + listTileTheme: ListTileThemeData( 92 + textColor: darkOnSurface, 93 + iconColor: darkOnSurfaceVariant, 94 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: darkOnSurface), 95 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: darkOnSurfaceVariant), 96 + ), 97 + textTheme: AppTypography.textTheme( 98 + bodyColor: darkOnSurface, 99 + headlineColor: darkOnSurface, 100 + captionColor: darkOnSurfaceVariant, 101 + ), 102 + floatingActionButtonTheme: const FloatingActionButtonThemeData( 103 + backgroundColor: darkPrimary, 104 + foregroundColor: darkOnPrimary, 105 + ), 106 + elevatedButtonTheme: ElevatedButtonThemeData( 107 + style: ElevatedButton.styleFrom( 108 + backgroundColor: darkPrimary, 109 + foregroundColor: darkOnPrimary, 110 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 111 + ), 112 + ), 113 + textButtonTheme: TextButtonThemeData( 114 + style: TextButton.styleFrom( 115 + foregroundColor: darkPrimary, 116 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 117 + ), 118 + ), 119 + inputDecorationTheme: InputDecorationTheme( 120 + filled: true, 121 + fillColor: darkSurfaceContainerHigh, 122 + border: const OutlineInputBorder(borderSide: BorderSide(color: darkOutlineVariant)), 123 + enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: darkOutlineVariant)), 124 + focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: darkPrimary)), 125 + labelStyle: AppTypography.googleSans(color: darkOnSurfaceVariant), 126 + hintStyle: AppTypography.googleSans(color: darkOnSurfaceVariant), 127 + ), 128 + snackBarTheme: SnackBarThemeData( 129 + backgroundColor: darkSurfaceContainerHighest, 130 + contentTextStyle: AppTypography.googleSans(color: darkOnSurface), 131 + ), 132 + ); 133 + } 134 + 135 + static ThemeData light() { 136 + return ThemeData( 137 + useMaterial3: true, 138 + brightness: Brightness.light, 139 + colorScheme: const ColorScheme( 140 + brightness: Brightness.light, 141 + primary: lightPrimary, 142 + onPrimary: lightOnPrimary, 143 + primaryContainer: lightPrimaryContainer, 144 + onPrimaryContainer: lightOnPrimaryContainer, 145 + secondary: lightPrimaryContainer, 146 + onSecondary: lightOnPrimaryContainer, 147 + secondaryContainer: lightSurfaceContainer, 148 + onSecondaryContainer: lightOnSurface, 149 + tertiary: lightPrimary, 150 + onTertiary: lightOnPrimary, 151 + tertiaryContainer: lightSurfaceContainerHigh, 152 + onTertiaryContainer: lightOnSurface, 153 + error: lightError, 154 + onError: lightOnPrimary, 155 + errorContainer: lightErrorContainer, 156 + onErrorContainer: lightOnSurface, 157 + surface: lightSurface, 158 + onSurface: lightOnSurface, 159 + surfaceBright: lightSurfaceBright, 160 + surfaceContainerLowest: lightSurfaceContainerLowest, 161 + surfaceContainerLow: lightSurfaceVariant, 162 + surfaceContainer: lightSurfaceContainer, 163 + surfaceContainerHigh: lightSurfaceContainerHigh, 164 + surfaceContainerHighest: lightSurfaceContainerHighest, 165 + onSurfaceVariant: lightOnSurfaceVariant, 166 + outline: lightOutline, 167 + outlineVariant: lightOutlineVariant, 168 + inverseSurface: darkSurface, 169 + onInverseSurface: darkOnSurface, 170 + inversePrimary: darkPrimary, 171 + surfaceTint: lightPrimary, 172 + ), 173 + scaffoldBackgroundColor: lightSurface, 174 + appBarTheme: AppBarTheme( 175 + backgroundColor: lightSurface, 176 + foregroundColor: lightOnSurface, 177 + surfaceTintColor: lightPrimary, 178 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: lightOnSurface), 179 + ), 180 + cardTheme: const CardThemeData(color: lightSurfaceContainer, surfaceTintColor: lightPrimary), 181 + dividerTheme: const DividerThemeData(color: lightOutlineVariant), 182 + iconTheme: const IconThemeData(color: lightOnSurfaceVariant), 183 + listTileTheme: ListTileThemeData( 184 + textColor: lightOnSurface, 185 + iconColor: lightOnSurfaceVariant, 186 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: lightOnSurface), 187 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: lightOnSurfaceVariant), 188 + ), 189 + textTheme: AppTypography.textTheme( 190 + bodyColor: lightOnSurface, 191 + headlineColor: lightOnSurface, 192 + captionColor: lightOnSurfaceVariant, 193 + ), 194 + floatingActionButtonTheme: const FloatingActionButtonThemeData( 195 + backgroundColor: lightPrimary, 196 + foregroundColor: lightOnPrimary, 197 + ), 198 + elevatedButtonTheme: ElevatedButtonThemeData( 199 + style: ElevatedButton.styleFrom( 200 + backgroundColor: lightPrimary, 201 + foregroundColor: lightOnPrimary, 202 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 203 + ), 204 + ), 205 + textButtonTheme: TextButtonThemeData( 206 + style: TextButton.styleFrom( 207 + foregroundColor: lightPrimary, 208 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 209 + ), 210 + ), 211 + inputDecorationTheme: InputDecorationTheme( 212 + filled: true, 213 + fillColor: lightSurfaceContainer, 214 + border: const OutlineInputBorder(borderSide: BorderSide(color: lightOutlineVariant)), 215 + enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: lightOutlineVariant)), 216 + focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: lightPrimary)), 217 + labelStyle: AppTypography.googleSans(color: lightOnSurfaceVariant), 218 + hintStyle: AppTypography.googleSans(color: lightOnSurfaceVariant), 219 + ), 220 + snackBarTheme: SnackBarThemeData( 221 + backgroundColor: lightSurfaceContainerHighest, 222 + contentTextStyle: AppTypography.googleSans(color: lightOnSurface), 223 + ), 224 + ); 225 + } 226 + }
+16 -16
lib/core/theme/nord_theme.dart
··· 52 52 backgroundColor: nord0, 53 53 foregroundColor: nord5, 54 54 surfaceTintColor: nord8, 55 - titleTextStyle: AppTypography.dmSans(fontSize: 18, fontWeight: FontWeight.w600, color: nord5), 55 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: nord5), 56 56 ), 57 57 cardTheme: const CardThemeData(color: nord1, surfaceTintColor: nord8), 58 58 dividerTheme: const DividerThemeData(color: nord2), ··· 60 60 listTileTheme: ListTileThemeData( 61 61 textColor: nord5, 62 62 iconColor: nord4, 63 - titleTextStyle: AppTypography.dmSans(fontSize: 16, fontWeight: FontWeight.w500, color: nord5), 64 - subtitleTextStyle: AppTypography.dmSans(fontSize: 14, color: nord4), 63 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: nord5), 64 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: nord4), 65 65 ), 66 66 textTheme: AppTypography.textTheme(bodyColor: nord5, headlineColor: nord6, captionColor: nord3), 67 67 floatingActionButtonTheme: const FloatingActionButtonThemeData(backgroundColor: nord8, foregroundColor: nord0), ··· 69 69 style: ElevatedButton.styleFrom( 70 70 backgroundColor: nord8, 71 71 foregroundColor: nord0, 72 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 72 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 73 73 ), 74 74 ), 75 75 textButtonTheme: TextButtonThemeData( 76 76 style: TextButton.styleFrom( 77 77 foregroundColor: nord8, 78 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 78 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 79 79 ), 80 80 ), 81 81 inputDecorationTheme: InputDecorationTheme( ··· 84 84 border: const OutlineInputBorder(borderSide: BorderSide(color: nord2)), 85 85 enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: nord2)), 86 86 focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: nord8)), 87 - labelStyle: AppTypography.dmSans(color: nord3), 88 - hintStyle: AppTypography.dmSans(color: nord3), 87 + labelStyle: AppTypography.googleSans(color: nord3), 88 + hintStyle: AppTypography.googleSans(color: nord3), 89 89 ), 90 90 snackBarTheme: SnackBarThemeData( 91 91 backgroundColor: nord1, 92 - contentTextStyle: AppTypography.dmSans(color: nord5), 92 + contentTextStyle: AppTypography.googleSans(color: nord5), 93 93 ), 94 94 ); 95 95 } ··· 125 125 backgroundColor: nord6, 126 126 foregroundColor: nord3, 127 127 surfaceTintColor: nord8, 128 - titleTextStyle: AppTypography.dmSans(fontSize: 18, fontWeight: FontWeight.w600, color: nord3), 128 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: nord3), 129 129 ), 130 130 cardTheme: const CardThemeData(color: nord5, surfaceTintColor: nord8), 131 131 dividerTheme: const DividerThemeData(color: nord2), ··· 133 133 listTileTheme: ListTileThemeData( 134 134 textColor: nord3, 135 135 iconColor: nord4, 136 - titleTextStyle: AppTypography.dmSans(fontSize: 16, fontWeight: FontWeight.w500, color: nord3), 137 - subtitleTextStyle: AppTypography.dmSans(fontSize: 14, color: nord4), 136 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: nord3), 137 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: nord4), 138 138 ), 139 139 textTheme: AppTypography.textTheme(bodyColor: nord3, headlineColor: nord0, captionColor: nord3), 140 140 floatingActionButtonTheme: const FloatingActionButtonThemeData(backgroundColor: nord8, foregroundColor: nord0), ··· 142 142 style: ElevatedButton.styleFrom( 143 143 backgroundColor: nord8, 144 144 foregroundColor: nord0, 145 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 145 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 146 146 ), 147 147 ), 148 148 textButtonTheme: TextButtonThemeData( 149 149 style: TextButton.styleFrom( 150 150 foregroundColor: nord8, 151 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 151 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 152 152 ), 153 153 ), 154 154 inputDecorationTheme: InputDecorationTheme( ··· 157 157 border: const OutlineInputBorder(borderSide: BorderSide(color: nord2)), 158 158 enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: nord2)), 159 159 focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: nord8)), 160 - labelStyle: AppTypography.dmSans(color: nord3), 161 - hintStyle: AppTypography.dmSans(color: nord3), 160 + labelStyle: AppTypography.googleSans(color: nord3), 161 + hintStyle: AppTypography.googleSans(color: nord3), 162 162 ), 163 163 snackBarTheme: SnackBarThemeData( 164 164 backgroundColor: nord5, 165 - contentTextStyle: AppTypography.dmSans(color: nord3), 165 + contentTextStyle: AppTypography.googleSans(color: nord3), 166 166 ), 167 167 ); 168 168 }
+16 -16
lib/core/theme/oxocarbon_theme.dart
··· 69 69 backgroundColor: darkBase00, 70 70 foregroundColor: darkBase05, 71 71 surfaceTintColor: darkBase09, 72 - titleTextStyle: AppTypography.dmSans(fontSize: 18, fontWeight: FontWeight.w600, color: darkBase05), 72 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: darkBase05), 73 73 ), 74 74 cardTheme: const CardThemeData(color: darkBase01, surfaceTintColor: darkBase09), 75 75 dividerTheme: const DividerThemeData(color: darkBase02), ··· 77 77 listTileTheme: ListTileThemeData( 78 78 textColor: darkBase05, 79 79 iconColor: darkBase04, 80 - titleTextStyle: AppTypography.dmSans(fontSize: 16, fontWeight: FontWeight.w500, color: darkBase05), 81 - subtitleTextStyle: AppTypography.dmSans(fontSize: 14, color: darkBase04), 80 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: darkBase05), 81 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: darkBase04), 82 82 ), 83 83 textTheme: AppTypography.textTheme(bodyColor: darkBase05, headlineColor: darkBase06, captionColor: darkBase03), 84 84 floatingActionButtonTheme: const FloatingActionButtonThemeData( ··· 89 89 style: ElevatedButton.styleFrom( 90 90 backgroundColor: darkBase09, 91 91 foregroundColor: darkBase00, 92 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 92 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 93 93 ), 94 94 ), 95 95 textButtonTheme: TextButtonThemeData( 96 96 style: TextButton.styleFrom( 97 97 foregroundColor: darkBase09, 98 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 98 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 99 99 ), 100 100 ), 101 101 inputDecorationTheme: InputDecorationTheme( ··· 104 104 border: const OutlineInputBorder(borderSide: BorderSide(color: darkBase02)), 105 105 enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: darkBase02)), 106 106 focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: darkBase09)), 107 - labelStyle: AppTypography.dmSans(color: darkBase03), 108 - hintStyle: AppTypography.dmSans(color: darkBase03), 107 + labelStyle: AppTypography.googleSans(color: darkBase03), 108 + hintStyle: AppTypography.googleSans(color: darkBase03), 109 109 ), 110 110 snackBarTheme: SnackBarThemeData( 111 111 backgroundColor: darkBase01, 112 - contentTextStyle: AppTypography.dmSans(color: darkBase05), 112 + contentTextStyle: AppTypography.googleSans(color: darkBase05), 113 113 ), 114 114 ); 115 115 } ··· 145 145 backgroundColor: lightBase00, 146 146 foregroundColor: lightBase03, 147 147 surfaceTintColor: lightBase0B, 148 - titleTextStyle: AppTypography.dmSans(fontSize: 18, fontWeight: FontWeight.w600, color: lightBase03), 148 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: lightBase03), 149 149 ), 150 150 cardTheme: const CardThemeData(color: lightBase01, surfaceTintColor: lightBase0B), 151 151 dividerTheme: const DividerThemeData(color: lightBase02), ··· 153 153 listTileTheme: ListTileThemeData( 154 154 textColor: lightBase03, 155 155 iconColor: lightBase04, 156 - titleTextStyle: AppTypography.dmSans(fontSize: 16, fontWeight: FontWeight.w500, color: lightBase03), 157 - subtitleTextStyle: AppTypography.dmSans(fontSize: 14, color: lightBase04), 156 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: lightBase03), 157 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: lightBase04), 158 158 ), 159 159 textTheme: AppTypography.textTheme(bodyColor: lightBase03, headlineColor: lightBase03, captionColor: lightBase05), 160 160 floatingActionButtonTheme: const FloatingActionButtonThemeData( ··· 165 165 style: ElevatedButton.styleFrom( 166 166 backgroundColor: lightBase0B, 167 167 foregroundColor: lightBase00, 168 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 168 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 169 169 ), 170 170 ), 171 171 textButtonTheme: TextButtonThemeData( 172 172 style: TextButton.styleFrom( 173 173 foregroundColor: lightBase0B, 174 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 174 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 175 175 ), 176 176 ), 177 177 inputDecorationTheme: InputDecorationTheme( ··· 180 180 border: const OutlineInputBorder(borderSide: BorderSide(color: lightBase02)), 181 181 enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: lightBase02)), 182 182 focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: lightBase0B)), 183 - labelStyle: AppTypography.dmSans(color: lightBase05), 184 - hintStyle: AppTypography.dmSans(color: lightBase05), 183 + labelStyle: AppTypography.googleSans(color: lightBase05), 184 + hintStyle: AppTypography.googleSans(color: lightBase05), 185 185 ), 186 186 snackBarTheme: SnackBarThemeData( 187 187 backgroundColor: lightBase01, 188 - contentTextStyle: AppTypography.dmSans(color: lightBase03), 188 + contentTextStyle: AppTypography.googleSans(color: lightBase03), 189 189 ), 190 190 ); 191 191 }
+16 -16
lib/core/theme/rose_pine_theme.dart
··· 61 61 backgroundColor: mainBase, 62 62 foregroundColor: mainText, 63 63 surfaceTintColor: mainRose, 64 - titleTextStyle: AppTypography.dmSans(fontSize: 18, fontWeight: FontWeight.w600, color: mainText), 64 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: mainText), 65 65 ), 66 66 cardTheme: const CardThemeData(color: mainSurface, surfaceTintColor: mainRose), 67 67 dividerTheme: const DividerThemeData(color: mainOverlay), ··· 69 69 listTileTheme: ListTileThemeData( 70 70 textColor: mainText, 71 71 iconColor: mainSubtle, 72 - titleTextStyle: AppTypography.dmSans(fontSize: 16, fontWeight: FontWeight.w500, color: mainText), 73 - subtitleTextStyle: AppTypography.dmSans(fontSize: 14, color: mainSubtle), 72 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: mainText), 73 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: mainSubtle), 74 74 ), 75 75 textTheme: AppTypography.textTheme(bodyColor: mainText, headlineColor: mainText, captionColor: mainMuted), 76 76 floatingActionButtonTheme: const FloatingActionButtonThemeData( ··· 81 81 style: ElevatedButton.styleFrom( 82 82 backgroundColor: mainRose, 83 83 foregroundColor: mainBase, 84 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 84 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 85 85 ), 86 86 ), 87 87 textButtonTheme: TextButtonThemeData( 88 88 style: TextButton.styleFrom( 89 89 foregroundColor: mainRose, 90 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 90 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 91 91 ), 92 92 ), 93 93 inputDecorationTheme: InputDecorationTheme( ··· 96 96 border: const OutlineInputBorder(borderSide: BorderSide(color: mainOverlay)), 97 97 enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: mainOverlay)), 98 98 focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: mainRose)), 99 - labelStyle: AppTypography.dmSans(color: mainMuted), 100 - hintStyle: AppTypography.dmSans(color: mainMuted), 99 + labelStyle: AppTypography.googleSans(color: mainMuted), 100 + hintStyle: AppTypography.googleSans(color: mainMuted), 101 101 ), 102 102 snackBarTheme: SnackBarThemeData( 103 103 backgroundColor: mainSurface, 104 - contentTextStyle: AppTypography.dmSans(color: mainText), 104 + contentTextStyle: AppTypography.googleSans(color: mainText), 105 105 ), 106 106 ); 107 107 } ··· 137 137 backgroundColor: dawnBase, 138 138 foregroundColor: dawnText, 139 139 surfaceTintColor: dawnRose, 140 - titleTextStyle: AppTypography.dmSans(fontSize: 18, fontWeight: FontWeight.w600, color: dawnText), 140 + titleTextStyle: AppTypography.googleSans(fontSize: 18, fontWeight: FontWeight.w600, color: dawnText), 141 141 ), 142 142 cardTheme: const CardThemeData(color: dawnSurface, surfaceTintColor: dawnRose), 143 143 dividerTheme: const DividerThemeData(color: dawnOverlay), ··· 145 145 listTileTheme: ListTileThemeData( 146 146 textColor: dawnText, 147 147 iconColor: dawnSubtle, 148 - titleTextStyle: AppTypography.dmSans(fontSize: 16, fontWeight: FontWeight.w500, color: dawnText), 149 - subtitleTextStyle: AppTypography.dmSans(fontSize: 14, color: dawnSubtle), 148 + titleTextStyle: AppTypography.googleSans(fontSize: 16, fontWeight: FontWeight.w500, color: dawnText), 149 + subtitleTextStyle: AppTypography.googleSans(fontSize: 14, color: dawnSubtle), 150 150 ), 151 151 textTheme: AppTypography.textTheme(bodyColor: dawnText, headlineColor: dawnText, captionColor: dawnMuted), 152 152 floatingActionButtonTheme: const FloatingActionButtonThemeData( ··· 157 157 style: ElevatedButton.styleFrom( 158 158 backgroundColor: dawnRose, 159 159 foregroundColor: dawnBase, 160 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 160 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 161 161 ), 162 162 ), 163 163 textButtonTheme: TextButtonThemeData( 164 164 style: TextButton.styleFrom( 165 165 foregroundColor: dawnRose, 166 - textStyle: AppTypography.dmSans(fontSize: 14, fontWeight: FontWeight.w500), 166 + textStyle: AppTypography.googleSans(fontSize: 14, fontWeight: FontWeight.w500), 167 167 ), 168 168 ), 169 169 inputDecorationTheme: InputDecorationTheme( ··· 172 172 border: const OutlineInputBorder(borderSide: BorderSide(color: dawnOverlay)), 173 173 enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: dawnOverlay)), 174 174 focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: dawnRose)), 175 - labelStyle: AppTypography.dmSans(color: dawnMuted), 176 - hintStyle: AppTypography.dmSans(color: dawnMuted), 175 + labelStyle: AppTypography.googleSans(color: dawnMuted), 176 + hintStyle: AppTypography.googleSans(color: dawnMuted), 177 177 ), 178 178 snackBarTheme: SnackBarThemeData( 179 179 backgroundColor: dawnSurface, 180 - contentTextStyle: AppTypography.dmSans(color: dawnText), 180 + contentTextStyle: AppTypography.googleSans(color: dawnText), 181 181 ), 182 182 ); 183 183 }
+10 -10
lib/core/theme/typography.dart
··· 4 4 class AppTypography { 5 5 AppTypography._(); 6 6 7 - static TextStyle dmSans({ 7 + static TextStyle googleSans({ 8 8 double fontSize = 14, 9 9 FontWeight fontWeight = FontWeight.normal, 10 10 Color? color, 11 11 double? letterSpacing, 12 12 double? height, 13 13 }) { 14 - return GoogleFonts.dmSans( 14 + return GoogleFonts.googleSans( 15 15 fontSize: fontSize, 16 16 fontWeight: fontWeight, 17 17 color: color, ··· 36 36 ); 37 37 } 38 38 39 - static TextStyle jetBrainsMono({ 39 + static TextStyle googleSansCode({ 40 40 double fontSize = 14, 41 41 FontWeight fontWeight = FontWeight.normal, 42 42 Color? color, 43 43 double? letterSpacing, 44 44 double? height, 45 45 }) { 46 - return GoogleFonts.jetBrainsMono( 46 + return GoogleFonts.googleSansCode( 47 47 fontSize: fontSize, 48 48 fontWeight: fontWeight, 49 49 color: color, ··· 63 63 titleLarge: lora(fontSize: 22, fontWeight: FontWeight.w600, color: bodyColor), 64 64 titleMedium: lora(fontSize: 16, fontWeight: FontWeight.w500, color: bodyColor, letterSpacing: 0.15), 65 65 titleSmall: lora(fontSize: 14, fontWeight: FontWeight.w500, color: bodyColor, letterSpacing: 0.1), 66 - bodyLarge: dmSans(fontSize: 16, fontWeight: FontWeight.w400, color: bodyColor, letterSpacing: 0.5), 67 - bodyMedium: dmSans(fontSize: 14, fontWeight: FontWeight.w400, color: bodyColor, letterSpacing: 0.25), 68 - bodySmall: dmSans(fontSize: 12, fontWeight: FontWeight.w400, color: captionColor, letterSpacing: 0.4), 69 - labelLarge: dmSans(fontSize: 14, fontWeight: FontWeight.w500, color: bodyColor, letterSpacing: 0.1), 70 - labelMedium: dmSans(fontSize: 12, fontWeight: FontWeight.w500, color: bodyColor, letterSpacing: 0.5), 71 - labelSmall: dmSans(fontSize: 12, fontWeight: FontWeight.w500, color: captionColor, letterSpacing: 0.5), 66 + bodyLarge: googleSans(fontSize: 16, fontWeight: FontWeight.w400, color: bodyColor, letterSpacing: 0.5), 67 + bodyMedium: googleSans(fontSize: 14, fontWeight: FontWeight.w400, color: bodyColor, letterSpacing: 0.25), 68 + bodySmall: googleSans(fontSize: 12, fontWeight: FontWeight.w400, color: captionColor, letterSpacing: 0.4), 69 + labelLarge: googleSans(fontSize: 14, fontWeight: FontWeight.w500, color: bodyColor, letterSpacing: 0.1), 70 + labelMedium: googleSans(fontSize: 12, fontWeight: FontWeight.w500, color: bodyColor, letterSpacing: 0.5), 71 + labelSmall: googleSans(fontSize: 12, fontWeight: FontWeight.w500, color: captionColor, letterSpacing: 0.5), 72 72 ); 73 73 } 74 74 }
+4 -46
lib/core/widgets/lazurite_app_bar.dart
··· 2 2 import 'package:flutter_bloc/flutter_bloc.dart'; 3 3 import 'package:lazurite/core/logging/app_logger.dart'; 4 4 import 'package:lazurite/core/router/app_shell.dart'; 5 - import 'package:lazurite/features/auth/bloc/auth_bloc.dart'; 6 5 import 'package:lazurite/features/connectivity/cubit/connectivity_cubit.dart'; 7 6 import 'package:lazurite/features/settings/bloc/settings_cubit.dart'; 8 7 9 8 /// Custom top app bar for the Lazurite shell screens. 10 9 /// 11 - /// Shows a hamburger button on the left, a section label (uppercase, 12 - /// letterSpacing 3, labelSmall, onSurfaceVariant), and a square user 13 - /// avatar thumbnail on the right. 10 + /// Shows a hamburger button on the left and a section label (uppercase, 11 + /// letterSpacing 3, labelSmall, onSurfaceVariant) 14 12 /// 15 13 /// Pass [bottom] to add an additional row below the toolbar (e.g., for the 16 14 /// home-screen feed-switcher tabs). 17 15 class LazuriteAppBar extends StatelessWidget implements PreferredSizeWidget { 18 - const LazuriteAppBar({super.key, required this.sectionLabel, this.bottom, this.actions, this.showAvatar = true}); 16 + const LazuriteAppBar({super.key, required this.sectionLabel, this.bottom, this.actions}); 19 17 20 18 final String sectionLabel; 21 19 final PreferredSizeWidget? bottom; 22 20 final List<Widget>? actions; 23 - final bool showAvatar; 24 21 25 22 static const double _toolbarHeight = 64; 26 23 ··· 43 40 ), 44 41 centerTitle: false, 45 42 titleSpacing: 0, 46 - actions: [ 47 - ...?actions, 48 - const _AppBarOfflineIndicator(), 49 - if (showAvatar) ...[const _AppBarAvatar(), const SizedBox(width: 8)], 50 - ], 43 + actions: [...?actions, const _AppBarOfflineIndicator()], 51 44 bottom: bottom, 52 45 shape: Border(bottom: BorderSide(color: theme.colorScheme.outlineVariant)), 53 46 ); ··· 99 92 ); 100 93 } 101 94 } 102 - 103 - class _AppBarAvatar extends StatelessWidget { 104 - const _AppBarAvatar(); 105 - 106 - @override 107 - Widget build(BuildContext context) { 108 - final theme = Theme.of(context); 109 - AuthState? authState; 110 - try { 111 - authState = context.watch<AuthBloc>().state; 112 - } catch (_) { 113 - log.d('showing default avatar'); 114 - } 115 - final tokens = authState?.tokens; 116 - final initials = _initialsFor(tokens?.displayName ?? tokens?.handle ?? 'L'); 117 - 118 - return Container( 119 - width: 32, 120 - height: 32, 121 - decoration: BoxDecoration( 122 - color: theme.colorScheme.surfaceContainerHigh, 123 - border: Border.all(color: theme.colorScheme.outlineVariant), 124 - ), 125 - child: Center( 126 - child: Text(initials, style: theme.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.w600)), 127 - ), 128 - ); 129 - } 130 - 131 - String _initialsFor(String value) { 132 - final parts = value.trim().split(RegExp(r'\s+')).where((p) => p.isNotEmpty).take(2).toList(); 133 - if (parts.isEmpty) return 'L'; 134 - return parts.map((p) => p[0].toUpperCase()).join(); 135 - } 136 - }
+1 -1
lib/features/devtools/presentation/dev_tools_screen.dart
··· 569 569 children: [ 570 570 TextButton.icon( 571 571 icon: const Icon(Icons.copy, size: 16), 572 - label: const Text('Copy'), 572 + label: const Text('Copy JSON'), 573 573 onPressed: () { 574 574 Clipboard.setData(ClipboardData(text: jsonString)); 575 575 ScaffoldMessenger.of(context).showSnackBar(
+1 -1
lib/features/settings/bloc/settings_cubit.dart
··· 16 16 String? initialConstellationUrl, 17 17 }) : super( 18 18 SettingsState( 19 - themePalette: initialPalette ?? AppThemePalette.oxocarbon, 19 + themePalette: initialPalette ?? AppThemePalette.lazurite, 20 20 themeVariant: initialVariant ?? AppThemeVariant.dark, 21 21 useSystemTheme: initialUseSystemTheme ?? false, 22 22 feedLayout: initialFeedLayout ?? FeedLayout.card,
+2 -2
lib/features/settings/presentation/settings_screen.dart
··· 302 302 ), 303 303 child: _SettingsTile( 304 304 icon: Icons.cloud_off_outlined, 305 - title: 'Simulate Offline', 306 - subtitle: 'Force offline UI for testing network resilience', 305 + title: 'Go Offline', 306 + subtitle: 'Turn off online connectivity', 307 307 trailing: Switch.adaptive(value: state.simulateOffline, onChanged: settingsCubit.setSimulateOffline), 308 308 ), 309 309 );
+4 -5
lib/main.dart
··· 237 237 ListRepository(bluesky: bluesky, moderationService: context.read<ModerationService>()), 238 238 ), 239 239 RepositoryProvider( 240 - create: (context) => ProfileRepository( 241 - database: widget.database, 242 - bluesky: bluesky, 243 - moderationService: context.read<ModerationService>(), 244 - ), 240 + create: (context) { 241 + final service = context.read<ModerationService>(); 242 + return ProfileRepository(database: widget.database, bluesky: bluesky, moderationService: service); 243 + }, 245 244 ), 246 245 RepositoryProvider( 247 246 create: (context) =>
+2 -2
pubspec.lock
··· 564 564 dependency: "direct main" 565 565 description: 566 566 name: google_fonts 567 - sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 567 + sha256: db9df7a5898d894eeda4c78143f35c30a243558be439518972366880b80bf88e 568 568 url: "https://pub.dev" 569 569 source: hosted 570 - version: "6.3.3" 570 + version: "8.0.2" 571 571 graphs: 572 572 dependency: transitive 573 573 description:
+1 -1
pubspec.yaml
··· 27 27 crypto: ^3.0.6 28 28 url_launcher: ^6.3.1 29 29 intl: ^0.19.0 30 - google_fonts: ^6.2.1 30 + google_fonts: ^8.0.2 31 31 logger: ^2.6.2 32 32 share_plus: ^10.1.4 33 33 http: ^1.2.2
+16 -4
test/core/theme/app_theme_test.dart
··· 4 4 void main() { 5 5 group('AppTheme', () { 6 6 group('getPaletteName', () { 7 + test('returns correct name for lazurite', () { 8 + expect(AppTheme.getPaletteName(AppThemePalette.lazurite), 'Lazurite'); 9 + }); 10 + 7 11 test('returns correct name for oxocarbon', () { 8 12 expect(AppTheme.getPaletteName(AppThemePalette.oxocarbon), 'Oxocarbon'); 9 13 }); ··· 32 36 }); 33 37 34 38 group('parsePalette', () { 39 + test('parses lazurite', () { 40 + expect(AppTheme.parsePalette('lazurite'), AppThemePalette.lazurite); 41 + }); 42 + 35 43 test('parses oxocarbon', () { 36 44 expect(AppTheme.parsePalette('oxocarbon'), AppThemePalette.oxocarbon); 37 45 }); ··· 48 56 expect(AppTheme.parsePalette('rosePine'), AppThemePalette.rosePine); 49 57 }); 50 58 51 - test('returns oxocarbon for null', () { 52 - expect(AppTheme.parsePalette(null), AppThemePalette.oxocarbon); 59 + test('returns lazurite for null', () { 60 + expect(AppTheme.parsePalette(null), AppThemePalette.lazurite); 53 61 }); 54 62 55 - test('returns oxocarbon for unknown value', () { 56 - expect(AppTheme.parsePalette('unknown'), AppThemePalette.oxocarbon); 63 + test('returns lazurite for unknown value', () { 64 + expect(AppTheme.parsePalette('unknown'), AppThemePalette.lazurite); 57 65 }); 58 66 }); 59 67 60 68 group('paletteToString', () { 69 + test('converts lazurite to string', () { 70 + expect(AppTheme.paletteToString(AppThemePalette.lazurite), 'lazurite'); 71 + }); 72 + 61 73 test('converts oxocarbon to string', () { 62 74 expect(AppTheme.paletteToString(AppThemePalette.oxocarbon), 'oxocarbon'); 63 75 });
+85
test/core/theme/lazurite_theme_test.dart
··· 1 + import 'package:flutter/material.dart'; 2 + import 'package:flutter_test/flutter_test.dart'; 3 + import 'package:lazurite/core/theme/lazurite_theme.dart'; 4 + 5 + void main() { 6 + group('LazuriteTheme', () { 7 + group('Dark color values', () { 8 + test('matches expected palette tokens', () { 9 + expect(LazuriteTheme.darkPrimary, const Color(0xFF7dafff)); 10 + expect(LazuriteTheme.darkOnPrimary, const Color(0xFF05080f)); 11 + expect(LazuriteTheme.darkPrimaryContainer, const Color(0xFF0073de)); 12 + expect(LazuriteTheme.darkOnPrimaryContainer, const Color(0xFFf4f6fb)); 13 + expect(LazuriteTheme.darkSurface, const Color(0xFF0e0e0e)); 14 + expect(LazuriteTheme.darkOnSurface, const Color(0xFFf4f6fb)); 15 + expect(LazuriteTheme.darkSurfaceVariant, const Color(0xFF191919)); 16 + expect(LazuriteTheme.darkOnSurfaceVariant, const Color(0xFFababab)); 17 + expect(LazuriteTheme.darkSurfaceContainerLowest, const Color(0xFF000000)); 18 + expect(LazuriteTheme.darkSurfaceContainer, const Color(0xFF191919)); 19 + expect(LazuriteTheme.darkSurfaceContainerHigh, const Color(0xFF1f1f1f)); 20 + expect(LazuriteTheme.darkSurfaceContainerHighest, const Color(0xF5242424)); 21 + expect(LazuriteTheme.darkSurfaceBright, const Color(0x0Dffffff)); 22 + expect(LazuriteTheme.darkOutline, const Color(0x33ffffff)); 23 + expect(LazuriteTheme.darkOutlineVariant, const Color(0x1Affffff)); 24 + expect(LazuriteTheme.darkError, const Color(0xFFff8080)); 25 + expect(LazuriteTheme.darkErrorContainer, const Color(0xB88a1f1f)); 26 + }); 27 + }); 28 + 29 + group('Light color values', () { 30 + test('matches expected palette tokens', () { 31 + expect(LazuriteTheme.lightPrimary, const Color(0xFF0b63d1)); 32 + expect(LazuriteTheme.lightOnPrimary, const Color(0xFFffffff)); 33 + expect(LazuriteTheme.lightPrimaryContainer, const Color(0xFF0953af)); 34 + expect(LazuriteTheme.lightOnPrimaryContainer, const Color(0xFFffffff)); 35 + expect(LazuriteTheme.lightSurface, const Color(0xFFffffff)); 36 + expect(LazuriteTheme.lightOnSurface, const Color(0xFF101418)); 37 + expect(LazuriteTheme.lightSurfaceVariant, const Color(0xFFf4f6f9)); 38 + expect(LazuriteTheme.lightOnSurfaceVariant, const Color(0xFF45505e)); 39 + expect(LazuriteTheme.lightSurfaceContainerLowest, const Color(0xFFeef1f5)); 40 + expect(LazuriteTheme.lightSurfaceContainer, const Color(0xFFf4f6f9)); 41 + expect(LazuriteTheme.lightSurfaceContainerHigh, const Color(0xFFeceff4)); 42 + expect(LazuriteTheme.lightSurfaceContainerHighest, const Color(0xF5f6f8fc)); 43 + expect(LazuriteTheme.lightSurfaceBright, const Color(0x0F111827)); 44 + expect(LazuriteTheme.lightOutline, const Color(0x3D111827)); 45 + expect(LazuriteTheme.lightOutlineVariant, const Color(0x24111827)); 46 + expect(LazuriteTheme.lightError, const Color(0xFFb42318)); 47 + expect(LazuriteTheme.lightErrorContainer, const Color(0xF2fee2e2)); 48 + }); 49 + }); 50 + 51 + group('ThemeData', () { 52 + testWidgets('dark theme maps key color scheme roles', (tester) async { 53 + final theme = LazuriteTheme.dark(); 54 + final scheme = theme.colorScheme; 55 + 56 + expect(theme.brightness, Brightness.dark); 57 + expect(scheme.primary, LazuriteTheme.darkPrimary); 58 + expect(scheme.onPrimary, LazuriteTheme.darkOnPrimary); 59 + expect(scheme.primaryContainer, LazuriteTheme.darkPrimaryContainer); 60 + expect(scheme.surfaceContainerLowest, LazuriteTheme.darkSurfaceContainerLowest); 61 + expect(scheme.surfaceContainerHigh, LazuriteTheme.darkSurfaceContainerHigh); 62 + expect(scheme.surfaceContainerHighest, LazuriteTheme.darkSurfaceContainerHighest); 63 + expect(scheme.onSurfaceVariant, LazuriteTheme.darkOnSurfaceVariant); 64 + expect(scheme.outlineVariant, LazuriteTheme.darkOutlineVariant); 65 + expect(scheme.errorContainer, LazuriteTheme.darkErrorContainer); 66 + }); 67 + 68 + testWidgets('light theme maps key color scheme roles', (tester) async { 69 + final theme = LazuriteTheme.light(); 70 + final scheme = theme.colorScheme; 71 + 72 + expect(theme.brightness, Brightness.light); 73 + expect(scheme.primary, LazuriteTheme.lightPrimary); 74 + expect(scheme.onPrimary, LazuriteTheme.lightOnPrimary); 75 + expect(scheme.primaryContainer, LazuriteTheme.lightPrimaryContainer); 76 + expect(scheme.surfaceContainerLowest, LazuriteTheme.lightSurfaceContainerLowest); 77 + expect(scheme.surfaceContainerHigh, LazuriteTheme.lightSurfaceContainerHigh); 78 + expect(scheme.surfaceContainerHighest, LazuriteTheme.lightSurfaceContainerHighest); 79 + expect(scheme.onSurfaceVariant, LazuriteTheme.lightOnSurfaceVariant); 80 + expect(scheme.outlineVariant, LazuriteTheme.lightOutlineVariant); 81 + expect(scheme.errorContainer, LazuriteTheme.lightErrorContainer); 82 + }); 83 + }); 84 + }); 85 + }
+3 -41
test/core/widgets/lazurite_app_bar_test.dart
··· 6 6 import 'package:lazurite/core/theme/app_theme.dart'; 7 7 import 'package:lazurite/core/widgets/lazurite_app_bar.dart'; 8 8 import 'package:lazurite/features/auth/bloc/auth_bloc.dart'; 9 - import 'package:lazurite/features/connectivity/cubit/connectivity_cubit.dart'; 10 9 import 'package:lazurite/features/auth/data/models/auth_models.dart'; 10 + import 'package:lazurite/features/connectivity/cubit/connectivity_cubit.dart'; 11 11 import 'package:lazurite/features/settings/bloc/settings_cubit.dart'; 12 12 import 'package:lazurite/features/settings/bloc/settings_state.dart'; 13 13 import 'package:mocktail/mocktail.dart'; ··· 62 62 when(() => settingsCubit.setSimulateOffline(any())).thenAnswer((_) async {}); 63 63 }); 64 64 65 - Widget buildSubject({ 66 - required String sectionLabel, 67 - PreferredSizeWidget? bottom, 68 - List<Widget>? actions, 69 - bool showAvatar = true, 70 - }) { 65 + Widget buildSubject({required String sectionLabel, PreferredSizeWidget? bottom, List<Widget>? actions}) { 71 66 return MultiBlocProvider( 72 67 providers: [ 73 68 BlocProvider<AuthBloc>.value(value: authBloc), ··· 76 71 ], 77 72 child: MaterialApp( 78 73 home: Scaffold( 79 - appBar: LazuriteAppBar(sectionLabel: sectionLabel, bottom: bottom, actions: actions, showAvatar: showAvatar), 74 + appBar: LazuriteAppBar(sectionLabel: sectionLabel, bottom: bottom, actions: actions), 80 75 body: const SizedBox.shrink(), 81 76 ), 82 77 ), ··· 95 90 expect(find.byType(AppShellMenuButton), findsOneWidget); 96 91 }); 97 92 98 - testWidgets('renders user initials in avatar from displayName', (tester) async { 99 - await tester.pumpWidget(buildSubject(sectionLabel: 'Home')); 100 - await tester.pumpAndSettle(); 101 - expect(find.text('RT'), findsOneWidget); 102 - }); 103 - 104 93 testWidgets('renders initials from handle when displayName is absent', (tester) async { 105 94 authBloc = MockAuthBloc(); 106 95 const noDisplayName = AuthTokens( ··· 116 105 await tester.pumpWidget(buildSubject(sectionLabel: 'Home')); 117 106 await tester.pumpAndSettle(); 118 107 expect(find.text('A'), findsOneWidget); 119 - }); 120 - 121 - testWidgets('renders additional actions alongside avatar', (tester) async { 122 - await tester.pumpWidget( 123 - buildSubject( 124 - sectionLabel: 'Alerts', 125 - actions: [TextButton(onPressed: () {}, child: const Text('Mark All Read'))], 126 - ), 127 - ); 128 - await tester.pumpAndSettle(); 129 - 130 - expect(find.text('Mark All Read'), findsOneWidget); 131 - expect(find.text('ALERTS'), findsOneWidget); 132 - }); 133 - 134 - testWidgets('can hide avatar when custom trailing actions are used', (tester) async { 135 - await tester.pumpWidget( 136 - buildSubject( 137 - sectionLabel: 'Home', 138 - showAvatar: false, 139 - actions: [IconButton(onPressed: () {}, icon: const Icon(Icons.rss_feed))], 140 - ), 141 - ); 142 - await tester.pumpAndSettle(); 143 - 144 - expect(find.byIcon(Icons.rss_feed), findsOneWidget); 145 - expect(find.text('RT'), findsNothing); 146 108 }); 147 109 148 110 testWidgets('shows simulated offline indicator and lets the user disable it', (tester) async {
+2 -2
test/features/settings/bloc/settings_cubit_test.dart
··· 21 21 group('SettingsCubit', () { 22 22 test('initial state has default values', () { 23 23 final cubit = SettingsCubit(database: database); 24 - expect(cubit.state.themePalette, AppThemePalette.oxocarbon); 24 + expect(cubit.state.themePalette, AppThemePalette.lazurite); 25 25 expect(cubit.state.themeVariant, AppThemeVariant.dark); 26 26 expect(cubit.state.useSystemTheme, false); 27 27 expect(cubit.state.feedLayout, FeedLayout.card); ··· 76 76 act: (cubit) => cubit.loadSettings(), 77 77 expect: () => [ 78 78 isA<SettingsState>() 79 - .having((s) => s.themePalette, 'themePalette', AppThemePalette.oxocarbon) 79 + .having((s) => s.themePalette, 'themePalette', AppThemePalette.lazurite) 80 80 .having((s) => s.themeVariant, 'themeVariant', AppThemeVariant.dark) 81 81 .having((s) => s.useSystemTheme, 'useSystemTheme', false) 82 82 .having((s) => s.feedLayout, 'feedLayout', FeedLayout.card)