diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e61e4d42..61393c74 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,15 +34,7 @@ build_web: script: - sudo apt update - sudo apt install curl -y - - rm -r assets/js/package - - cd assets/js/ && curl -L 'https://gitlab.com/famedly/libraries/olm/-/jobs/artifacts/master/download?job=build_js' > olm.zip && cd ../../ - - cd assets/js/ && unzip olm.zip && cd ../../ - - cd assets/js/ && rm olm.zip && cd ../../ - - cd assets/js/ && mv javascript package && cd ../../ - - cd web/ && rm sql-wasm.js sql-wasm.wasm && cd ../ - - cd web/ && curl -L 'https://github.com/sql-js/sql.js/releases/latest/download/sqljs-wasm.zip' > sqljs-wasm.zip && cd ../ - - cd web/ && unzip sqljs-wasm.zip && cd ../ - - cd web/ && rm sqljs-wasm.zip && cd ../ + - ./scripts/prepare-web.sh - flutter clean - flutter pub get - flutter build web --release --verbose @@ -216,7 +208,7 @@ snap:edge: - './*.snap' when: on_success allow_failure: true - + snap:publish: stage: publish image: "cibuilds/snapcraft:core18" diff --git a/README.md b/README.md index d7342ebc..285cf234 100644 --- a/README.md +++ b/README.md @@ -67,14 +67,25 @@ sudo apt install ninja-build * Enable web support in Flutter: https://flutter.dev/docs/get-started/web -* Build with: `flutter build web --release` +* Build with: +```bash +./scripts/prepare-web.sh +flutter clean +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 -* Build with one of these: -``` +* Build with one of these: +```bash flutter build linux --release flutter build windows --release flutter build macos --release diff --git a/config.sample.json b/config.sample.json new file mode 100644 index 00000000..fad342e3 --- /dev/null +++ b/config.sample.json @@ -0,0 +1,11 @@ +{ + "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/components/matrix.dart b/lib/components/matrix.dart index 0b02989b..f6e9cf7f 100644 --- a/lib/components/matrix.dart +++ b/lib/components/matrix.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:io'; +import 'dart:convert'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:famedlysdk/encryption.dart'; @@ -13,6 +14,7 @@ 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:dbus/dbus.dart'; @@ -27,6 +29,8 @@ import '../config/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'; @@ -227,6 +231,38 @@ class MatrixState extends State { @override 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(); if (widget.client == null) { debugPrint('[Matrix] Init matrix client'); @@ -307,6 +343,25 @@ class MatrixState extends State { client = widget.client; client.connect(); } + if (kIsWeb) { + onFocusSub = html.window.onFocus.listen((_) => webHasFocus = true); + onBlurSub = html.window.onBlur.listen((_) => webHasFocus = false); + } + if (kIsWeb || Platform.isLinux) { + client.onSync.stream.first.then((s) { + html.Notification.requestPermission(); + onNotification ??= client.onEvent.stream + .where((e) => + e.type == EventUpdateType.timeline && + [EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted] + .contains(e.eventType) && + e.content['sender'] != client.userID) + .listen(_showLocalNotification); + }); + } + } + + void initSettings() { if (store != null) { store .getItem(SettingKeys.jitsiInstance) @@ -330,23 +385,6 @@ class MatrixState extends State { SettingKeys.hideUnknownEvents, AppConfig.hideUnknownEvents) .then((value) => AppConfig.hideUnknownEvents = value); } - if (kIsWeb) { - onFocusSub = html.window.onFocus.listen((_) => webHasFocus = true); - onBlurSub = html.window.onBlur.listen((_) => webHasFocus = false); - } - if (kIsWeb || Platform.isLinux) { - client.onSync.stream.first.then((s) { - html.Notification.requestPermission(); - onNotification ??= client.onEvent.stream - .where((e) => - e.type == EventUpdateType.timeline && - [EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted] - .contains(e.eventType) && - e.content['sender'] != client.userID) - .listen(_showLocalNotification); - }); - } - super.initState(); } @override diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index a2e4320f..14d7799e 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -1,14 +1,51 @@ abstract class AppConfig { - static const String applicationName = 'FluffyChat'; - static const String defaultHomeserver = 'matrix.tchncs.de'; - static const String privacyUrl = 'https://fluffychat.im/en/privacy.html'; - static const String sourceCodeUrl = + static String get applicationName => _applicationName; + static String _applicationName = 'FluffyChat'; + static String get defaultHomeserver => _defaultHomeserver; + static String _defaultHomeserver = 'matrix.tchncs.de'; + 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 const String supportUrl = + static String get supportUrl => _supportUrl; + static String _supportUrl = 'https://gitlab.com/ChristianPauly/fluffychat-flutter/issues'; - static const String sentryDsn = + 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 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/scripts/prepare-web.sh b/scripts/prepare-web.sh new file mode 100755 index 00000000..2ec48bf5 --- /dev/null +++ b/scripts/prepare-web.sh @@ -0,0 +1,10 @@ +#!/bin/bash +rm -r assets/js/package +cd assets/js/ && curl -L 'https://gitlab.com/famedly/libraries/olm/-/jobs/artifacts/master/download?job=build_js' > olm.zip && cd ../../ +cd assets/js/ && unzip olm.zip && cd ../../ +cd assets/js/ && rm olm.zip && cd ../../ +cd assets/js/ && mv javascript package && cd ../../ +cd web/ && rm sql-wasm.js sql-wasm.wasm && cd ../ +cd web/ && curl -L 'https://github.com/sql-js/sql.js/releases/latest/download/sqljs-wasm.zip' > sqljs-wasm.zip && cd ../ +cd web/ && unzip sqljs-wasm.zip && cd ../ +cd web/ && rm sqljs-wasm.zip && cd ../