diff --git a/README.md b/README.md index 285cf234..f134134c 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ sudo apt install ninja-build * Enable web support in Flutter: https://flutter.dev/docs/get-started/web +* Optionally edit the file `lib/app_config.dart`. If you e.g. only want to change the default homeserver, then only modify the `defaultHomeserver` key. + * Build with: ```bash ./scripts/prepare-web.sh @@ -75,11 +77,6 @@ flutter pub get flutter build web --release --verbose ``` -* Optionally configure by serving a `config.json` at the same path as fluffychat. - An example can be found at `config.sample.json`. None of these - values have to exist, the ones stated here are the default ones. If you e.g. only want - to change the default homeserver, then only modify the `default_homeserver` key. - ### Desktop (Linux, Windows, macOS) * Enable Desktop support in Flutter: https://flutter.dev/desktop diff --git a/assets/fluffychat-banner.png b/assets/banner.png similarity index 100% rename from assets/fluffychat-banner.png rename to assets/banner.png diff --git a/config.sample.json b/config.sample.json deleted file mode 100644 index fad342e3..00000000 --- a/config.sample.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "application_name": "FluffyChat", - "default_homeserver": "matrix.tchncsde", - "privacy_url": "https://fluffychat.im/en/privacy.html", - "source_code_url": "https://gitlab.com/ChristianPauly/fluffychat-flutter", - "support_url": "https://gitlab.com/ChristianPauly/fluffychat-flutter/issues", - "sentry_dns": "https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143", - "render_html": false, - "hide_redacted_events": false, - "hide_unknown_events": false -} diff --git a/lib/app_config.dart b/lib/app_config.dart new file mode 100644 index 00000000..35f7c5fa --- /dev/null +++ b/lib/app_config.dart @@ -0,0 +1,27 @@ +abstract class AppConfig { + static const String applicationName = 'FluffyChat'; + static const String applicationWelcomeMessage = null; + static const String defaultHomeserver = 'matrix.org'; + static String jitsiInstance = 'https://meet.jit.si/'; + static const bool allowOtherHomeservers = true; + static const bool enableRegistration = true; + static const String privacyUrl = 'https://fluffychat.im/en/privacy.html'; + static const String sourceCodeUrl = + 'https://gitlab.com/ChristianPauly/fluffychat-flutter'; + static const String supportUrl = + 'https://gitlab.com/ChristianPauly/fluffychat-flutter/issues'; + static const bool enableSentry = true; + static const String sentryDns = + 'https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143'; + static bool renderHtml = false; + static bool hideRedactedEvents = false; + static bool hideUnknownEvents = false; + static const String inviteLinkPrefix = 'https://matrix.to/#/'; + static const String pushNotificationsChannelId = 'fluffychat_push'; + static const String pushNotificationsChannelName = 'FluffyChat push channel'; + static const String pushNotificationsChannelDescription = + 'Push notifications for FluffyChat'; + static const String pushNotificationsAppId = 'chat.fluffy.fluffychat'; + static const String pushNotificationsGatewayUrl = 'https://janian.de:7023/'; + static const String pushNotificationsPusherFormat = 'event_id_only'; +} diff --git a/lib/components/chat_settings_popup_menu.dart b/lib/components/chat_settings_popup_menu.dart index 22d848a4..8b22fc77 100644 --- a/lib/components/chat_settings_popup_menu.dart +++ b/lib/components/chat_settings_popup_menu.dart @@ -9,6 +9,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:url_launcher/url_launcher.dart'; +import '../app_config.dart'; import 'dialogs/simple_dialogs.dart'; import 'matrix.dart'; @@ -33,7 +34,7 @@ class _ChatSettingsPopupMenuState extends State { void startCallAction(BuildContext context) async { final url = - '${Matrix.of(context).jitsiInstance}${Uri.encodeComponent(widget.room.id.localpart)}'; + '${AppConfig.jitsiInstance}${Uri.encodeComponent(widget.room.id.localpart)}'; final success = await SimpleDialogs(context) .tryRequestWithLoadingDialog(widget.room.sendEvent({ 'msgtype': Matrix.callNamespace, diff --git a/lib/components/matrix.dart b/lib/components/matrix.dart index cc0c6008..3eec6beb 100644 --- a/lib/components/matrix.dart +++ b/lib/components/matrix.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:io'; -import 'dart:convert'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:famedlysdk/encryption.dart'; @@ -17,9 +16,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:universal_html/prefer_universal/html.dart' as html; import 'package:url_launcher/url_launcher.dart'; -import 'package:path_provider/path_provider.dart'; /*import 'package:fluffychat/views/chat.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/app_config.dart'; import 'package:dbus/dbus.dart'; import 'package:desktop_notifications/desktop_notifications.dart';*/ @@ -27,22 +25,16 @@ import '../utils/beautify_string_extension.dart'; import '../utils/famedlysdk_store.dart'; import 'dialogs/key_verification_dialog.dart'; import '../utils/platform_infos.dart'; -import '../config/app_config.dart'; +import '../app_config.dart'; import '../config/setting_keys.dart'; import 'avatar.dart'; -import 'package:http/http.dart' as http; - class Matrix extends StatefulWidget { static const String callNamespace = 'chat.fluffy.jitsi_call'; final Widget child; - final String clientName; - - final Store store; - - Matrix({this.child, this.clientName, this.store, Key key}) : super(key: key); + Matrix({this.child, Key key}) : super(key: key); @override MatrixState createState() => MatrixState(); @@ -58,7 +50,7 @@ class Matrix extends StatefulWidget { class MatrixState extends State { Client client; - Store store; + Store store = Store(); @override BuildContext context; @@ -77,13 +69,12 @@ class MatrixState extends State { String activeRoomId; File wallpaper; - - String jitsiInstance = 'https://meet.jit.si/'; + String clientName; void clean() async { if (!kIsWeb) return; - await store.deleteItem(widget.clientName); + await store.deleteItem(clientName); } void _initWithStore() async { @@ -96,7 +87,7 @@ class MatrixState extends State { if (PlatformInfos.isMobile) { await FirebaseController.setupFirebase( this, - widget.clientName, + clientName, ); } } @@ -284,38 +275,11 @@ class MatrixState extends State { void initState() { super.initState(); initMatrix(); - initConfig().then((_) => initSettings()); - } - - Future initConfig() async { - if (PlatformInfos.isMobile) { - return; - } - try { - var configJsonString = ''; - if (PlatformInfos.isWeb) { - configJsonString = - utf8.decode((await http.get('config.json')).bodyBytes); - } else if (PlatformInfos.isBetaDesktop) { - final appDocDir = await getApplicationSupportDirectory(); - configJsonString = - await File('${appDocDir.path}/config.json').readAsString(); - } else { - final appDocDir = await getApplicationDocumentsDirectory(); - configJsonString = - await File('${appDocDir.path}/config.json').readAsString(); - } - final configJson = json.decode(configJsonString); - AppConfig.loadFromJson(configJson); - } catch (error) { - debugPrint( - '[ConfigLoader] Failed to load config.json: ' + error.toString()); - } } void initMatrix() { - store = widget.store ?? Store(); - + clientName = + '${AppConfig.applicationName} ${kIsWeb ? 'Web' : Platform.operatingSystem}'; final Set verificationMethods = { KeyVerificationMethod.numbers }; @@ -324,7 +288,7 @@ class MatrixState extends State { verificationMethods.add(KeyVerificationMethod.emoji); } client = Client( - widget.clientName, + clientName, enableE2eeRecovery: true, verificationMethods: verificationMethods, importantStateEvents: { @@ -405,13 +369,13 @@ class MatrixState extends State { .listen(_showLocalNotification); }); } + initSettings(); } void initSettings() { if (store != null) { - store - .getItem(SettingKeys.jitsiInstance) - .then((final instance) => jitsiInstance = instance ?? jitsiInstance); + store.getItem(SettingKeys.jitsiInstance).then((final instance) => + AppConfig.jitsiInstance = instance ?? AppConfig.jitsiInstance); store.getItem(SettingKeys.wallpaper).then((final path) async { if (path == null) return; final file = File(path); diff --git a/lib/components/message_content.dart b/lib/components/message_content.dart index 00a1b9fe..59e35df6 100644 --- a/lib/components/message_content.dart +++ b/lib/components/message_content.dart @@ -13,7 +13,7 @@ import 'package:matrix_link_text/link_text.dart'; import 'package:url_launcher/url_launcher.dart'; import '../utils/url_launcher.dart'; -import '../config/app_config.dart'; +import '../app_config.dart'; import 'html_message.dart'; import 'matrix.dart'; import 'message_download_content.dart'; diff --git a/lib/components/reply_content.dart b/lib/components/reply_content.dart index bf3651eb..9af5bdb1 100644 --- a/lib/components/reply_content.dart +++ b/lib/components/reply_content.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'html_message.dart'; -import '../config/app_config.dart'; +import '../app_config.dart'; class ReplyContent extends StatelessWidget { final Event replyEvent; diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart deleted file mode 100644 index f948b741..00000000 --- a/lib/config/app_config.dart +++ /dev/null @@ -1,52 +0,0 @@ -abstract class AppConfig { - static String get applicationName => _applicationName; - static String _applicationName = 'FluffyChat'; - static String get defaultHomeserver => _defaultHomeserver; - static String _defaultHomeserver = 'matrix-client.matrix.org'; - static String get privacyUrl => _privacyUrl; - static String _privacyUrl = 'https://fluffychat.im/en/privacy.html'; - static String get sourceCodeUrl => _sourceCodeUrl; - static String _sourceCodeUrl = - 'https://gitlab.com/ChristianPauly/fluffychat-flutter'; - static String get supportUrl => _supportUrl; - static String _supportUrl = - 'https://gitlab.com/ChristianPauly/fluffychat-flutter/issues'; - static String get sentryDsn => _sentryDsn; - static String _sentryDsn = - 'https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143'; - // these settings can be re-set at runtime depending on what the in-app settings are - static bool renderHtml = false; - static bool hideRedactedEvents = false; - static bool hideUnknownEvents = false; - static String matrixToLinkPrefix = 'https://matrix.to/#/'; - - static void loadFromJson(Map json) { - if (json['application_name'] is String) { - _applicationName = json['application_name']; - } - if (json['default_homeserver'] is String) { - _defaultHomeserver = json['default_homeserver']; - } - if (json['privacy_url'] is String) { - _privacyUrl = json['privacy_url']; - } - if (json['source_code_url'] is String) { - _sourceCodeUrl = json['source_code_url']; - } - if (json['support_url'] is String) { - _supportUrl = json['support_url']; - } - if (json['sentry_dsn'] is String) { - _sentryDsn = json['sentry_dsn']; - } - if (json['render_html'] is bool) { - renderHtml = json['render_html']; - } - if (json['hide_redacted_events'] is bool) { - hideRedactedEvents = json['hide_redacted_events']; - } - if (json['hide_unknown_events'] is bool) { - hideUnknownEvents = json['hide_unknown_events']; - } - } -} diff --git a/lib/main.dart b/lib/main.dart index 101ade15..a387fb85 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/utils/sentry_controller.dart'; @@ -13,9 +12,10 @@ import 'package:universal_html/prefer_universal/html.dart' as html; import 'components/matrix.dart'; import 'components/theme_switcher.dart'; +import 'app_config.dart'; import 'views/chat_list.dart'; -void main() { +void main() async { SystemChrome.setSystemUIOverlayStyle( SystemUiOverlayStyle(statusBarColor: Colors.transparent)); FlutterError.onError = (FlutterErrorDetails details) => @@ -27,49 +27,50 @@ void main() { } class App extends StatelessWidget { - final String platform = kIsWeb ? 'Web' : Platform.operatingSystem; @override Widget build(BuildContext context) { return Matrix( - clientName: 'FluffyChat $platform', child: Builder( builder: (BuildContext context) => ThemeSwitcherWidget( child: Builder( - builder: (BuildContext context) => MaterialApp( - title: 'FluffyChat', - theme: ThemeSwitcherWidget.of(context).themeData, - localizationsDelegates: L10n.localizationsDelegates, - supportedLocales: L10n.supportedLocales, - locale: kIsWeb - ? Locale(html.window.navigator.language.split('-').first) - : null, - home: FutureBuilder( - future: - Matrix.of(context).client.onLoginStateChanged.stream.first, - builder: (context, snapshot) { - if (snapshot.hasError) { - WidgetsBinding.instance - .addPostFrameCallback((_) => FlushbarHelper.createError( - title: L10n.of(context).oopsSomethingWentWrong, - message: snapshot.error.toString(), - ).show(context)); - return HomeserverPicker(); - } - if (!snapshot.hasData) { - return Scaffold( - body: Center( - child: CircularProgressIndicator(), - ), - ); - } - if (Matrix.of(context).client.isLogged()) { - return ChatListView(); - } - return HomeserverPicker(); - }, - ), - ), - ), + builder: (context) => MaterialApp( + title: '${AppConfig.applicationName}', + theme: ThemeSwitcherWidget.of(context).themeData, + localizationsDelegates: L10n.localizationsDelegates, + supportedLocales: L10n.supportedLocales, + locale: kIsWeb + ? Locale( + html.window.navigator.language.split('-').first) + : null, + home: FutureBuilder( + future: Matrix.of(context) + .client + .onLoginStateChanged + .stream + .first, + builder: (context, snapshot) { + if (snapshot.hasError) { + WidgetsBinding.instance.addPostFrameCallback((_) => + FlushbarHelper.createError( + title: L10n.of(context).oopsSomethingWentWrong, + message: snapshot.error.toString(), + ).show(context)); + return HomeserverPicker(); + } + if (!snapshot.hasData) { + return Scaffold( + body: Center( + child: CircularProgressIndicator(), + ), + ); + } + if (Matrix.of(context).client.isLogged()) { + return ChatListView(); + } + return HomeserverPicker(); + }, + ), + )), ), ), ); diff --git a/lib/utils/firebase_controller.dart b/lib/utils/firebase_controller.dart index 9c779eb9..abcd6404 100644 --- a/lib/utils/firebase_controller.dart +++ b/lib/utils/firebase_controller.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:fluffychat/app_config.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:flushbar/flushbar_helper.dart'; import 'package:famedlysdk/famedlysdk.dart'; @@ -25,12 +26,6 @@ abstract class FirebaseController { static final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); static BuildContext context; - static const String CHANNEL_ID = 'fluffychat_push'; - static const String CHANNEL_NAME = 'FluffyChat push channel'; - static const String CHANNEL_DESCRIPTION = 'Push notifications for FluffyChat'; - static const String APP_ID = 'chat.fluffy.fluffychat'; - static const String GATEWAY_URL = 'https://janian.de:7023/'; - static const String PUSHER_FORMAT = 'event_id_only'; static Future setupFirebase( MatrixState matrix, String clientName) async { @@ -65,12 +60,14 @@ abstract class FirebaseController { final currentPushers = pushers.where((pusher) => pusher.pushkey == token); if (currentPushers.length == 1 && currentPushers.first.kind == 'http' && - currentPushers.first.appId == APP_ID && + currentPushers.first.appId == AppConfig.pushNotificationsAppId && currentPushers.first.appDisplayName == clientName && currentPushers.first.deviceDisplayName == client.deviceName && currentPushers.first.lang == 'en' && - currentPushers.first.data.url.toString() == GATEWAY_URL && - currentPushers.first.data.format == PUSHER_FORMAT) { + currentPushers.first.data.url.toString() == + AppConfig.pushNotificationsGatewayUrl && + currentPushers.first.data.format == + AppConfig.pushNotificationsPusherFormat) { debugPrint('[Push] Pusher already set'); } else { if (currentPushers.isNotEmpty) { @@ -88,13 +85,13 @@ abstract class FirebaseController { .setPusher( Pusher( token, - APP_ID, + AppConfig.pushNotificationsAppId, clientName, client.deviceName, 'en', PusherData( - url: Uri.parse(GATEWAY_URL), - format: PUSHER_FORMAT, + url: Uri.parse(AppConfig.pushNotificationsGatewayUrl), + format: AppConfig.pushNotificationsPusherFormat, ), kind: 'http', ), @@ -255,7 +252,9 @@ abstract class FirebaseController { // Show notification var androidPlatformChannelSpecifics = AndroidNotificationDetails( - CHANNEL_ID, CHANNEL_NAME, CHANNEL_DESCRIPTION, + AppConfig.pushNotificationsChannelId, + AppConfig.pushNotificationsChannelName, + AppConfig.pushNotificationsChannelDescription, styleInformation: MessagingStyleInformation( person, conversationTitle: title, @@ -328,8 +327,11 @@ abstract class FirebaseController { // Display notification var androidPlatformChannelSpecifics = AndroidNotificationDetails( - CHANNEL_ID, CHANNEL_NAME, CHANNEL_DESCRIPTION, - importance: Importance.max, priority: Priority.high); + AppConfig.pushNotificationsChannelId, + AppConfig.pushNotificationsChannelName, + AppConfig.pushNotificationsChannelDescription, + importance: Importance.max, + priority: Priority.high); var iOSPlatformChannelSpecifics = IOSNotificationDetails(); var platformChannelSpecifics = NotificationDetails( android: androidPlatformChannelSpecifics, diff --git a/lib/utils/sentry_controller.dart b/lib/utils/sentry_controller.dart index 32f633a7..512bdcf9 100644 --- a/lib/utils/sentry_controller.dart +++ b/lib/utils/sentry_controller.dart @@ -1,6 +1,6 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:flushbar/flushbar_helper.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/app_config.dart'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -11,6 +11,7 @@ import '../config/setting_keys.dart'; abstract class SentryController { static Future toggleSentryAction(BuildContext context) async { + if (!AppConfig.enableSentry) return; final enableSentry = await showOkCancelAlertDialog( context: context, title: L10n.of(context).sendBugReports, @@ -28,11 +29,12 @@ abstract class SentryController { } static Future getSentryStatus() async { + if (!AppConfig.enableSentry) return false; final storage = Store(); return await storage.getItemBool(SettingKeys.sentry); } - static final sentry = SentryClient(dsn: AppConfig.sentryDsn); + static final sentry = SentryClient(dsn: AppConfig.sentryDns); static void captureException(error, stackTrace) async { debugPrint(error.toString()); diff --git a/lib/utils/url_launcher.dart b/lib/utils/url_launcher.dart index 3875b12e..626f4354 100644 --- a/lib/utils/url_launcher.dart +++ b/lib/utils/url_launcher.dart @@ -2,7 +2,7 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/components/dialogs/simple_dialogs.dart'; import 'package:fluffychat/components/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/app_config.dart'; import 'package:fluffychat/utils/app_route.dart'; import 'package:fluffychat/views/chat.dart'; import 'package:flutter/material.dart'; @@ -15,7 +15,7 @@ class UrlLauncher { const UrlLauncher(this.context, this.url); void launchUrl() { - if (url.startsWith(AppConfig.matrixToLinkPrefix) || + if (url.startsWith(AppConfig.inviteLinkPrefix) || {'#', '@', '!', '+', '\$'}.contains(url[0])) { return openMatrixToUrl(); } @@ -24,7 +24,7 @@ class UrlLauncher { void openMatrixToUrl() async { final matrix = Matrix.of(context); - final identifier = url.replaceAll(AppConfig.matrixToLinkPrefix, ''); + final identifier = url.replaceAll(AppConfig.inviteLinkPrefix, ''); if (identifier[0] == '#' || identifier[0] == '!') { // sometimes we have identifiers which have an event id and additional query parameters // we want to separate those. diff --git a/lib/views/chat.dart b/lib/views/chat.dart index d737a89b..27fa6af4 100644 --- a/lib/views/chat.dart +++ b/lib/views/chat.dart @@ -33,7 +33,7 @@ import 'package:swipe_to_action/swipe_to_action.dart'; import '../components/dialogs/send_file_dialog.dart'; import '../components/input_bar.dart'; -import '../config/app_config.dart'; +import '../app_config.dart'; import '../utils/matrix_file_extension.dart'; import 'chat_details.dart'; import 'chat_list.dart'; diff --git a/lib/views/chat_details.dart b/lib/views/chat_details.dart index ecc0852c..e21ac9d0 100644 --- a/lib/views/chat_details.dart +++ b/lib/views/chat_details.dart @@ -1,5 +1,5 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/app_config.dart'; import 'package:fluffychat/utils/fluffy_share.dart'; import 'package:fluffychat/views/chat_permissions_settings.dart'; import 'package:flushbar/flushbar_helper.dart'; @@ -202,7 +202,7 @@ class _ChatDetailsState extends State { IconButton( icon: Icon(Icons.share_outlined), onPressed: () => FluffyShare.share( - AppConfig.matrixToLinkPrefix + + AppConfig.inviteLinkPrefix + widget.room.canonicalAlias, context), ), diff --git a/lib/views/chat_list.dart b/lib/views/chat_list.dart index c90c80f2..a211db76 100644 --- a/lib/views/chat_list.dart +++ b/lib/views/chat_list.dart @@ -7,7 +7,7 @@ import 'package:fluffychat/components/connection_status_header.dart'; import 'package:fluffychat/components/default_app_bar_search_field.dart'; import 'package:fluffychat/components/default_drawer.dart'; import 'package:fluffychat/components/dialogs/simple_dialogs.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/app_config.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -105,7 +105,7 @@ class _ChatListState extends State { if (Navigator.of(context).canPop()) { Navigator.of(context).popUntil((r) => r.isFirst); } - if (text.startsWith(AppConfig.matrixToLinkPrefix)) { + if (text.startsWith(AppConfig.inviteLinkPrefix)) { UrlLauncher(context, text).openMatrixToUrl(); return; } diff --git a/lib/views/homeserver_picker.dart b/lib/views/homeserver_picker.dart index 17bf565e..876e1d48 100644 --- a/lib/views/homeserver_picker.dart +++ b/lib/views/homeserver_picker.dart @@ -4,7 +4,7 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/components/dialogs/simple_dialogs.dart'; import 'package:fluffychat/components/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/app_config.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:fluffychat/utils/app_route.dart'; import 'package:fluffychat/utils/sentry_controller.dart'; @@ -12,6 +12,8 @@ import 'package:fluffychat/views/sign_up.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'login.dart'; + class HomeserverPicker extends StatelessWidget { Future _setHomeserverAction(BuildContext context) async { const prefix = 'https://'; @@ -42,7 +44,8 @@ class HomeserverPicker extends StatelessWidget { final success = await SimpleDialogs(context).tryRequestWithLoadingDialog( checkHomeserver(homeserver, Matrix.of(context).client)); if (success == true) { - await Navigator.of(context).push(AppRoute(SignUp())); + await Navigator.of(context) + .push(AppRoute(AppConfig.enableRegistration ? SignUp() : Login())); } } @@ -61,35 +64,42 @@ class HomeserverPicker extends StatelessWidget { max((MediaQuery.of(context).size.width - 600) / 2, 0)), child: Column( children: [ - Hero( - tag: 'loginBanner', - child: InkWell( - onTap: () => showAboutDialog( - context: context, - children: [ - RaisedButton( - child: Text(L10n.of(context).privacy), - onPressed: () => launch(AppConfig.privacyUrl), - ) - ], - applicationIcon: - Image.asset('assets/logo.png', width: 100, height: 100), - applicationName: AppConfig.applicationName, - ), - child: Image.asset('assets/fluffychat-banner.png'), + Expanded( + child: ListView( + children: [ + Hero( + tag: 'loginBanner', + child: InkWell( + onTap: () => showAboutDialog( + context: context, + children: [ + RaisedButton( + child: Text(L10n.of(context).privacy), + onPressed: () => launch(AppConfig.privacyUrl), + ) + ], + applicationIcon: Image.asset('assets/logo.png', + width: 100, height: 100), + applicationName: AppConfig.applicationName, + ), + child: Image.asset('assets/banner.png'), + ), + ), + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + AppConfig.applicationWelcomeMessage ?? + L10n.of(context).welcomeText, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + ), + ), + ), + ], ), ), - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - L10n.of(context).welcomeText, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - ), - ), - ), - Spacer(), + SizedBox(height: 16), Hero( tag: 'loginButton', child: Container( @@ -123,16 +133,31 @@ class HomeserverPicker extends StatelessWidget { ), ), ), - FlatButton( - child: Text( - L10n.of(context).changeTheHomeserver, - style: TextStyle( - decoration: TextDecoration.underline, - color: Colors.blue, - fontSize: 16, + Wrap( + children: [ + if (AppConfig.allowOtherHomeservers) + FlatButton( + child: Text( + L10n.of(context).changeTheHomeserver, + style: TextStyle( + decoration: TextDecoration.underline, + color: Theme.of(context).primaryColor, + fontSize: 16, + ), + ), + onPressed: () => _setHomeserverAction(context), + ), + FlatButton( + child: Text( + L10n.of(context).privacy, + style: TextStyle( + decoration: TextDecoration.underline, + fontSize: 16, + ), + ), + onPressed: () => launch(AppConfig.privacyUrl), ), - ), - onPressed: () => _setHomeserverAction(context), + ], ), SizedBox(height: 16), ], diff --git a/lib/views/login.dart b/lib/views/login.dart index 664ddbb5..1fd23ec5 100644 --- a/lib/views/login.dart +++ b/lib/views/login.dart @@ -49,7 +49,7 @@ class _LoginState extends State { await matrix.client.login( user: usernameController.text, password: passwordController.text, - initialDeviceDisplayName: matrix.widget.clientName); + initialDeviceDisplayName: matrix.clientName); } on MatrixException catch (exception) { setState(() => passwordError = exception.errorMessage); return setState(() => loading = false); @@ -59,7 +59,7 @@ class _LoginState extends State { } await FirebaseController.setupFirebase( matrix, - matrix.widget.clientName, + matrix.clientName, ).catchError(SentryController.captureException); setState(() => loading = false); diff --git a/lib/views/settings.dart b/lib/views/settings.dart index 67be51c0..492bdadd 100644 --- a/lib/views/settings.dart +++ b/lib/views/settings.dart @@ -7,7 +7,7 @@ import 'package:flushbar/flushbar_helper.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:file_picker_cross/file_picker_cross.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/app_config.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/sentry_controller.dart'; import 'package:fluffychat/views/settings_devices.dart'; @@ -22,7 +22,7 @@ import '../components/content_banner.dart'; import '../components/dialogs/simple_dialogs.dart'; import '../components/matrix.dart'; import '../utils/app_route.dart'; -import '../config/app_config.dart'; +import '../app_config.dart'; import '../config/setting_keys.dart'; import 'app_info.dart'; import 'chat_list.dart'; @@ -141,8 +141,7 @@ class _SettingsState extends State { title: L10n.of(context).editJitsiInstance, textFields: [ DialogTextField( - initialText: - Matrix.of(context).jitsiInstance.replaceFirst(prefix, ''), + initialText: AppConfig.jitsiInstance.replaceFirst(prefix, ''), prefixText: prefix, ), ], @@ -154,7 +153,7 @@ class _SettingsState extends State { } final matrix = Matrix.of(context); await matrix.store.setItem(SettingKeys.jitsiInstance, jitsi); - matrix.jitsiInstance = jitsi; + AppConfig.jitsiInstance = jitsi; } void setDisplaynameAction(BuildContext context) async { @@ -411,7 +410,7 @@ class _SettingsState extends State { ListTile( trailing: Icon(Icons.phone_outlined), title: Text(L10n.of(context).editJitsiInstance), - subtitle: Text(Matrix.of(context).jitsiInstance), + subtitle: Text(AppConfig.jitsiInstance), onTap: () => setJitsiInstanceAction(context), ), ListTile( diff --git a/lib/views/settings_notifications.dart b/lib/views/settings_notifications.dart index 2c809e64..0d936aae 100644 --- a/lib/views/settings_notifications.dart +++ b/lib/views/settings_notifications.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/components/adaptive_page_layout.dart'; import 'package:fluffychat/components/dialogs/simple_dialogs.dart'; -import 'package:fluffychat/utils/firebase_controller.dart'; +import 'package:fluffychat/app_config.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -68,9 +68,9 @@ class SettingsNotifications extends StatelessWidget { await NotificationSetting.configureChannel( NotificationDetails( android: AndroidNotificationDetails( - FirebaseController.CHANNEL_ID, - FirebaseController.CHANNEL_NAME, - FirebaseController.CHANNEL_DESCRIPTION, + AppConfig.pushNotificationsChannelId, + AppConfig.pushNotificationsChannelName, + AppConfig.pushNotificationsChannelDescription, ), ), ); diff --git a/lib/views/sign_up.dart b/lib/views/sign_up.dart index 6988293b..6637a0ab 100644 --- a/lib/views/sign_up.dart +++ b/lib/views/sign_up.dart @@ -90,7 +90,7 @@ class _SignUpState extends State { children: [ Hero( tag: 'loginBanner', - child: Image.asset('assets/fluffychat-banner.png'), + child: Image.asset('assets/banner.png'), ), ListTile( leading: CircleAvatar( diff --git a/lib/views/sign_up_password.dart b/lib/views/sign_up_password.dart index 10fa2cf1..d93a104b 100644 --- a/lib/views/sign_up_password.dart +++ b/lib/views/sign_up_password.dart @@ -44,7 +44,7 @@ class _SignUpPasswordState extends State { await matrix.client.register( username: widget.username, password: passwordController.text, - initialDeviceDisplayName: matrix.widget.clientName, + initialDeviceDisplayName: matrix.clientName, auth: auth, ); await waitForLogin;