From a88ccf31b59541faea8c38c638737c1359cfff47 Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Sat, 27 May 2023 13:14:45 -0600 Subject: Se implementan colores dinámicos (Android 13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 42 +++++--- lib/providers/theme_provider.dart | 7 +- lib/screens/chat_screen.dart | 8 +- lib/screens/dashboard_screen.dart | 39 ++++--- lib/settings/preferences.dart | 15 ++- lib/settings/themes.dart | 28 ++--- lib/widgets/chat_bubble.dart | 148 +++++++++++++++++---------- linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + pubspec.lock | 10 +- pubspec.yaml | 1 + 11 files changed, 191 insertions(+), 112 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 97a8fb4..b067b07 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:dynamic_color/dynamic_color.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:linkchat/screens/dashboard_screen.dart'; @@ -50,20 +51,35 @@ class LinkChat extends StatelessWidget { @override Widget build(BuildContext context) { final ThemeProvider provider = context.watch(); - final ThemeData? theme = provider.theme; - provider.syncFromPrefs(); + final ThemeEnum themeEnum = provider.theme; + return StreamBuilder( stream: _auth.userChanges, - builder: (context, snapshot) { - return MaterialApp( - theme: theme ?? ThemeSettings.lightTheme, - darkTheme: theme ?? ThemeSettings.darkTheme, - themeMode: ThemeMode.system, - routes: getApplicationRoutes(), - home: (snapshot.hasData && !snapshot.data!.isAnonymous) - ? const DashboardScreen() - : const LoginScreen(), - ); - }); + builder: (context, snapshot) => + DynamicColorBuilder(builder: (lightDynamic, darkDynamic) { + provider.syncFromPrefs(); + ThemeData lightTheme = ThemeSettings.lightTheme(lightDynamic); + ThemeData darkTheme = ThemeSettings.darkTheme(darkDynamic); + ThemeData? theme; + switch (themeEnum) { + case ThemeEnum.light: + theme = lightTheme; + case ThemeEnum.dark: + theme = darkTheme; + case ThemeEnum.auto: + theme = null; + } + return MaterialApp( + theme: theme ?? lightTheme, + darkTheme: theme ?? darkTheme, + //theme: theme ?? ThemeSettings.lightTheme(lightDynamic), + //darkTheme: theme ?? ThemeSettings.darkTheme(darkDynamic), + themeMode: ThemeMode.system, + routes: getApplicationRoutes(), + home: (snapshot.hasData && !snapshot.data!.isAnonymous) + ? const DashboardScreen() + : const LoginScreen(), + ); + })); } } diff --git a/lib/providers/theme_provider.dart b/lib/providers/theme_provider.dart index 3a65731..240c9a7 100644 --- a/lib/providers/theme_provider.dart +++ b/lib/providers/theme_provider.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; import '../settings/preferences.dart'; +import '../settings/themes.dart'; class ThemeProvider with ChangeNotifier { bool synced = false; - ThemeData? _theme; + ThemeEnum _theme = ThemeEnum.auto; void syncFromPrefs() { if (synced) return; @@ -15,9 +16,9 @@ class ThemeProvider with ChangeNotifier { }); } - ThemeData? get theme => _theme; + ThemeEnum get theme => _theme; - set theme(ThemeData? theme) { + set theme(ThemeEnum theme) { Preferences.setTheme(theme); _theme = theme; notifyListeners(); diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 64f8621..b815a6a 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -1,4 +1,5 @@ import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:linkchat/firebase/auth.dart'; import 'package:linkchat/firebase/database.dart'; @@ -43,11 +44,6 @@ class _ChatScreenState extends State { leadingWidth: 30, title: Row( children: [ - // ClipRRect( - // borderRadius: BorderRadius.circular(30), - // child: CircleAvatar( - // backgroundImage: NetworkImage(user!.photoUrl), - // )), CachedAvatar(user?.photoUrl), Padding( padding: const EdgeInsets.only(left: 10), @@ -119,7 +115,7 @@ class _ChatScreenState extends State { }), ); } else if (snapshot.hasError) { - print('Error: ${snapshot.error}'); + if (kDebugMode) print('Error: ${snapshot.error}'); return const Center(child: Text('Hubo un error')); } return const Center(child: CircularProgressIndicator()); diff --git a/lib/screens/dashboard_screen.dart b/lib/screens/dashboard_screen.dart index 4905b84..be3aca0 100644 --- a/lib/screens/dashboard_screen.dart +++ b/lib/screens/dashboard_screen.dart @@ -51,29 +51,40 @@ class _DashboardScreenState extends State { children: [ UserAccountsDrawerHeader( currentAccountPicture: CachedAvatar(_auth.currentUser?.photoURL), - accountName: Text(_auth.currentUser?.displayName ?? "Lincite"), + accountName: Text( + _auth.currentUser?.displayName ?? "Lincite", + style: TextStyle( + color: Theme.of(context).colorScheme.onPrimary, + ), + ), accountEmail: _auth.currentUser?.email != null - ? Text(_auth.currentUser!.email!) + ? Text( + _auth.currentUser!.email!, + style: TextStyle( + color: Theme.of(context).colorScheme.onPrimary, + ), + ) : null, ), ListTile( title: const Text('Tema'), - trailing: SegmentedButton( - segments: [ - const ButtonSegment( - value: null, + trailing: SegmentedButton( + segments: const [ + ButtonSegment( + value: ThemeEnum.auto, icon: Icon(Icons.brightness_auto), ), - ButtonSegment( - value: ThemeSettings.lightTheme, - icon: const Icon(Icons.light_mode), + ButtonSegment( + value: ThemeEnum.light, + icon: Icon(Icons.light_mode), + ), + ButtonSegment( + value: ThemeEnum.dark, + icon: Icon(Icons.dark_mode), ), - ButtonSegment( - value: ThemeSettings.darkTheme, - icon: const Icon(Icons.dark_mode)), ], - selected: {themeProvider.theme}, - onSelectionChanged: ((Set newSelection) { + selected: {themeProvider.theme}, + onSelectionChanged: ((Set newSelection) { themeProvider.theme = newSelection.first; }), ), diff --git a/lib/settings/preferences.dart b/lib/settings/preferences.dart index 3c0ef5d..9cfbf6a 100644 --- a/lib/settings/preferences.dart +++ b/lib/settings/preferences.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../settings/themes.dart'; @@ -11,21 +10,21 @@ class Preferences { return _prefs!; } - static Future getTheme() async { + static Future getTheme() async { switch ((await prefs).getString('theme')) { case 'light': - return ThemeSettings.lightTheme; + return ThemeEnum.light; case 'dark': - return ThemeSettings.darkTheme; + return ThemeEnum.dark; } - return null; + return ThemeEnum.auto; } - static void setTheme(ThemeData? theme) { + static void setTheme(ThemeEnum? theme) { prefs.then((p) { - if (theme == ThemeSettings.lightTheme) { + if (theme == ThemeEnum.light) { p.setString('theme', 'light'); - } else if (theme == ThemeSettings.darkTheme) { + } else if (theme == ThemeEnum.dark) { p.setString('theme', 'dark'); } else { p.remove('theme'); diff --git a/lib/settings/themes.dart b/lib/settings/themes.dart index cc506a9..b9a09d7 100644 --- a/lib/settings/themes.dart +++ b/lib/settings/themes.dart @@ -1,18 +1,20 @@ import 'package:flutter/material.dart'; +enum ThemeEnum { light, dark, auto } + class ThemeSettings { - static ThemeData lightTheme = ThemeData( - useMaterial3: true, - primaryColor: Colors.purple, - fontFamily: 'Manrope', - ); + static ThemeData lightTheme(ColorScheme? lightDynamic) => ThemeData( + useMaterial3: true, + primaryColor: Colors.purple, + fontFamily: 'Manrope', + colorScheme: lightDynamic, + ); - static ThemeData darkTheme = ThemeData( - useMaterial3: true, - brightness: Brightness.dark, - fontFamily: 'Manrope', - colorScheme: const ColorScheme.dark().copyWith( - primary: Colors.purple, - ), - ); + static ThemeData darkTheme(ColorScheme? darkDynamic) => ThemeData( + useMaterial3: true, + brightness: Brightness.dark, + fontFamily: 'Manrope', + primaryColor: Colors.purple, + colorScheme: (darkDynamic ?? const ColorScheme.dark()), + ); } diff --git a/lib/widgets/chat_bubble.dart b/lib/widgets/chat_bubble.dart index e7622e4..091a039 100644 --- a/lib/widgets/chat_bubble.dart +++ b/lib/widgets/chat_bubble.dart @@ -56,38 +56,21 @@ class BubbleLeft extends StatelessWidget { @override Widget build(BuildContext context) { + Color background = Theme.of(context).colorScheme.tertiaryContainer; + Color foreground = Theme.of(context).colorScheme.onTertiaryContainer; return Padding( - padding: const EdgeInsets.only(right: 77), + padding: const EdgeInsets.only(top: 10, right: 77), child: ClipPath( clipper: UpperNipMessageClipper(MessageType.receive), child: Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Color(0xFFE1E1E2), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LinkPreview(message), - Link( - uri: Uri.parse(message.messageText), - builder: (context, followLink) => TextButton( - onPressed: followLink, - child: Text( - message.messageText, - style: const TextStyle(color: Colors.blue), - ), - ), - ), - IconButton( - icon: favorited - ? const Icon(Icons.favorite, color: Colors.black) - : const Icon(Icons.favorite_outline, color: Colors.black), - onPressed: () => onFavorite(message.id!, !favorited), - ), - ], - ), - ), + padding: const EdgeInsets.all(20), + decoration: BoxDecoration(color: background), + child: BubbleContent( + message, + favorited: favorited, + foregroundColor: foreground, + onFavorited: () => onFavorite(message.id!, !favorited), + )), ), ); } @@ -107,43 +90,100 @@ class BubbleRight extends StatelessWidget { @override Widget build(BuildContext context) { + Color background = Theme.of(context).colorScheme.primaryContainer; + Color foreground = Theme.of(context).colorScheme.onPrimaryContainer; return Container( alignment: Alignment.centerRight, child: Padding( - padding: const EdgeInsets.only(top: 20, left: 77), + padding: const EdgeInsets.only(top: 10, left: 77), child: ClipPath( clipper: LowerNipMessageClipper(MessageType.send), child: Container( - padding: - const EdgeInsets.only(left: 20, top: 10, bottom: 20, right: 20), - decoration: const BoxDecoration( - color: Color(0xFF113753), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LinkPreview(message), - Link( - uri: Uri.parse(message.messageText), - builder: (context, followLink) => TextButton( - onPressed: followLink, - child: Text( - message.messageText, - style: const TextStyle(color: Colors.blue), + padding: const EdgeInsets.only( + left: 20, top: 10, bottom: 20, right: 20), + decoration: BoxDecoration(color: background), + child: BubbleContent( + message, + favorited: favorited, + foregroundColor: foreground, + onFavorited: () => onFavorite(message.id!, !favorited), + )), + ), + ), + ); + } +} + +class BubbleContent extends StatelessWidget { + final bool favorited; + final Message message; + final Color foregroundColor; + final Function() onFavorited; + + const BubbleContent( + this.message, { + super.key, + required this.favorited, + required this.foregroundColor, + required this.onFavorited, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LinkPreview(message), + Row( + children: [ + Expanded( + child: Link( + uri: Uri.parse(message.messageText), + builder: (context, followLink) => TextButton( + onPressed: followLink, + child: Text( + message.messageText, + textAlign: TextAlign.start, + style: TextStyle( + color: foregroundColor, + decoration: TextDecoration.underline, + decorationColor: foregroundColor, ), ), ), - IconButton( - icon: favorited - ? const Icon(Icons.favorite, color: Colors.white) - : const Icon(Icons.favorite_outline, color: Colors.white), - onPressed: () => onFavorite(message.id!, !favorited), - ), - ], + ), + ), + Favorited( + favorited, + color: foregroundColor, + onPressed: () => onFavorited(), ), - ), + ], ), - ), + ], + ); + } +} + +class Favorited extends StatelessWidget { + final bool favorited; + final Color color; + final Function() onPressed; + + const Favorited( + this.favorited, { + super.key, + required this.color, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + return IconButton( + icon: favorited + ? Icon(Icons.favorite, color: color) + : Icon(Icons.favorite_outline, color: color), + onPressed: onPressed, ); } } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index f6f23bf..fe56f8d 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,9 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) dynamic_color_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); + dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index f16b4c3..1836621 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + dynamic_color url_launcher_linux ) diff --git a/pubspec.lock b/pubspec.lock index 4088b0b..69c79fb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -161,6 +161,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + dynamic_color: + dependency: "direct main" + description: + name: dynamic_color + sha256: "74dff1435a695887ca64899b8990004f8d1232b0e84bfc4faa1fdda7c6f57cc1" + url: "https://pub.dev" + source: hosted + version: "1.6.5" email_validator: dependency: "direct main" description: @@ -871,4 +879,4 @@ packages: version: "1.0.0" sdks: dart: ">=3.0.1 <4.0.0" - flutter: ">=3.3.0" + flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index 8dbe28a..d6b9076 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,6 +10,7 @@ dependencies: flutter: sdk: flutter + dynamic_color: ^1.6.5 provider: ^6.0.5 shared_preferences: ^2.1.1 lottie: ^2.3.2 -- cgit v1.2.3