Merge branch 'theme-add-dark-theme' into 'master'

Add dark Theme!

Closes #9

See merge request ChristianPauly/fluffychat-flutter!24
This commit is contained in:
Christian Pauly 2020-02-16 14:57:50 +00:00
commit 38ef2b7807
16 changed files with 577 additions and 111 deletions

View File

@ -0,0 +1,285 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import '../utils/famedlysdk_store.dart';
import 'matrix.dart';
enum Themes {
light,
dark,
system,
}
final ThemeData lightTheme = ThemeData(
primaryColorDark: Colors.white,
primaryColorLight: Color(0xff121212),
brightness: Brightness.light,
primaryColor: Color(0xFF5625BA),
backgroundColor: Colors.white,
secondaryHeaderColor: Color(0xFFECECF2),
scaffoldBackgroundColor: Colors.white,
dialogTheme: DialogTheme(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
popupMenuTheme: PopupMenuThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
appBarTheme: AppBarTheme(
brightness: Brightness.light,
color: Colors.white,
textTheme: TextTheme(
title: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
iconTheme: IconThemeData(color: Colors.black),
),
);
final ThemeData darkTheme = ThemeData.dark().copyWith(
primaryColorDark: Color(0xff121212),
primaryColorLight: Colors.white,
primaryColor: Color(0xFF5625BA),
backgroundColor: Color(0xff121212),
scaffoldBackgroundColor: Color(0xff121212),
accentColor: Color(0xFFF5B4D2),
secondaryHeaderColor: Color(0xff1D1D1D),
appBarTheme: AppBarTheme(
brightness: Brightness.dark,
color: Color(0xff1D1D1D),
textTheme: TextTheme(
title: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
iconTheme: IconThemeData(color: Colors.white),
),
);
final ThemeData amoledTheme = ThemeData.dark().copyWith(
primaryColorDark: Color(0xff121212),
primaryColorLight: Colors.white,
primaryColor: Color(0xFF5625BA),
backgroundColor: Colors.black,
scaffoldBackgroundColor: Colors.black,
accentColor: Color(0xFFF5B4D2),
secondaryHeaderColor: Color(0xff1D1D1D),
appBarTheme: AppBarTheme(
brightness: Brightness.dark,
color: Color(0xff1D1D1D),
textTheme: TextTheme(
title: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
iconTheme: IconThemeData(color: Colors.white),
),
);
Color chatListItemColor(BuildContext context, bool activeChat) =>
Theme.of(context).brightness == Brightness.light
? activeChat ? Color(0xFFE8E8E8) : Colors.white
: activeChat
? ThemeSwitcherWidget.of(context).amoledEnabled
? Color(0xff121212)
: Colors.black
: ThemeSwitcherWidget.of(context).amoledEnabled
? Colors.black
: Color(0xff121212);
Color blackWhiteColor(BuildContext context) =>
Theme.of(context).brightness == Brightness.light
? Colors.white
: Colors.black;
class ThemeSwitcher extends InheritedWidget {
final ThemeSwitcherWidgetState data;
const ThemeSwitcher({
Key key,
@required this.data,
@required Widget child,
}) : assert(child != null),
super(key: key, child: child);
@override
bool updateShouldNotify(ThemeSwitcher old) {
return this != old;
}
}
class ThemeSwitcherWidget extends StatefulWidget {
final Widget child;
ThemeSwitcherWidget({Key key, this.child})
: assert(child != null),
super(key: key);
@override
ThemeSwitcherWidgetState createState() => ThemeSwitcherWidgetState();
/// Returns the (nearest) Client instance of your application.
static ThemeSwitcherWidgetState of(BuildContext context) {
ThemeSwitcherWidgetState newState =
(context.dependOnInheritedWidgetOfExactType<ThemeSwitcher>()).data;
newState.context = context;
return newState;
}
}
class ThemeSwitcherWidgetState extends State<ThemeSwitcherWidget> {
ThemeData themeData;
Themes selectedTheme;
bool amoledEnabled;
BuildContext context;
Future loadSelection(MatrixState matrix) async {
if (kIsWeb) {
Store store = matrix.client.storeAPI;
String item = await store.getItem("theme") ?? "light";
selectedTheme =
Themes.values.firstWhere((e) => e.toString() == 'Themes.' + item);
amoledEnabled =
(await store.getItem("amoled_enabled") ?? "false").toLowerCase() ==
'true';
} else {
ExtendedStore store = matrix.client.storeAPI;
String item = await store.getItem("theme") ?? "light";
selectedTheme =
Themes.values.firstWhere((e) => e.toString() == 'Themes.' + item);
amoledEnabled =
(await store.getItem("amoled_enabled") ?? "false").toLowerCase() ==
'true';
}
switchTheme(matrix, selectedTheme, amoledEnabled);
return;
}
void switchTheme(
MatrixState matrix, Themes newTheme, bool amoled_enabled) async {
ThemeData theme;
switch (newTheme) {
case Themes.light:
theme = lightTheme;
break;
case Themes.dark:
if (amoled_enabled) {
theme = amoledTheme;
} else {
theme = darkTheme;
}
break;
case Themes.system:
// This needs to be a low level call as we don't have a MaterialApp yet
Brightness brightness =
MediaQueryData.fromWindow(WidgetsBinding.instance.window)
.platformBrightness;
if (brightness == Brightness.dark) {
if (amoled_enabled) {
theme = amoledTheme;
} else {
theme = darkTheme;
}
} else {
theme = lightTheme;
}
break;
}
await saveThemeValue(matrix, newTheme);
await saveAmoledEnabledValue(matrix, amoled_enabled);
setState(() {
amoledEnabled = amoled_enabled;
selectedTheme = newTheme;
themeData = theme;
});
}
Future saveThemeValue(MatrixState matrix, Themes value) async {
if (kIsWeb) {
Store store = matrix.client.storeAPI;
await store.setItem("theme", value.toString().split('.').last);
} else {
ExtendedStore store = matrix.client.storeAPI;
await store.setItem("theme", value.toString().split('.').last);
}
}
Future saveAmoledEnabledValue(MatrixState matrix, bool value) async {
if (kIsWeb) {
Store store = matrix.client.storeAPI;
await store.setItem("amoled_enabled", value.toString());
} else {
ExtendedStore store = matrix.client.storeAPI;
await store.setItem("amoled_enabled", value.toString());
}
}
void setup() async {
final MatrixState matrix = Matrix.of(context);
await loadSelection(matrix);
if (selectedTheme == null) {
switchTheme(matrix, Themes.light, false);
} else {
switch (selectedTheme) {
case Themes.light:
switchTheme(matrix, Themes.light, false);
break;
case Themes.dark:
if (amoledEnabled) {
switchTheme(matrix, Themes.dark, true);
} else {
switchTheme(matrix, Themes.dark, false);
}
break;
case Themes.system:
switchTheme(matrix, Themes.system, false);
break;
}
}
}
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (amoledEnabled == null || selectedTheme == null) {
setup();
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
if (themeData == null) {
// This needs to be a low level call as we don't have a MaterialApp yet
Brightness brightness =
MediaQueryData.fromWindow(WidgetsBinding.instance.window)
.platformBrightness;
if (brightness == Brightness.dark) {
themeData = darkTheme;
} else {
themeData = lightTheme;
}
return ThemeSwitcher(
data: this,
child: widget.child,
);
} else {
return ThemeSwitcher(
data: this,
child: widget.child,
);
}
}
}

View File

@ -1,18 +1,19 @@
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/components/dialogs/simple_dialogs.dart';
import 'package:fluffychat/i18n/i18n.dart';
import 'package:fluffychat/utils/event_extension.dart';
import 'package:fluffychat/utils/date_time_extension.dart';
import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/utils/room_extension.dart';
import 'package:fluffychat/views/chat.dart'; import 'package:fluffychat/views/chat.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:toast/toast.dart';
import 'package:pedantic/pedantic.dart'; import 'package:pedantic/pedantic.dart';
import 'package:toast/toast.dart';
import '../../i18n/i18n.dart';
import '../../utils/app_route.dart';
import '../../utils/date_time_extension.dart';
import '../../utils/event_extension.dart';
import '../../utils/room_extension.dart';
import '../../views/chat.dart';
import '../ThemeSwitcher.dart';
import '../avatar.dart'; import '../avatar.dart';
import '../dialogs/simple_dialogs.dart';
import '../matrix.dart'; import '../matrix.dart';
class ChatListItem extends StatelessWidget { class ChatListItem extends StatelessWidget {
@ -133,7 +134,7 @@ class ChatListItem extends StatelessWidget {
onWillDismiss: (actionType) => archiveAction(context), onWillDismiss: (actionType) => archiveAction(context),
), ),
child: Material( child: Material(
color: activeChat ? Color(0xFFE8E8E8) : Colors.white, color: chatListItemColor(context, activeChat),
child: ListTile( child: ListTile(
leading: Avatar(room.avatar, room.displayname), leading: Avatar(room.avatar, room.displayname),
title: Row( title: Row(

View File

@ -44,7 +44,11 @@ class Message extends StatelessWidget {
BubbleNip nip = sameSender BubbleNip nip = sameSender
? BubbleNip.no ? BubbleNip.no
: ownMessage ? BubbleNip.rightBottom : BubbleNip.leftBottom; : ownMessage ? BubbleNip.rightBottom : BubbleNip.leftBottom;
final Color textColor = ownMessage ? Colors.white : Colors.black; final Color textColor = ownMessage
? Colors.white
: Theme.of(context).brightness == Brightness.dark
? Colors.white
: Colors.black;
MainAxisAlignment rowMainAxisAlignment = MainAxisAlignment rowMainAxisAlignment =
ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start; ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start;

View File

@ -1,14 +1,9 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/i18n/i18n.dart'; import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/utils/event_extension.dart';
import 'package:fluffychat/utils/famedlysdk_store.dart';
import 'package:fluffychat/utils/room_extension.dart';
import 'package:fluffychat/views/chat.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart';
@ -16,6 +11,13 @@ import 'package:localstorage/localstorage.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:toast/toast.dart'; import 'package:toast/toast.dart';
import '../i18n/i18n.dart';
import '../utils/app_route.dart';
import '../utils/event_extension.dart';
import '../utils/famedlysdk_store.dart';
import '../utils/room_extension.dart';
import '../views/chat.dart';
class Matrix extends StatefulWidget { class Matrix extends StatefulWidget {
final Widget child; final Widget child;
@ -295,7 +297,7 @@ class MatrixState extends State<Matrix> {
client.storeAPI = kIsWeb ? Store(client) : ExtendedStore(client); client.storeAPI = kIsWeb ? Store(client) : ExtendedStore(client);
debugPrint( debugPrint(
"[Store] Store is extended: ${client.storeAPI.extended.toString()}"); "[Store] Store is extended: ${client.storeAPI.extended.toString()}");
if (await initLoginState == LoginState.logged) { if (await initLoginState == LoginState.logged && !kIsWeb) {
await setupFirebase(); await setupFirebase();
} }
} }

View File

@ -569,6 +569,16 @@ class I18n {
String get signUp => Intl.message("Sign up"); String get signUp => Intl.message("Sign up");
String get changeTheme => Intl.message("Change your style");
String get systemTheme => Intl.message("System");
String get lightTheme => Intl.message("Light");
String get darkTheme => Intl.message("Dark");
String get useAmoledTheme => Intl.message("Use Amoled compatible colors?");
String get sourceCode => Intl.message("Source code"); String get sourceCode => Intl.message("Source code");
String get startYourFirstChat => Intl.message("Start your first chat :-)"); String get startYourFirstChat => Intl.message("Start your first chat :-)");

View File

@ -892,6 +892,31 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"Change your style": "Change your style",
"@Change your style": {
"type": "text",
"placeholders": {}
},
"System": "System",
"@System": {
"type": "text",
"placeholders": {}
},
"Light": "Hell",
"@Light": {
"type": "text",
"placeholders": {}
},
"Dark": "Dunkel",
"@Dark": {
"type": "text",
"placeholders": {}
},
"Use Amoled compatible colors?": "Amoled optimierte Farben verwenden?",
"@Use Amoled compatible colors?": {
"type": "text",
"placeholders": {}
},
"Source code": "Quellcode", "Source code": "Quellcode",
"@Source code": { "@Source code": {
"type": "text", "type": "text",

View File

@ -892,6 +892,31 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"Change your style": "Change your style",
"@Change your style": {
"type": "text",
"placeholders": {}
},
"System": "System",
"@System": {
"type": "text",
"placeholders": {}
},
"Light": "Light",
"@Light": {
"type": "text",
"placeholders": {}
},
"Dark": "Dark",
"@Dark": {
"type": "text",
"placeholders": {}
},
"Use Amoled compatible colors?": "Use Amoled compatible colors?",
"@Use Amoled compatible colors?": {
"type": "text",
"placeholders": {}
},
"Source code": "Source code", "Source code": "Source code",
"@Source code": { "@Source code": {
"type": "text", "type": "text",

View File

@ -150,6 +150,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Ban from chat" : MessageLookupByLibrary.simpleMessage("Aus dem Chat verbannen"), "Ban from chat" : MessageLookupByLibrary.simpleMessage("Aus dem Chat verbannen"),
"Banned" : MessageLookupByLibrary.simpleMessage("Banned"), "Banned" : MessageLookupByLibrary.simpleMessage("Banned"),
"Change the name of the group" : MessageLookupByLibrary.simpleMessage("Gruppenname ändern"), "Change the name of the group" : MessageLookupByLibrary.simpleMessage("Gruppenname ändern"),
"Change your style" : MessageLookupByLibrary.simpleMessage("Change your style"),
"Changelog" : MessageLookupByLibrary.simpleMessage("Changelog"), "Changelog" : MessageLookupByLibrary.simpleMessage("Changelog"),
"Chat details" : MessageLookupByLibrary.simpleMessage("Gruppeninfo"), "Chat details" : MessageLookupByLibrary.simpleMessage("Gruppeninfo"),
"Choose a username" : MessageLookupByLibrary.simpleMessage("Wähle einen Benutzernamen"), "Choose a username" : MessageLookupByLibrary.simpleMessage("Wähle einen Benutzernamen"),
@ -166,6 +167,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Create" : MessageLookupByLibrary.simpleMessage("Create"), "Create" : MessageLookupByLibrary.simpleMessage("Create"),
"Create account now" : MessageLookupByLibrary.simpleMessage("Account jetzt erstellen"), "Create account now" : MessageLookupByLibrary.simpleMessage("Account jetzt erstellen"),
"Create new group" : MessageLookupByLibrary.simpleMessage("Neue Gruppe"), "Create new group" : MessageLookupByLibrary.simpleMessage("Neue Gruppe"),
"Dark" : MessageLookupByLibrary.simpleMessage("Dunkel"),
"Delete" : MessageLookupByLibrary.simpleMessage("Löschen"), "Delete" : MessageLookupByLibrary.simpleMessage("Löschen"),
"Delete message" : MessageLookupByLibrary.simpleMessage("Nachricht löschen"), "Delete message" : MessageLookupByLibrary.simpleMessage("Nachricht löschen"),
"Discard picture" : MessageLookupByLibrary.simpleMessage("Bild verwerfen"), "Discard picture" : MessageLookupByLibrary.simpleMessage("Bild verwerfen"),
@ -199,6 +201,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Leave" : MessageLookupByLibrary.simpleMessage("Verlassen"), "Leave" : MessageLookupByLibrary.simpleMessage("Verlassen"),
"Left the chat" : MessageLookupByLibrary.simpleMessage("Hat den Chat verlassen"), "Left the chat" : MessageLookupByLibrary.simpleMessage("Hat den Chat verlassen"),
"License" : MessageLookupByLibrary.simpleMessage("Lizenz"), "License" : MessageLookupByLibrary.simpleMessage("Lizenz"),
"Light" : MessageLookupByLibrary.simpleMessage("Hell"),
"Loading... Please wait" : MessageLookupByLibrary.simpleMessage("Lade ... Bitte warten"), "Loading... Please wait" : MessageLookupByLibrary.simpleMessage("Lade ... Bitte warten"),
"Login" : MessageLookupByLibrary.simpleMessage("Login"), "Login" : MessageLookupByLibrary.simpleMessage("Login"),
"Logout" : MessageLookupByLibrary.simpleMessage("Logout"), "Logout" : MessageLookupByLibrary.simpleMessage("Logout"),
@ -244,12 +247,14 @@ class MessageLookup extends MessageLookupByLibrary {
"Source code" : MessageLookupByLibrary.simpleMessage("Quellcode"), "Source code" : MessageLookupByLibrary.simpleMessage("Quellcode"),
"Start your first chat :-)" : MessageLookupByLibrary.simpleMessage("Starte deinen ersten Chat :-)"), "Start your first chat :-)" : MessageLookupByLibrary.simpleMessage("Starte deinen ersten Chat :-)"),
"Sunday" : MessageLookupByLibrary.simpleMessage("Sonntag"), "Sunday" : MessageLookupByLibrary.simpleMessage("Sonntag"),
"System" : MessageLookupByLibrary.simpleMessage("System"),
"Tap to show menu" : MessageLookupByLibrary.simpleMessage("Tippen, um das Menü anzuzeigen"), "Tap to show menu" : MessageLookupByLibrary.simpleMessage("Tippen, um das Menü anzuzeigen"),
"This room has been archived." : MessageLookupByLibrary.simpleMessage("Dieser Raum wurde archiviert."), "This room has been archived." : MessageLookupByLibrary.simpleMessage("Dieser Raum wurde archiviert."),
"Thursday" : MessageLookupByLibrary.simpleMessage("Donnerstag"), "Thursday" : MessageLookupByLibrary.simpleMessage("Donnerstag"),
"Try to send again" : MessageLookupByLibrary.simpleMessage("Nochmal versuchen zu senden"), "Try to send again" : MessageLookupByLibrary.simpleMessage("Nochmal versuchen zu senden"),
"Tuesday" : MessageLookupByLibrary.simpleMessage("Tuesday"), "Tuesday" : MessageLookupByLibrary.simpleMessage("Tuesday"),
"Unmute chat" : MessageLookupByLibrary.simpleMessage("Stumm aus"), "Unmute chat" : MessageLookupByLibrary.simpleMessage("Stumm aus"),
"Use Amoled compatible colors?" : MessageLookupByLibrary.simpleMessage("Amoled optimierte Farben verwenden?"),
"Username" : MessageLookupByLibrary.simpleMessage("Benutzername"), "Username" : MessageLookupByLibrary.simpleMessage("Benutzername"),
"Visibility of the chat history" : MessageLookupByLibrary.simpleMessage("Sichtbarkeit des Chat-Verlaufs"), "Visibility of the chat history" : MessageLookupByLibrary.simpleMessage("Sichtbarkeit des Chat-Verlaufs"),
"Visible for all participants" : MessageLookupByLibrary.simpleMessage("Sichtbar für alle Teilnehmer"), "Visible for all participants" : MessageLookupByLibrary.simpleMessage("Sichtbar für alle Teilnehmer"),

View File

@ -150,6 +150,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Ban from chat" : MessageLookupByLibrary.simpleMessage("Ban from chat"), "Ban from chat" : MessageLookupByLibrary.simpleMessage("Ban from chat"),
"Banned" : MessageLookupByLibrary.simpleMessage("Banned"), "Banned" : MessageLookupByLibrary.simpleMessage("Banned"),
"Change the name of the group" : MessageLookupByLibrary.simpleMessage("Change the name of the group"), "Change the name of the group" : MessageLookupByLibrary.simpleMessage("Change the name of the group"),
"Change your style" : MessageLookupByLibrary.simpleMessage("Change your style"),
"Changelog" : MessageLookupByLibrary.simpleMessage("Changelog"), "Changelog" : MessageLookupByLibrary.simpleMessage("Changelog"),
"Chat details" : MessageLookupByLibrary.simpleMessage("Chat details"), "Chat details" : MessageLookupByLibrary.simpleMessage("Chat details"),
"Choose a username" : MessageLookupByLibrary.simpleMessage("Choose a username"), "Choose a username" : MessageLookupByLibrary.simpleMessage("Choose a username"),
@ -166,6 +167,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Create" : MessageLookupByLibrary.simpleMessage("Create"), "Create" : MessageLookupByLibrary.simpleMessage("Create"),
"Create account now" : MessageLookupByLibrary.simpleMessage("Create account now"), "Create account now" : MessageLookupByLibrary.simpleMessage("Create account now"),
"Create new group" : MessageLookupByLibrary.simpleMessage("Create new group"), "Create new group" : MessageLookupByLibrary.simpleMessage("Create new group"),
"Dark" : MessageLookupByLibrary.simpleMessage("Dark"),
"Delete" : MessageLookupByLibrary.simpleMessage("Delete"), "Delete" : MessageLookupByLibrary.simpleMessage("Delete"),
"Delete message" : MessageLookupByLibrary.simpleMessage("Delete message"), "Delete message" : MessageLookupByLibrary.simpleMessage("Delete message"),
"Discard picture" : MessageLookupByLibrary.simpleMessage("Discard picture"), "Discard picture" : MessageLookupByLibrary.simpleMessage("Discard picture"),
@ -199,6 +201,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Leave" : MessageLookupByLibrary.simpleMessage("Leave"), "Leave" : MessageLookupByLibrary.simpleMessage("Leave"),
"Left the chat" : MessageLookupByLibrary.simpleMessage("Left the chat"), "Left the chat" : MessageLookupByLibrary.simpleMessage("Left the chat"),
"License" : MessageLookupByLibrary.simpleMessage("License"), "License" : MessageLookupByLibrary.simpleMessage("License"),
"Light" : MessageLookupByLibrary.simpleMessage("Light"),
"Loading... Please wait" : MessageLookupByLibrary.simpleMessage("Loading... Please wait"), "Loading... Please wait" : MessageLookupByLibrary.simpleMessage("Loading... Please wait"),
"Login" : MessageLookupByLibrary.simpleMessage("Login"), "Login" : MessageLookupByLibrary.simpleMessage("Login"),
"Logout" : MessageLookupByLibrary.simpleMessage("Logout"), "Logout" : MessageLookupByLibrary.simpleMessage("Logout"),
@ -244,12 +247,14 @@ class MessageLookup extends MessageLookupByLibrary {
"Source code" : MessageLookupByLibrary.simpleMessage("Source code"), "Source code" : MessageLookupByLibrary.simpleMessage("Source code"),
"Start your first chat :-)" : MessageLookupByLibrary.simpleMessage("Start your first chat :-)"), "Start your first chat :-)" : MessageLookupByLibrary.simpleMessage("Start your first chat :-)"),
"Sunday" : MessageLookupByLibrary.simpleMessage("Sunday"), "Sunday" : MessageLookupByLibrary.simpleMessage("Sunday"),
"System" : MessageLookupByLibrary.simpleMessage("System"),
"Tap to show menu" : MessageLookupByLibrary.simpleMessage("Tap to show menu"), "Tap to show menu" : MessageLookupByLibrary.simpleMessage("Tap to show menu"),
"This room has been archived." : MessageLookupByLibrary.simpleMessage("This room has been archived."), "This room has been archived." : MessageLookupByLibrary.simpleMessage("This room has been archived."),
"Thursday" : MessageLookupByLibrary.simpleMessage("Thursday"), "Thursday" : MessageLookupByLibrary.simpleMessage("Thursday"),
"Try to send again" : MessageLookupByLibrary.simpleMessage("Try to send again"), "Try to send again" : MessageLookupByLibrary.simpleMessage("Try to send again"),
"Tuesday" : MessageLookupByLibrary.simpleMessage("Tuesday"), "Tuesday" : MessageLookupByLibrary.simpleMessage("Tuesday"),
"Unmute chat" : MessageLookupByLibrary.simpleMessage("Unmute chat"), "Unmute chat" : MessageLookupByLibrary.simpleMessage("Unmute chat"),
"Use Amoled compatible colors?" : MessageLookupByLibrary.simpleMessage("Use Amoled compatible colors?"),
"Username" : MessageLookupByLibrary.simpleMessage("Username"), "Username" : MessageLookupByLibrary.simpleMessage("Username"),
"Visibility of the chat history" : MessageLookupByLibrary.simpleMessage("Visibility of the chat history"), "Visibility of the chat history" : MessageLookupByLibrary.simpleMessage("Visibility of the chat history"),
"Visible for all participants" : MessageLookupByLibrary.simpleMessage("Visible for all participants"), "Visible for all participants" : MessageLookupByLibrary.simpleMessage("Visible for all participants"),

View File

@ -1,19 +1,17 @@
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/i18n/i18n.dart';
import 'package:fluffychat/views/sign_up.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:universal_html/prefer_universal/html.dart' as html;
import 'i18n/i18n.dart';
import 'views/sign_up.dart';
import 'components/ThemeSwitcher.dart';
import 'components/matrix.dart'; import 'components/matrix.dart';
import 'views/chat_list.dart'; import 'views/chat_list.dart';
void main() { void main() {
SystemChrome.setSystemUIOverlayStyle( SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(statusBarColor: Colors.white), SystemUiOverlayStyle(statusBarColor: Colors.transparent));
);
runApp(App()); runApp(App());
} }
@ -23,63 +21,39 @@ class App extends StatelessWidget {
return Matrix( return Matrix(
clientName: "FluffyChat", clientName: "FluffyChat",
child: Builder( child: Builder(
builder: (BuildContext context) => MaterialApp( builder: (BuildContext context) => ThemeSwitcherWidget(
title: 'FluffyChat', child: Builder(
theme: ThemeData( builder: (BuildContext context) => MaterialApp(
brightness: Brightness.light, title: 'FluffyChat',
primaryColor: Color(0xFF5625BA), theme: ThemeSwitcherWidget.of(context).themeData,
backgroundColor: Colors.white, localizationsDelegates: [
secondaryHeaderColor: Color(0xFFECECF2), AppLocalizationsDelegate(),
scaffoldBackgroundColor: Colors.white, GlobalMaterialLocalizations.delegate,
dialogTheme: DialogTheme( GlobalWidgetsLocalizations.delegate,
shape: RoundedRectangleBorder( GlobalCupertinoLocalizations.delegate,
borderRadius: BorderRadius.circular(8.0), ],
supportedLocales: [
const Locale('en'), // English
const Locale('de'), // German
],
home: FutureBuilder<LoginState>(
future:
Matrix.of(context).client.onLoginStateChanged.stream.first,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
if (Matrix.of(context).client.isLogged()) {
return ChatListView();
}
return SignUp();
},
), ),
), ),
popupMenuTheme: PopupMenuThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
appBarTheme: AppBarTheme(
brightness: Brightness.light,
color: Colors.white,
//elevation: 1,
textTheme: TextTheme(
title: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
iconTheme: IconThemeData(color: Colors.black),
),
),
localizationsDelegates: [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
const Locale('en'), // English
const Locale('de'), // German
],
locale: kIsWeb
? Locale(html.window.navigator.language.split("-").first)
: null,
home: FutureBuilder<LoginState>(
future: Matrix.of(context).client.onLoginStateChanged.stream.first,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
if (Matrix.of(context).client.isLogged()) return ChatListView();
return SignUp();
},
), ),
), ),
), ),

View File

@ -237,7 +237,7 @@ class _ChatDetailsState extends State<ChatDetails> {
linkStyle: TextStyle(color: Colors.blueAccent), linkStyle: TextStyle(color: Colors.blueAccent),
textStyle: TextStyle( textStyle: TextStyle(
fontSize: 14, fontSize: 14,
color: Colors.black, color: Theme.of(context).accentColor,
), ),
), ),
onTap: widget.room.canSendEvent("m.room.topic") onTap: widget.room.canSendEvent("m.room.topic")

View File

@ -1,16 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/components/adaptive_page_layout.dart';
import 'package:fluffychat/components/list_items/chat_list_item.dart';
import 'package:fluffychat/components/matrix.dart';
import 'package:fluffychat/i18n/i18n.dart';
import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/utils/url_launcher.dart';
import 'package:fluffychat/views/archive.dart';
import 'package:fluffychat/views/new_group.dart';
import 'package:fluffychat/views/new_private_chat.dart';
import 'package:fluffychat/views/settings.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -18,6 +8,18 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:toast/toast.dart'; import 'package:toast/toast.dart';
import 'package:uni_links/uni_links.dart'; import 'package:uni_links/uni_links.dart';
import '../components/ThemeSwitcher.dart';
import '../components/adaptive_page_layout.dart';
import '../components/list_items/chat_list_item.dart';
import '../components/matrix.dart';
import '../i18n/i18n.dart';
import '../utils/app_route.dart';
import '../utils/url_launcher.dart';
import 'archive.dart';
import 'new_group.dart';
import 'new_private_chat.dart';
import 'settings.dart';
enum SelectMode { normal, share } enum SelectMode { normal, share }
class ChatListView extends StatelessWidget { class ChatListView extends StatelessWidget {
@ -39,6 +41,7 @@ class ChatList extends StatefulWidget {
final String activeChat; final String activeChat;
const ChatList({this.activeChat, Key key}) : super(key: key); const ChatList({this.activeChat, Key key}) : super(key: key);
@override @override
_ChatListState createState() => _ChatListState(); _ChatListState createState() => _ChatListState();
} }
@ -189,13 +192,15 @@ class _ChatListState extends State<ChatList> {
), ),
floatingActionButton: SpeedDial( floatingActionButton: SpeedDial(
child: Icon(Icons.add), child: Icon(Icons.add),
overlayColor: blackWhiteColor(context),
backgroundColor: Theme.of(context).primaryColor, backgroundColor: Theme.of(context).primaryColor,
children: [ children: [
SpeedDialChild( SpeedDialChild(
child: Icon(Icons.people_outline), child: Icon(Icons.people_outline),
backgroundColor: Colors.blue, backgroundColor: Colors.blue,
label: I18n.of(context).createNewGroup, label: I18n.of(context).createNewGroup,
labelStyle: TextStyle(fontSize: 18.0), labelStyle:
TextStyle(fontSize: 18.0, color: blackWhiteColor(context)),
onTap: () => Navigator.of(context).pushAndRemoveUntil( onTap: () => Navigator.of(context).pushAndRemoveUntil(
AppRoute.defaultRoute(context, NewGroupView()), AppRoute.defaultRoute(context, NewGroupView()),
(r) => r.isFirst), (r) => r.isFirst),
@ -204,7 +209,11 @@ class _ChatListState extends State<ChatList> {
child: Icon(Icons.person_add), child: Icon(Icons.person_add),
backgroundColor: Colors.green, backgroundColor: Colors.green,
label: I18n.of(context).newPrivateChat, label: I18n.of(context).newPrivateChat,
labelStyle: TextStyle(fontSize: 18.0), labelStyle: TextStyle(
fontSize: 18.0,
color: Theme.of(context).brightness == Brightness.light
? Colors.white
: Colors.black),
onTap: () => Navigator.of(context).pushAndRemoveUntil( onTap: () => Navigator.of(context).pushAndRemoveUntil(
AppRoute.defaultRoute(context, NewPrivateChatView()), AppRoute.defaultRoute(context, NewPrivateChatView()),
(r) => r.isFirst), (r) => r.isFirst),

View File

@ -120,7 +120,6 @@ class _LoginState extends State<Login> {
), ),
ListTile( ListTile(
leading: CircleAvatar( leading: CircleAvatar(
backgroundColor: Colors.white,
child: Icon(Icons.account_box, child: Icon(Icons.account_box,
color: Theme.of(context).primaryColor), color: Theme.of(context).primaryColor),
), ),
@ -137,7 +136,9 @@ class _LoginState extends State<Login> {
), ),
ListTile( ListTile(
leading: CircleAvatar( leading: CircleAvatar(
backgroundColor: Colors.white, backgroundColor: Theme.of(context).brightness == Brightness.dark
? Color(0xff121212)
: Colors.white,
child: Icon(Icons.lock, color: Theme.of(context).primaryColor), child: Icon(Icons.lock, color: Theme.of(context).primaryColor),
), ),
title: TextField( title: TextField(

View File

@ -1,20 +1,22 @@
import 'dart:io'; import 'dart:io';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/components/adaptive_page_layout.dart';
import 'package:fluffychat/components/content_banner.dart';
import 'package:fluffychat/components/dialogs/simple_dialogs.dart';
import 'package:fluffychat/components/matrix.dart';
import 'package:fluffychat/i18n/i18n.dart';
import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/views/app_info.dart';
import 'package:fluffychat/views/chat_list.dart';
import 'package:fluffychat/views/sign_up.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:toast/toast.dart'; import 'package:toast/toast.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'app_info.dart';
import 'chat_list.dart';
import 'settings_themes.dart';
import 'sign_up.dart';
import '../components/dialogs/simple_dialogs.dart';
import '../components/adaptive_page_layout.dart';
import '../components/content_banner.dart';
import '../components/matrix.dart';
import '../i18n/i18n.dart';
import '../utils/app_route.dart';
class SettingsView extends StatelessWidget { class SettingsView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -34,6 +36,7 @@ class Settings extends StatefulWidget {
class _SettingsState extends State<Settings> { class _SettingsState extends State<Settings> {
Future<dynamic> profileFuture; Future<dynamic> profileFuture;
dynamic profile; dynamic profile;
void logoutAction(BuildContext context) async { void logoutAction(BuildContext context) async {
if (await SimpleDialogs(context).askConfirmation() == false) { if (await SimpleDialogs(context).askConfirmation() == false) {
return; return;
@ -140,6 +143,17 @@ class _SettingsState extends State<Settings> {
subtitle: Text(profile?.displayname ?? client.userID.localpart), subtitle: Text(profile?.displayname ?? client.userID.localpart),
onTap: () => setDisplaynameAction(context), onTap: () => setDisplaynameAction(context),
), ),
ListTile(
trailing: Icon(Icons.color_lens),
title: Text(I18n.of(context).changeTheme),
onTap: () async => await Navigator.of(context).push(
AppRoute.defaultRoute(
context,
ThemesSettingsView(),
),
),
),
Divider(thickness: 1),
ListTile( ListTile(
trailing: Icon(Icons.exit_to_app), trailing: Icon(Icons.exit_to_app),
title: Text(I18n.of(context).logout), title: Text(I18n.of(context).logout),

View File

@ -0,0 +1,105 @@
import 'package:flutter/material.dart';
import '../components/ThemeSwitcher.dart';
import '../components/adaptive_page_layout.dart';
import '../components/matrix.dart';
import '../i18n/i18n.dart';
import 'chat_list.dart';
class ThemesSettingsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AdaptivePageLayout(
primaryPage: FocusPage.SECOND,
firstScaffold: ChatList(),
secondScaffold: ThemesSettings(),
);
}
}
class ThemesSettings extends StatefulWidget {
@override
ThemesSettingsState createState() => ThemesSettingsState();
}
class ThemesSettingsState extends State<ThemesSettings> {
Themes _selectedTheme;
bool _amoledEnabled;
@override
Widget build(BuildContext context) {
final MatrixState matrix = Matrix.of(context);
final ThemeSwitcherWidgetState themeEngine =
ThemeSwitcherWidget.of(context);
_selectedTheme = themeEngine.selectedTheme;
_amoledEnabled = themeEngine.amoledEnabled;
return Scaffold(
appBar: AppBar(
title: Text(I18n.of(context).changeTheme),
),
body: Column(
children: <Widget>[
RadioListTile<Themes>(
title: Text(
I18n.of(context).systemTheme,
),
value: Themes.system,
groupValue: _selectedTheme,
activeColor: Theme.of(context).primaryColor,
onChanged: (Themes value) {
setState(() {
_selectedTheme = value;
themeEngine.switchTheme(matrix, value, _amoledEnabled);
});
},
),
RadioListTile<Themes>(
title: Text(
I18n.of(context).lightTheme,
),
value: Themes.light,
groupValue: _selectedTheme,
activeColor: Theme.of(context).primaryColor,
onChanged: (Themes value) {
setState(() {
_selectedTheme = value;
themeEngine.switchTheme(matrix, value, _amoledEnabled);
});
},
),
RadioListTile<Themes>(
title: Text(
I18n.of(context).darkTheme,
),
value: Themes.dark,
groupValue: _selectedTheme,
activeColor: Theme.of(context).primaryColor,
onChanged: (Themes value) {
setState(() {
_selectedTheme = value;
themeEngine.switchTheme(matrix, value, _amoledEnabled);
});
},
),
Divider(thickness: 8),
ListTile(
title: Text(
I18n.of(context).useAmoledTheme,
),
trailing: Switch(
value: _amoledEnabled,
activeColor: Theme.of(context).primaryColor,
onChanged: (bool value) {
setState(() {
_amoledEnabled = value;
themeEngine.switchTheme(matrix, _selectedTheme, value);
});
},
),
),
],
),
);
}
}

View File

@ -97,12 +97,13 @@ class _SignUpState extends State<SignUp> {
autocorrect: false, autocorrect: false,
controller: serverController, controller: serverController,
decoration: InputDecoration( decoration: InputDecoration(
icon: Icon(Icons.domain), icon: Icon(Icons.domain),
hintText: "matrix-client.matrix.org", hintText: "matrix-client.matrix.org",
errorText: serverError, errorText: serverError,
errorMaxLines: 1, errorMaxLines: 1,
prefixText: "https://", prefixText: "https://",
labelText: serverError == null ? "Homeserver" : serverError), labelText: serverError == null ? "Homeserver" : serverError,
),
), ),
), ),
body: ListView( body: ListView(
@ -115,7 +116,7 @@ class _SignUpState extends State<SignUp> {
leading: CircleAvatar( leading: CircleAvatar(
backgroundImage: avatar == null ? null : FileImage(avatar), backgroundImage: avatar == null ? null : FileImage(avatar),
backgroundColor: avatar == null backgroundColor: avatar == null
? Colors.white ? Theme.of(context).brightness == Brightness.dark ? Color(0xff121212) : Colors.white
: Theme.of(context).secondaryHeaderColor, : Theme.of(context).secondaryHeaderColor,
child: avatar == null child: avatar == null
? Icon(Icons.camera_alt, ? Icon(Icons.camera_alt,
@ -137,7 +138,7 @@ class _SignUpState extends State<SignUp> {
), ),
ListTile( ListTile(
leading: CircleAvatar( leading: CircleAvatar(
backgroundColor: Colors.white, backgroundColor: Theme.of(context).brightness == Brightness.dark ? Color(0xff121212) : Colors.white,
child: Icon( child: Icon(
Icons.account_circle, Icons.account_circle,
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,