feat: Option to hide redacted and unknown events

This commit is contained in:
Sorunome 2020-11-07 12:00:41 +01:00
parent ee1b128d77
commit 36315a45ec
No known key found for this signature in database
GPG Key ID: B19471D07FC9BE9C
16 changed files with 118 additions and 38 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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<Matrix> {
String activeRoomId;
File wallpaper;
bool renderHtml = false;
String jitsiInstance = 'https://meet.jit.si/';
@ -304,18 +305,26 @@ class MatrixState extends State<Matrix> {
}
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);

View File

@ -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'];

View File

@ -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]

View File

@ -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<ThemeSwitcherWidget> {
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<ThemeSwitcherWidget> {
}
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 {

View File

@ -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;
}

View File

@ -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';
}

View File

@ -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",

View File

@ -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<Database> getDatabase(Client client) async {
@ -16,7 +17,7 @@ Future<Database> 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<Database> 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<bool> 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<void> setItem(String key, String value) async {
if (!PlatformInfos.isMobile) {
await _setupLocalStorage();

View File

@ -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;

View File

@ -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<void> 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<bool> getSentryStatus() async {
final storage = Store();
return await storage.getItem('sentry') == 'true';
return await storage.getItemBool(SettingKeys.sentry);
}
static final sentry = SentryClient(dsn: AppConfig.sentryDsn);

View File

@ -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<Event> 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

View File

@ -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<Settings> {
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<Settings> {
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<Settings> {
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);
},
),

View File

@ -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"

View File

@ -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