diff --git a/lib/components/html_message.dart b/lib/components/html_message.dart
index a67377a0..9139cf0b 100644
--- a/lib/components/html_message.dart
+++ b/lib/components/html_message.dart
@@ -2,6 +2,7 @@ import 'package:famedlysdk/famedlysdk.dart';
import 'package:flutter_matrix_html/flutter_html.dart';
import 'package:flutter/material.dart';
import '../utils/url_launcher.dart';
+import '../config/setting_keys.dart';
import 'matrix.dart';
@@ -59,10 +60,10 @@ class HtmlMessage extends StatelessWidget {
);
},
setCodeLanguage: (String key, String value) async {
- await matrix.store.setItem('code_language.$key', value);
+ await matrix.store.setItem('${SettingKeys.codeLanguage}.$key', value);
},
getCodeLanguage: (String key) async {
- return await matrix.store.getItem('code_language.$key');
+ return await matrix.store.getItem('${SettingKeys.codeLanguage}.$key');
},
getPillInfo: (String identifier) async {
if (room == null) {
diff --git a/lib/components/list_items/message.dart b/lib/components/list_items/message.dart
index 145e46de..5e99962d 100644
--- a/lib/components/list_items/message.dart
+++ b/lib/components/list_items/message.dart
@@ -72,9 +72,6 @@ class Message extends StatelessWidget {
@override
Widget build(BuildContext context) {
- if (event.type == EventTypes.Unknown) {
- return Container();
- }
if (![EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted]
.contains(event.type)) {
return StateMessage(event);
diff --git a/lib/components/matrix.dart b/lib/components/matrix.dart
index 4f359959..c895daa1 100644
--- a/lib/components/matrix.dart
+++ b/lib/components/matrix.dart
@@ -23,6 +23,8 @@ import '../utils/beautify_string_extension.dart';
import '../utils/famedlysdk_store.dart';
import '../views/key_verification.dart';
import '../utils/platform_infos.dart';
+import '../config/app_config.dart';
+import '../config/setting_keys.dart';
import 'avatar.dart';
class Matrix extends StatefulWidget {
@@ -72,7 +74,6 @@ class MatrixState extends State {
String activeRoomId;
File wallpaper;
- bool renderHtml = false;
String jitsiInstance = 'https://meet.jit.si/';
@@ -304,18 +305,26 @@ class MatrixState extends State {
}
if (store != null) {
store
- .getItem('chat.fluffy.jitsi_instance')
+ .getItem(SettingKeys.jitsiInstance)
.then((final instance) => jitsiInstance = instance ?? jitsiInstance);
- store.getItem('chat.fluffy.wallpaper').then((final path) async {
+ store.getItem(SettingKeys.wallpaper).then((final path) async {
if (path == null) return;
final file = File(path);
if (await file.exists()) {
wallpaper = file;
}
});
- store.getItem('chat.fluffy.renderHtml').then((final render) async {
- renderHtml = render == '1';
- });
+ store
+ .getItemBool(SettingKeys.renderHtml, AppConfig.renderHtml)
+ .then((value) => AppConfig.renderHtml = value);
+ store
+ .getItemBool(
+ SettingKeys.hideRedactedEvents, AppConfig.hideRedactedEvents)
+ .then((value) => AppConfig.hideRedactedEvents = value);
+ store
+ .getItemBool(
+ SettingKeys.hideUnknownEvents, AppConfig.hideUnknownEvents)
+ .then((value) => AppConfig.hideUnknownEvents = value);
}
if (kIsWeb) {
onFocusSub = html.window.onFocus.listen((_) => webHasFocus = true);
diff --git a/lib/components/message_content.dart b/lib/components/message_content.dart
index 3909a764..a28c15c3 100644
--- a/lib/components/message_content.dart
+++ b/lib/components/message_content.dart
@@ -9,6 +9,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 'html_message.dart';
import 'matrix.dart';
import 'message_download_content.dart';
@@ -43,7 +44,7 @@ class MessageContent extends StatelessWidget {
case MessageTypes.Text:
case MessageTypes.Notice:
case MessageTypes.Emote:
- if (Matrix.of(context).renderHtml &&
+ if (AppConfig.renderHtml &&
!event.redacted &&
event.isRichMessage) {
String html = event.content['formatted_body'];
diff --git a/lib/components/reply_content.dart b/lib/components/reply_content.dart
index 1ebc3b0f..bf3651eb 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 'matrix.dart';
+import '../config/app_config.dart';
class ReplyContent extends StatelessWidget {
final Event replyEvent;
@@ -22,7 +22,7 @@ class ReplyContent extends StatelessWidget {
? replyEvent.getDisplayEvent(timeline)
: replyEvent;
if (displayEvent != null &&
- Matrix.of(context).renderHtml &&
+ AppConfig.renderHtml &&
[EventTypes.Message, EventTypes.Encrypted]
.contains(displayEvent.type) &&
[MessageTypes.Text, MessageTypes.Notice, MessageTypes.Emote]
diff --git a/lib/components/theme_switcher.dart b/lib/components/theme_switcher.dart
index dafdd4cc..1284d758 100644
--- a/lib/components/theme_switcher.dart
+++ b/lib/components/theme_switcher.dart
@@ -1,6 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'matrix.dart';
+import '../config/setting_keys.dart';
enum Themes {
light,
@@ -175,14 +176,12 @@ class ThemeSwitcherWidgetState extends State {
BuildContext context;
Future loadSelection(MatrixState matrix) async {
- var item = await matrix.store.getItem('theme') ?? 'system';
+ var item = await matrix.store.getItem(SettingKeys.theme) ?? 'system';
selectedTheme = Themes.values.firstWhere(
(e) => e.toString() == 'Themes.' + item,
orElse: () => Themes.system);
- amoledEnabled = (await matrix.store.getItem('amoled_enabled') ?? 'false')
- .toLowerCase() ==
- 'true';
+ amoledEnabled = await matrix.store.getItemBool(SettingKeys.amoledEnabled);
switchTheme(matrix, selectedTheme, amoledEnabled);
return;
@@ -229,11 +228,12 @@ class ThemeSwitcherWidgetState extends State {
}
Future saveThemeValue(MatrixState matrix, Themes value) async {
- await matrix.store.setItem('theme', value.toString().split('.').last);
+ await matrix.store
+ .setItem(SettingKeys.theme, value.toString().split('.').last);
}
Future saveAmoledEnabledValue(MatrixState matrix, bool value) async {
- await matrix.store.setItem('amoled_enabled', value.toString());
+ await matrix.store.setItem(SettingKeys.amoledEnabled, value.toString());
}
void setup() async {
diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart
index a0c98cec..a2e4320f 100644
--- a/lib/config/app_config.dart
+++ b/lib/config/app_config.dart
@@ -8,4 +8,7 @@ abstract class AppConfig {
'https://gitlab.com/ChristianPauly/fluffychat-flutter/issues';
static const String sentryDsn =
'https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143';
+ static bool renderHtml = false;
+ static bool hideRedactedEvents = false;
+ static bool hideUnknownEvents = false;
}
diff --git a/lib/config/setting_keys.dart b/lib/config/setting_keys.dart
new file mode 100644
index 00000000..08c8ecb2
--- /dev/null
+++ b/lib/config/setting_keys.dart
@@ -0,0 +1,13 @@
+abstract class SettingKeys {
+ static const String jitsiInstance = 'chat.fluffy.jitsi_instance';
+ static const String wallpaper = 'chat.fluffy.wallpaper';
+ static const String renderHtml = 'chat.fluffy.renderHtml';
+ static const String hideRedactedEvents = 'chat.fluffy.hideRedactedEvents';
+ static const String hideUnknownEvents = 'chat.fluffy.hideUnknownEvents';
+ static const String sentry = 'sentry';
+ static const String theme = 'theme';
+ static const String amoledEnabled = 'amoled_enabled';
+ static const String codeLanguage = 'code_language';
+ static const String showNoGoogle = 'chat.fluffy.show_no_google';
+ static const String databasePassword = 'database-password';
+}
diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb
index 94237671..46f8aa0d 100644
--- a/lib/l10n/intl_en.arb
+++ b/lib/l10n/intl_en.arb
@@ -681,6 +681,16 @@
"type": "text",
"placeholders": {}
},
+ "hideRedactedEvents": "Hide redacted events",
+ "@hideRedactedEvents": {
+ "type": "text",
+ "placeholders": {}
+ },
+ "hideUnknownEvents": "Hide unknown events",
+ "@hideUnknownEvents": {
+ "type": "text",
+ "placeholders": {}
+ },
"homeserverIsNotCompatible": "Homeserver is not compatible",
"@homeserverIsNotCompatible": {
"type": "text",
diff --git a/lib/utils/famedlysdk_store.dart b/lib/utils/famedlysdk_store.dart
index 34232e59..0ce242d8 100644
--- a/lib/utils/famedlysdk_store.dart
+++ b/lib/utils/famedlysdk_store.dart
@@ -6,6 +6,7 @@ import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'dart:core';
import './database/shared.dart';
+import '../config/setting_keys.dart';
import 'package:random_string/random_string.dart';
Future getDatabase(Client client) async {
@@ -16,7 +17,7 @@ Future getDatabase(Client client) async {
try {
if (_db != null) return _db;
final store = Store();
- var password = await store.getItem('database-password');
+ var password = await store.getItem(SettingKeys.databasePassword);
var newPassword = false;
if (password == null || password.isEmpty) {
newPassword = true;
@@ -28,7 +29,7 @@ Future getDatabase(Client client) async {
password: password,
);
if (newPassword) {
- await store.setItem('database-password', password);
+ await store.setItem(SettingKeys.databasePassword, password);
}
return _db;
} finally {
@@ -74,6 +75,15 @@ class Store {
}
}
+ Future getItemBool(String key, [bool defaultValue]) async {
+ final value = await getItem(key);
+ if (value == null) {
+ return defaultValue ?? false;
+ }
+ // we also check for '1' for legacy reasons, some booleans were stored that way
+ return value == '1' || value.toLowerCase() == 'true';
+ }
+
Future setItem(String key, String value) async {
if (!PlatformInfos.isMobile) {
await _setupLocalStorage();
diff --git a/lib/utils/firebase_controller.dart b/lib/utils/firebase_controller.dart
index 02c12467..859bbd38 100644
--- a/lib/utils/firebase_controller.dart
+++ b/lib/utils/firebase_controller.dart
@@ -15,6 +15,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:path_provider/path_provider.dart';
import '../components/matrix.dart';
+import '../config/setting_keys.dart';
import 'famedlysdk_store.dart';
import 'matrix_locals.dart';
@@ -42,8 +43,7 @@ abstract class FirebaseController {
token = null;
}
if (token?.isEmpty ?? true) {
- final storeItem =
- await matrix.store.getItem('chat.fluffy.show_no_google');
+ final storeItem = await matrix.store.getItem(SettingKeys.showNoGoogle);
final configOptionMissing = storeItem == null || storeItem.isEmpty;
if (configOptionMissing || (!configOptionMissing && storeItem == '1')) {
BotToast.showText(
@@ -51,7 +51,7 @@ abstract class FirebaseController {
duration: Duration(seconds: 15),
);
if (configOptionMissing) {
- await matrix.store.setItem('chat.fluffy.show_no_google', '0');
+ await matrix.store.setItem(SettingKeys.showNoGoogle, '0');
}
}
return;
diff --git a/lib/utils/sentry_controller.dart b/lib/utils/sentry_controller.dart
index 8cebc6c1..a152a4e4 100644
--- a/lib/utils/sentry_controller.dart
+++ b/lib/utils/sentry_controller.dart
@@ -7,6 +7,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:sentry/sentry.dart';
import 'famedlysdk_store.dart';
+import '../config/setting_keys.dart';
abstract class SentryController {
static Future toggleSentryAction(BuildContext context) async {
@@ -17,14 +18,14 @@ abstract class SentryController {
cancelText: L10n.of(context).no,
);
final storage = Store();
- await storage.setItem('sentry', enableSentry.toString());
+ await storage.setItem(SettingKeys.sentry, enableSentry.toString());
BotToast.showText(text: L10n.of(context).changesHaveBeenSaved);
return;
}
static Future getSentryStatus() async {
final storage = Store();
- return await storage.getItem('sentry') == 'true';
+ return await storage.getItemBool(SettingKeys.sentry);
}
static final sentry = SentryClient(dsn: AppConfig.sentryDsn);
diff --git a/lib/views/chat.dart b/lib/views/chat.dart
index 49aa2d1f..92d20aa9 100644
--- a/lib/views/chat.dart
+++ b/lib/views/chat.dart
@@ -34,6 +34,7 @@ import 'package:swipe_to_action/swipe_to_action.dart';
import '../components/dialogs/send_file_dialog.dart';
import '../components/input_bar.dart';
import '../utils/matrix_file_extension.dart';
+import '../config/app_config.dart';
import 'chat_details.dart';
import 'chat_list.dart';
@@ -411,9 +412,15 @@ class _ChatState extends State<_Chat> {
List getFilteredEvents() => timeline.events
.where((e) =>
- ![RelationshipTypes.Edit, RelationshipTypes.Reaction]
+ // always filter out edit and reaction relationships
+ !{RelationshipTypes.Edit, RelationshipTypes.Reaction}
.contains(e.relationshipType) &&
- e.type != 'm.reaction')
+ // if a reaction has been redacted we also want it to appear in the timeline
+ e.type != EventTypes.Reaction &&
+ // if we enabled to hide all redacted events, don't show those
+ (!AppConfig.hideRedactedEvents || !e.redacted) &&
+ // if we enabled to hide all unknown events, don't show those
+ (!AppConfig.hideUnknownEvents || e.isEventTypeKnown))
.toList();
@override
diff --git a/lib/views/settings.dart b/lib/views/settings.dart
index bd4d4a54..ce62e6c2 100644
--- a/lib/views/settings.dart
+++ b/lib/views/settings.dart
@@ -21,6 +21,8 @@ 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 '../config/setting_keys.dart';
import 'app_info.dart';
import 'chat_list.dart';
import 'settings_emotes.dart';
@@ -115,7 +117,7 @@ class _SettingsState extends State {
jitsi += '/';
}
final matrix = Matrix.of(context);
- await matrix.store.setItem('chat.fluffy.jitsi_instance', jitsi);
+ await matrix.store.setItem(SettingKeys.jitsiInstance, jitsi);
matrix.jitsiInstance = jitsi;
}
@@ -179,13 +181,13 @@ class _SettingsState extends State {
Matrix.of(context).wallpaper = File(wallpaper.path);
await Matrix.of(context)
.store
- .setItem('chat.fluffy.wallpaper', wallpaper.path);
+ .setItem(SettingKeys.wallpaper, wallpaper.path);
setState(() => null);
}
void deleteWallpaperAction(BuildContext context) async {
Matrix.of(context).wallpaper = null;
- await Matrix.of(context).store.deleteItem('chat.fluffy.wallpaper');
+ await Matrix.of(context).store.deleteItem(SettingKeys.wallpaper);
setState(() => null);
}
@@ -340,13 +342,39 @@ class _SettingsState extends State {
ListTile(
title: Text(L10n.of(context).renderRichContent),
trailing: Switch(
- value: Matrix.of(context).renderHtml,
+ value: AppConfig.renderHtml,
activeColor: Theme.of(context).primaryColor,
onChanged: (bool newValue) async {
- Matrix.of(context).renderHtml = newValue;
+ AppConfig.renderHtml = newValue;
await Matrix.of(context)
.store
- .setItem('chat.fluffy.renderHtml', newValue ? '1' : '0');
+ .setItem(SettingKeys.renderHtml, newValue.toString());
+ setState(() => null);
+ },
+ ),
+ ),
+ ListTile(
+ title: Text(L10n.of(context).hideRedactedEvents),
+ trailing: Switch(
+ value: AppConfig.hideRedactedEvents,
+ activeColor: Theme.of(context).primaryColor,
+ onChanged: (bool newValue) async {
+ AppConfig.hideRedactedEvents = newValue;
+ await Matrix.of(context).store.setItem(
+ SettingKeys.hideRedactedEvents, newValue.toString());
+ setState(() => null);
+ },
+ ),
+ ),
+ ListTile(
+ title: Text(L10n.of(context).hideUnknownEvents),
+ trailing: Switch(
+ value: AppConfig.hideUnknownEvents,
+ activeColor: Theme.of(context).primaryColor,
+ onChanged: (bool newValue) async {
+ AppConfig.hideUnknownEvents = newValue;
+ await Matrix.of(context).store.setItem(
+ SettingKeys.hideUnknownEvents, newValue.toString());
setState(() => null);
},
),
diff --git a/pubspec.lock b/pubspec.lock
index 59f4c789..df5a2261 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -208,8 +208,8 @@ packages:
dependency: "direct main"
description:
path: "."
- ref: "15d817023d34f813e95eba6ca8c71c575b8c2457"
- resolved-ref: "15d817023d34f813e95eba6ca8c71c575b8c2457"
+ ref: "66572bd03209c1c6488cde53a0c72c11faef341d"
+ resolved-ref: "66572bd03209c1c6488cde53a0c72c11faef341d"
url: "https://gitlab.com/famedly/famedlysdk.git"
source: git
version: "0.0.1"
diff --git a/pubspec.yaml b/pubspec.yaml
index d14e03d0..9389847f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -23,7 +23,7 @@ dependencies:
famedlysdk:
git:
url: https://gitlab.com/famedly/famedlysdk.git
- ref: 15d817023d34f813e95eba6ca8c71c575b8c2457
+ ref: 66572bd03209c1c6488cde53a0c72c11faef341d
localstorage: ^3.0.3+6
file_picker_cross: 4.2.2