Skip to content
Merged
3 changes: 3 additions & 0 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,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 @@ -93,6 +94,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 @@ -199,6 +201,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 @@ -101,6 +101,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 @@ -162,6 +164,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 @@ -200,6 +203,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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the functionality expected behind this one?

Copy link
Copy Markdown
Collaborator Author

@EdGeraghty EdGeraghty Sep 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Purely defensive. The only two in the spec (on and private) + Off are handled above it. Feel free to patch out as wanted, it's on origin

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note this is purely to handle string translation

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 @@ -733,10 +733,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