2023-10-02 23:25:37 +00:00
import ' dart:io ' ;
2021-12-07 01:40:10 +00:00
import ' dart:core ' ;
2021-12-10 04:22:55 +00:00
import ' package:cwtch/themes/cwtch.dart ' ;
2023-10-19 15:29:05 +00:00
import ' package:cwtch/themes/yamltheme.dart ' ;
2021-12-07 01:40:10 +00:00
import ' package:flutter/material.dart ' ;
import ' package:cwtch/settings.dart ' ;
2022-01-04 20:52:43 +00:00
import ' package:flutter/services.dart ' ;
2024-02-02 07:48:20 +00:00
import ' package:path/path.dart ' as path ;
const custom_themes_subdir = " themes " ;
2021-12-07 01:40:10 +00:00
2021-12-09 05:40:40 +00:00
const mode_light = " light " ;
const mode_dark = " dark " ;
2023-05-18 18:15:13 +00:00
final TextStyle defaultSmallTextStyle = TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . normal , fontSize: 10 ) ;
2023-10-02 23:25:37 +00:00
final TextStyle defaultMessageTextStyle = TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . w400 , fontSize: 13 , fontFamilyFallback: [ Platform . isWindows ? ' Segoe UI Emoji ' : " Noto Color Emoji " ] ) ;
2023-05-18 18:15:13 +00:00
final TextStyle defaultFormLabelTextStyle = TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , fontSize: 20 ) ;
final TextStyle defaultTextStyle = TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . w500 , fontSize: 12 ) ;
final TextStyle defaultTextButtonStyle = defaultTextStyle . copyWith ( fontWeight: FontWeight . bold ) ;
2023-05-18 19:05:14 +00:00
final TextStyle defaultDropDownMenuItemTextStyle = TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , fontSize: 16 ) ;
2023-05-18 18:15:13 +00:00
2024-02-14 01:00:47 +00:00
class ThemeLoader extends ChangeNotifier {
Map < String , Map < String , OpaqueThemeType > > themes = Map ( ) ;
2023-10-19 15:29:05 +00:00
2024-02-14 01:00:47 +00:00
LoadThemes ( String cwtchDir ) async {
2024-02-14 04:02:33 +00:00
themes . clear ( ) ; // clear themes...
loadBuiltinThemes ( ) . then ( ( builtinThemes ) {
themes . addAll ( builtinThemes ) ;
2024-02-14 01:00:47 +00:00
notifyListeners ( ) ;
loadCustomThemes ( path . join ( cwtchDir , custom_themes_subdir ) ) . then ( ( customThemes ) {
themes . addAll ( customThemes ) ;
notifyListeners ( ) ;
} ) ;
} ) ;
2021-12-07 01:40:10 +00:00
}
2024-02-14 01:00:47 +00:00
OpaqueThemeType getTheme ( String ? themeId , String ? mode ) {
if ( themeId = = null ) {
themeId = cwtch_theme ;
}
if ( themeId = = mode_light ) {
mode = mode_light ;
}
if ( themeId = = mode_dark ) {
mode = mode_dark ;
}
var theme = themes [ themeId ] ? [ mode ] ? ? themes [ themeId ] ? [ flipMode ( mode ? ? mode_dark ) ] ;
return theme ? ? CwtchDark ( ) ;
}
2021-12-09 05:40:40 +00:00
2024-02-14 01:00:47 +00:00
String flipMode ( String mode ) {
if ( mode = = mode_dark ) {
return mode_light ;
}
return mode_dark ;
2023-10-19 15:29:05 +00:00
}
}
2021-12-10 04:22:55 +00:00
Color lighten ( Color color , [ double amount = 0.15 ] ) {
final hsl = HSLColor . fromColor ( color ) ;
final hslLight = hsl . withLightness ( ( hsl . lightness + amount ) . clamp ( 0.0 , 1.0 ) ) ;
2021-12-07 01:40:10 +00:00
2021-12-10 04:22:55 +00:00
return hslLight . toColor ( ) ;
}
2021-12-07 01:40:10 +00:00
2021-12-10 04:22:55 +00:00
Color darken ( Color color , [ double amount = 0.15 ] ) {
final hsl = HSLColor . fromColor ( color ) ;
final hslDarken = hsl . withLightness ( ( hsl . lightness - amount ) . clamp ( 0.0 , 1.0 ) ) ;
2021-12-07 01:40:10 +00:00
2021-12-10 04:22:55 +00:00
return hslDarken . toColor ( ) ;
}
2021-12-07 01:40:10 +00:00
2021-12-10 04:22:55 +00:00
abstract class OpaqueThemeType {
static final Color red = Color ( 0xFFFF0000 ) ;
2021-12-07 01:40:10 +00:00
2021-12-10 04:22:55 +00:00
get theme = > " dummy " ;
get mode = > mode_light ;
2021-12-07 01:40:10 +00:00
2021-12-10 04:22:55 +00:00
// Main screen background color (message pane, item rows)
get backgroundMainColor = > red ;
2021-12-07 01:40:10 +00:00
2021-12-21 05:07:16 +00:00
// pane colors (settings)
2021-12-10 04:22:55 +00:00
get backgroundPaneColor = > red ;
2021-12-07 01:40:10 +00:00
2021-12-21 05:07:16 +00:00
get topbarColor = > red ;
2021-12-10 04:22:55 +00:00
get mainTextColor = > red ;
2021-12-07 01:40:10 +00:00
2021-12-10 04:22:55 +00:00
// pressed row, offline heart
get hilightElementColor = > red ;
// Selected Row
get backgroundHilightElementColor = > red ;
// Faded text color for suggestions in textfields
// Todo: implement way more places
get sendHintTextColor = > red ;
get defaultButtonColor = > red ;
2021-12-11 05:07:47 +00:00
get defaultButtonActiveColor = > /*mode == mode_light ? darken(defaultButtonColor) :*/ lighten ( defaultButtonColor ) ;
2021-12-10 04:22:55 +00:00
get defaultButtonTextColor = > red ;
get defaultButtonDisabledColor = > red ;
get textfieldBackgroundColor = > red ;
get textfieldBorderColor = > red ;
get textfieldHintColor = > red ;
get textfieldErrorColor = > red ;
2024-02-07 16:16:33 +00:00
get textfieldSelectionColor = > red ;
2021-12-10 04:22:55 +00:00
get scrollbarDefaultColor = > red ;
get portraitBackgroundColor = > red ;
get portraitOnlineBorderColor = > red ;
get portraitOfflineBorderColor = > red ;
get portraitBlockedBorderColor = > red ;
get portraitBlockedTextColor = > red ;
get portraitContactBadgeColor = > red ;
get portraitContactBadgeTextColor = > red ;
get portraitProfileBadgeColor = > red ;
get portraitProfileBadgeTextColor = > red ;
2021-12-07 01:40:10 +00:00
2023-04-04 20:58:42 +00:00
get portraitOnlineAwayColor = > Color ( 0xFFFFF59D ) ;
get portraitOnlineBusyColor = > Color ( 0xFFEF9A9A ) ;
2021-12-09 05:40:40 +00:00
// dropshaddpow
// todo: probably should not be reply icon color in messagerow
2021-12-10 04:22:55 +00:00
get dropShadowColor = > red ;
2021-12-07 01:40:10 +00:00
2021-12-10 04:22:55 +00:00
get toolbarIconColor = > red ;
2024-01-04 02:30:35 +00:00
get chatReactionIconColor = > red ;
2021-12-10 04:22:55 +00:00
get messageFromMeBackgroundColor = > red ;
get messageFromMeTextColor = > red ;
get messageFromOtherBackgroundColor = > red ;
get messageFromOtherTextColor = > red ;
2024-02-07 16:16:33 +00:00
get messageSelectionColor = > red ;
get menuBackgroundColor = > red ;
2021-12-07 01:40:10 +00:00
2024-02-02 07:48:20 +00:00
get snackbarBackgroundColor = > red ;
get snackbarTextColor = > red ;
2023-12-10 18:38:04 +00:00
// Images
2024-01-10 05:57:12 +00:00
get chatImageColor = > red ;
2023-12-10 18:38:04 +00:00
get chatImage = > null ;
2024-02-03 02:08:21 +00:00
ImageProvider loadImage ( String key , { BuildContext ? context } ) {
return AssetImage ( " " ) ;
}
2024-01-04 02:30:35 +00:00
2021-12-07 01:40:10 +00:00
// Sizes
double contactOnionTextSize ( ) {
return 18 ;
}
}
2024-02-07 16:16:33 +00:00
// Borrowed from Stackoverflow
MaterialColor getMaterialColor ( Color color ) {
final int red = color . red ;
final int green = color . green ;
final int blue = color . blue ;
final Map < int , Color > shades = {
50 : Color . fromRGBO ( red , green , blue , . 1 ) ,
100 : Color . fromRGBO ( red , green , blue , . 2 ) ,
200 : Color . fromRGBO ( red , green , blue , . 3 ) ,
300 : Color . fromRGBO ( red , green , blue , . 4 ) ,
400 : Color . fromRGBO ( red , green , blue , . 5 ) ,
500 : Color . fromRGBO ( red , green , blue , . 6 ) ,
600 : Color . fromRGBO ( red , green , blue , . 7 ) ,
700 : Color . fromRGBO ( red , green , blue , . 8 ) ,
800 : Color . fromRGBO ( red , green , blue , . 9 ) ,
900 : Color . fromRGBO ( red , green , blue , 1 ) ,
} ;
return MaterialColor ( color . value , shades ) ;
}
2021-12-07 01:40:10 +00:00
ThemeData mkThemeData ( Settings opaque ) {
return ThemeData (
2024-02-03 02:08:21 +00:00
hoverColor: opaque . current ( ) . backgroundHilightElementColor . withOpacity ( 0.5 ) ,
visualDensity: VisualDensity . adaptivePlatformDensity ,
primaryIconTheme: IconThemeData (
color: opaque . current ( ) . mainTextColor ,
) ,
primaryColor: opaque . current ( ) . mainTextColor ,
canvasColor: opaque . current ( ) . backgroundMainColor ,
highlightColor: opaque . current ( ) . hilightElementColor ,
iconTheme: IconThemeData (
color: opaque . current ( ) . toolbarIconColor ,
) ,
cardColor: opaque . current ( ) . backgroundMainColor ,
appBarTheme: AppBarTheme (
systemOverlayStyle: SystemUiOverlayStyle (
// Status bar color
statusBarColor: opaque . current ( ) . topbarColor ,
// Status bar brightness (optional)
statusBarIconBrightness: opaque . current ( ) . mode = = mode_light ? Brightness . dark : Brightness . light , // For Android (dark icons)
statusBarBrightness: opaque . current ( ) . mode = = mode_light ? Brightness . dark : Brightness . light , // For iOS (dark icons)
) ,
backgroundColor: opaque . current ( ) . topbarColor ,
iconTheme: IconThemeData (
color: opaque . current ( ) . mainTextColor ,
) ,
titleTextStyle: TextStyle ( fontWeight: FontWeight . bold , fontFamily: " Inter " , color: opaque . current ( ) . mainTextColor , fontSize: opaque . fontScaling * 18.0 ) ,
actionsIconTheme: IconThemeData (
color: opaque . current ( ) . mainTextColor ,
) ) ,
//bottomNavigationBarTheme: BottomNavigationBarThemeData(type: BottomNavigationBarType.fixed, backgroundColor: opaque.current().backgroundHilightElementColor), // Can't determine current use
textButtonTheme: TextButtonThemeData (
style: ButtonStyle (
backgroundColor: MaterialStateProperty . all ( opaque . current ( ) . defaultButtonColor ) ,
foregroundColor: MaterialStateProperty . all ( opaque . current ( ) . defaultButtonTextColor ) ,
overlayColor: MaterialStateProperty . all ( opaque . current ( ) . defaultButtonActiveColor ) ,
padding: MaterialStateProperty . all ( EdgeInsets . all ( 20 ) ) ) ,
) ,
hintColor: opaque . current ( ) . textfieldHintColor ,
elevatedButtonTheme: ElevatedButtonThemeData (
style: ButtonStyle (
backgroundColor: MaterialStateProperty . resolveWith ( ( states ) = > states . contains ( MaterialState . disabled ) ? opaque . current ( ) . defaultButtonDisabledColor : opaque . current ( ) . defaultButtonColor ) ,
2021-12-10 04:22:55 +00:00
foregroundColor: MaterialStateProperty . all ( opaque . current ( ) . defaultButtonTextColor ) ,
2024-02-03 02:08:21 +00:00
overlayColor: MaterialStateProperty . resolveWith ( ( states ) = > ( states . contains ( MaterialState . pressed ) & & states . contains ( MaterialState . hovered ) )
? opaque . current ( ) . defaultButtonActiveColor
: states . contains ( MaterialState . disabled )
? opaque . current ( ) . defaultButtonDisabledColor
: null ) ,
enableFeedback: true ,
textStyle: MaterialStateProperty . all ( opaque . scaleFonts ( defaultTextButtonStyle ) ) ,
padding: MaterialStateProperty . all ( EdgeInsets . all ( 20 ) ) ,
shape: MaterialStateProperty . all ( RoundedRectangleBorder (
borderRadius: BorderRadius . circular ( 6.0 ) ,
) ) ,
) ,
2021-12-07 01:40:10 +00:00
) ,
2024-02-03 02:08:21 +00:00
scrollbarTheme: ScrollbarThemeData ( thumbVisibility: MaterialStateProperty . all ( false ) , thumbColor: MaterialStateProperty . all ( opaque . current ( ) . scrollbarDefaultColor ) ) ,
tabBarTheme: TabBarTheme (
labelColor: opaque . current ( ) . mainTextColor ,
unselectedLabelColor: opaque . current ( ) . mainTextColor ,
indicator: UnderlineTabIndicator ( borderSide: BorderSide ( color: opaque . current ( ) . defaultButtonActiveColor ) ) ,
labelStyle: opaque . scaleFonts ( defaultTextButtonStyle ) ,
unselectedLabelStyle: opaque . scaleFonts ( defaultTextStyle ) ,
) ,
dialogTheme: DialogTheme (
backgroundColor: opaque . current ( ) . backgroundPaneColor ,
titleTextStyle: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , color: opaque . current ( ) . mainTextColor ) ,
contentTextStyle: TextStyle (
fontFamily: " Inter " ,
color: opaque . current ( ) . mainTextColor ,
) ) ,
textTheme: TextTheme (
// NOTE: The following font scales were arrived at after consulting the material text scale
// docs: https://m3.material.io/styles/typography/type-scale-tokens and some trial and error
displaySmall: TextStyle ( fontFamily: " Inter " , fontSize: opaque . fontScaling * 14.0 , color: opaque . current ( ) . mainTextColor ) ,
displayMedium: TextStyle ( fontFamily: " Inter " , fontSize: opaque . fontScaling * 16.0 , color: opaque . current ( ) . mainTextColor ) ,
displayLarge: TextStyle ( fontFamily: " Inter " , fontSize: opaque . fontScaling * 18.0 , color: opaque . current ( ) . mainTextColor ) ,
titleSmall: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , fontSize: opaque . fontScaling * 16.0 , color: opaque . current ( ) . mainTextColor ) ,
titleLarge: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , fontSize: opaque . fontScaling * 18.0 , color: opaque . current ( ) . mainTextColor ) ,
titleMedium: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , fontSize: opaque . fontScaling * 20.0 , color: opaque . current ( ) . mainTextColor ) ,
bodySmall: TextStyle ( fontFamily: " Inter " , fontSize: opaque . fontScaling * 12.0 , color: opaque . current ( ) . mainTextColor ) ,
bodyMedium: TextStyle ( fontFamily: " Inter " , fontSize: opaque . fontScaling * 14.0 , color: opaque . current ( ) . mainTextColor ) ,
bodyLarge: TextStyle ( fontFamily: " Inter " , fontSize: opaque . fontScaling * 16.0 , color: opaque . current ( ) . mainTextColor ) ,
headlineSmall: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , fontSize: opaque . fontScaling * 24.0 , color: opaque . current ( ) . mainTextColor ) ,
headlineMedium: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , fontSize: opaque . fontScaling * 26.0 , color: opaque . current ( ) . mainTextColor ) ,
headlineLarge: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . bold , fontSize: opaque . fontScaling * 28.0 , color: opaque . current ( ) . mainTextColor ) ,
labelSmall: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . w100 , fontSize: opaque . fontScaling * 14.0 , color: opaque . current ( ) . mainTextColor ) ,
labelMedium: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . w300 , fontSize: opaque . fontScaling * 16.0 , color: opaque . current ( ) . mainTextColor ) ,
labelLarge: TextStyle ( fontFamily: " Inter " , fontWeight: FontWeight . w200 , fontSize: opaque . fontScaling * 18.0 , color: opaque . current ( ) . mainTextColor ) ,
) ,
switchTheme: SwitchThemeData (
overlayColor: MaterialStateProperty . all ( opaque . current ( ) . defaultButtonActiveColor ) ,
thumbColor: MaterialStateProperty . all ( opaque . current ( ) . mainTextColor ) ,
trackColor: MaterialStateProperty . all ( opaque . current ( ) . dropShadowColor ) ,
) ,
// the only way to change the text Selection Context Menu Color ?!
brightness: opaque . current ( ) . mode = = mode_dark ? Brightness . dark : Brightness . light ,
floatingActionButtonTheme: FloatingActionButtonThemeData (
foregroundColor: opaque . current ( ) . mainTextColor ,
backgroundColor: opaque . current ( ) . defaultButtonColor ,
hoverColor: opaque . current ( ) . defaultButtonActiveColor ,
enableFeedback: true ,
splashColor: opaque . current ( ) . defaultButtonActiveColor ) ,
textSelectionTheme: TextSelectionThemeData (
2024-02-07 16:16:33 +00:00
cursorColor: opaque . current ( ) . textfieldSelectionColor , selectionColor: opaque . current ( ) . textfieldSelectionColor , selectionHandleColor: opaque . current ( ) . textfieldSelectionColor ) ,
2024-02-03 02:08:21 +00:00
popupMenuTheme: PopupMenuThemeData (
color: opaque . current ( ) . backgroundPaneColor . withOpacity ( 0.9 ) ,
) ,
snackBarTheme: SnackBarThemeData (
backgroundColor: opaque . current ( ) . snackbarBackgroundColor ,
contentTextStyle: TextStyle ( color: opaque . current ( ) . snackbarTextColor ) ,
2024-02-14 04:29:14 +00:00
) ) ;
2021-12-07 01:40:10 +00:00
}