Skip to content

Commit

Permalink
Merge pull request syphon-org#717 from syphon-org/spec/msc2285-stable
Browse files Browse the repository at this point in the history
[Spec] MSC2285 Stable/Unstable crossover period support
  • Loading branch information
Ed Geraghty authored Sep 11, 2022
2 parents 4de04fd + d55cbfd commit 142adb5
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 19 deletions.
3 changes: 3 additions & 0 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"subtitle-proxy-use-basic-authentication": "Provide username and password to authenticate with a proxy",
"subtitle-settings-sync-interval": "Amount of time in seconds the app wait\nbetween syncing",
"subtitle-settings-sync-toggle": "Toggle syncing with the matrix server",
"subtitle-settings-read-receipts": "If read receipts are disabled or private, other users will not be able to see when you have read their messages.",
"subtitle-toggle-autocorrect": "Beware that keyboards may send autocorrect data to third-parties",
"subtitle-toggle-suggestions": "Beware that keyboards may send suggestions data to third-parties",
"subtitle-settings-show-membership-events": "Show membership changes within the chat",
Expand All @@ -94,6 +95,7 @@
"label-syncing-chats": "syncing chats…",
"label-on": "On",
"label-off": "Off",
"label-private": "Private",
"label-email": "Email",
"label-users": "Users",
"label-back": "Go Back",
Expand Down Expand Up @@ -200,6 +202,7 @@
"list-item-settings-proxy-password": "Proxy Password",
"list-item-settings-sync-interval": "Sync Interval",
"list-item-settings-sync-toggle": "Toggle Syncing",
"list-item-settings-read-receipts": "Read Receipts",
"list-item-settings-language": "Language",
"list-item-settings-show-membership-events": "Show Membership Events",
"list-item-settings-enter-sends": "Enter Key Sends",
Expand Down
14 changes: 8 additions & 6 deletions lib/global/libs/matrix/events/requests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -396,20 +396,22 @@ abstract class Events {
return await json.decode(response.body);
}

/// Send Hidden Read Receipt - unstable feature
/// Send Hidden Read Receipt
///
/// https://github.com/matrix-org/matrix-spec-proposals/blob/travis/msc/hidden-read-receipts/proposals/2285-hidden-read-receipts.md
static Future<dynamic> sendReadMarkerHidden({
/// https://github.com/matrix-org/matrix-spec-proposals/pull/2285
static Future<dynamic> sendPrivateReadMarker({
String? protocol = 'https://',
String? homeserver = Values.homeserverDefault,
String? accessToken,
String? roomId,
String? messageId,
String? lastRead,
bool readAll = true,
@Deprecated('Due to be unsupported as of Synapse v1.67.0')
bool stable = true,
}) async {
final String url =
'$protocol$homeserver/_matrix/client/r0/rooms/$roomId/receipt/m.read.private/$messageId';
'$protocol$homeserver/_matrix/client/v3/rooms/$roomId/receipt/'
'${stable ? 'm.read.private' : 'org.matrix.msc2285.read.private'}' //@deprecated
'/$messageId';

final Map<String, String> headers = {
'Authorization': 'Bearer $accessToken',
Expand Down
2 changes: 1 addition & 1 deletion lib/global/libs/matrix/index.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ abstract class MatrixApi {
static const sendMessage = Events.sendMessage;
static const sendReaction = Events.sendReaction;
static const sendReadReceipts = Events.sendReadMarkers;
static const sendReadReceiptHidden = Events.sendReadMarkerHidden;
static const sendPrivateReadReceipt = Events.sendPrivateReadMarker;
static const sendEventToDevice = Events.sendEventToDevice;
static const sendMessageEncrypted = Events.sendMessageEncrypted;
static const fetchStateEvents = Events.fetchStateEvents;
Expand Down
5 changes: 5 additions & 0 deletions lib/global/strings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ class Strings {
static final subtitleSettingsSyncInterval =
tr('subtitle-settings-sync-interval');
static final subtitleSettingsSyncToggle = tr('subtitle-settings-sync-toggle');
static final subtitleSettingsReadReceipts =
tr('subtitle-settings-read-receipts');
static final subtitleToggleAutocorrect = tr('subtitle-toggle-autocorrect');
static final subtitleToggleSuggestions = tr('subtitle-toggle-suggestions');
static final subtitleShowMembershipEvents =
Expand Down Expand Up @@ -165,6 +167,7 @@ class Strings {
tr('label-deleted-message'); // 'This message was deleted';
static final labelOn = tr('label-on'); // 'On';
static final labelOff = tr('label-off'); // 'Off';
static final labelPrivate = tr('label-private');
static final labelTermsOfService = tr('label-terms-of-service');
static final labelSearchUnencrypted = tr('label-search-unencrypted');
static final labelAbout = tr('label-about');
Expand Down Expand Up @@ -203,6 +206,8 @@ class Strings {
tr('list-item-settings-sync-interval');
static final listItemSettingsSyncToggle =
tr('list-item-settings-sync-toggle');
static final listItemSettingsReadReceipts =
tr('list-item-settings-read-receipts');

static final listItemSettingsLanguage = tr('list-item-settings-language');
static final listItemSettingsShowMembershipEvents =
Expand Down
11 changes: 7 additions & 4 deletions lib/store/events/receipts/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:syphon/store/events/messages/model.dart';
import 'package:syphon/store/events/receipts/model.dart';
import 'package:syphon/store/index.dart';
import 'package:syphon/store/rooms/room/model.dart';
import 'package:syphon/store/settings/actions.dart';
import 'package:syphon/store/settings/models.dart';

class SetReceipts {
Expand Down Expand Up @@ -40,22 +41,24 @@ ThunkAction<AppState> sendReadReceipts({
}) {
return (Store<AppState> store) async {
try {
// Skip if typing indicators are disabled
// Skip if Read Receipts are disabled
if (store.state.settingsStore.readReceipts == ReadReceiptTypes.Off) {
return log.info('[sendReadReceipts] read receipts disabled');
}

final data;

if (store.state.settingsStore.readReceipts == ReadReceiptTypes.Hidden) {
log.info('[sendReadReceipts] read receipts hidden');
if (store.state.settingsStore.readReceipts == ReadReceiptTypes.Private) {
log.info('[sendReadReceipts] read receipts set to private');

data = await MatrixApi.sendReadReceiptHidden(
data = await MatrixApi.sendPrivateReadReceipt(
protocol: store.state.authStore.protocol,
accessToken: store.state.authStore.user.accessToken,
homeserver: store.state.authStore.user.homeserver,
roomId: room!.id,
messageId: message!.id,
stable:
await homeserverSupportsPrivateReadReceipts(store), //@deprecated
);
} else {
data = await MatrixApi.sendReadReceipts(
Expand Down
26 changes: 22 additions & 4 deletions lib/store/settings/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,24 @@ ThunkAction<AppState> incrementLanguage() {
};
}

Future<bool> homeserverSupportsHiddenReadReceipts(Store<AppState> store) async {
Future<bool> homeserverSupportsPrivateReadReceipts(
Store<AppState> store) async {
final version = await MatrixApi.checkVersion(
protocol: store.state.authStore.protocol,
homeserver: store.state.authStore.user.homeserver,
);

final unstableFeatures = version['unstable_features'];

//TODO: update when this hits a spec version
return unstableFeatures != null &&
unstableFeatures.containsKey('org.matrix.msc2285.stable') &&
unstableFeatures['org.matrix.msc2285.stable'];
}

@Deprecated('Due to be unsupported as of Synapse v1.67.0')
Future<bool> homeserverSupportsUnstablePrivateReadReceipts(
Store<AppState> store) async {
final version = await MatrixApi.checkVersion(
protocol: store.state.authStore.protocol,
homeserver: store.state.authStore.user.homeserver,
Expand All @@ -263,16 +280,17 @@ ThunkAction<AppState> incrementReadReceipts() {
final nextReceipt = ReadReceiptTypes
.values[(readReceiptsIndex + 1) % ReadReceiptTypes.values.length];

if (nextReceipt != ReadReceiptTypes.Hidden) {
if (nextReceipt != ReadReceiptTypes.Private) {
//short-out
return store.dispatch(SetReadReceipts(
readReceipts: nextReceipt,
));
}

if (await homeserverSupportsHiddenReadReceipts(store)) {
if (await homeserverSupportsPrivateReadReceipts(store) ||
await homeserverSupportsUnstablePrivateReadReceipts(store)) {
return store.dispatch(SetReadReceipts(
readReceipts: ReadReceiptTypes.Hidden,
readReceipts: ReadReceiptTypes.Private,
));
}

Expand Down
2 changes: 1 addition & 1 deletion lib/store/settings/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ enum TimeFormat {

enum ReadReceiptTypes {
Off,
Hidden,
Private,
On,
}
12 changes: 11 additions & 1 deletion lib/store/settings/theme-settings/selectors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
import 'package:syphon/global/algos.dart';

import 'package:syphon/global/colors.dart';
import 'package:syphon/global/strings.dart';
import 'package:syphon/store/settings/models.dart';
import 'model.dart';

Expand Down Expand Up @@ -220,7 +221,16 @@ double? selectAppBarElevation(ThemeType themeTypeNew) {
}

String selectReadReceiptsString(ReadReceiptTypes readReceipts) {
return enumToString(readReceipts);
switch (readReceipts) {
case ReadReceiptTypes.On:
return Strings.labelOn;
case ReadReceiptTypes.Off:
return Strings.labelOff;
case ReadReceiptTypes.Private:
return Strings.labelPrivate;
default: //I've not been coded for this one yet
return readReceipts.name;
}
}

String selectFontNameString(FontName fontName) {
Expand Down
4 changes: 2 additions & 2 deletions lib/views/home/settings/settings-privacy-screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -734,10 +734,10 @@ class PrivacySettingsScreen extends hooks.HookWidget {
onTap: () => props.onIncrementReadReceipts(),
contentPadding: Dimensions.listPadding,
title: Text(
'Read Receipts',
Strings.listItemSettingsReadReceipts,
),
subtitle: Text(
'If read receipts are disabled or hidden, users will not see solid read indicators for your messages.',
Strings.subtitleSettingsReadReceipts,
style: Theme.of(context).textTheme.caption,
),
trailing: Text(props.readReceipts),
Expand Down

0 comments on commit 142adb5

Please sign in to comment.