feature: allow marking rooms as unread

This commit is contained in:
Marcus Hoffmann 2020-11-21 19:56:20 +01:00
parent b903930b01
commit 9b3f9e4ef7
4 changed files with 87 additions and 8 deletions

View File

@ -0,0 +1,43 @@
/*
* Famedly Matrix SDK
* Copyright (C) 2019, 2020 Famedly GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
mixin EventType {
static const String MarkedUnread = 'com.famedly.marked_unread';
}
class MarkedUnread {
bool unread;
MarkedUnread(this.unread);
MarkedUnread.fromJson(Map<String, dynamic> json) {
if (!(json['unread'] is bool)) {
unread = false;
} else {
unread = json['unread'];
}
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
if (unread != null) {
data['unread'] = unread;
}
return data;
}
}

View File

@ -18,6 +18,7 @@
import 'dart:async';
import 'package:famedlysdk/matrix_api/model/marked_unread.dart';
import 'package:famedlysdk/src/utils/tombstone_content.dart';
import 'package:html_unescape/html_unescape.dart';
import 'package:matrix_file_e2ee/matrix_file_e2ee.dart';
@ -40,6 +41,7 @@ enum PushRuleState { notify, mentions_only, dont_notify }
enum JoinRules { public, knock, invite, private }
enum GuestAccess { can_join, forbidden }
enum HistoryVisibility { invited, joined, shared, world_readable }
const String MessageSendingStatusKey =
'com.famedly.famedlysdk.message_sending_status';
@ -176,7 +178,7 @@ class Room {
? states[EventTypes.RoomName].content['name']
: '';
/// The pinned events for this room. If there are no this returns an empty
/// The pinned events for this room. If there are none this returns an empty
/// list.
List<String> get pinnedEventIds => states[EventTypes.RoomPinnedEvents] != null
? (states[EventTypes.RoomPinnedEvents].content['pinned'] is List<String>
@ -427,6 +429,24 @@ class Room {
return tags;
}
bool get markedUnread {
return MarkedUnread.fromJson(
roomAccountData[EventType.MarkedUnread]?.content ?? {})
.unread;
}
/// Returns true if this room is unread
bool get isUnread => notificationCount > 0 || markedUnread;
Future<void> setUnread(bool unread) async {
await client.setRoomAccountData(
client.userID,
id,
EventType.MarkedUnread,
MarkedUnread(unread).toJson(),
);
}
/// Returns true if this room has a m.favourite tag.
bool get isFavourite => tags[TagType.Favourite] != null;
@ -973,7 +993,8 @@ class Room {
/// Returns a Room from a json String which comes normally from the store. If the
/// state are also given, the method will await them.
static Future<Room> getRoomFromTableRow(
DbRoom row, // either Map<String, dynamic> or DbRoom
// either Map<String, dynamic> or DbRoom
DbRoom row,
Client matrix, {
dynamic states, // DbRoomState, as iterator and optionally as future
dynamic
@ -985,7 +1006,8 @@ class Room {
.firstWhere((e) => e.toString() == 'Membership.' + row.membership),
notificationCount: row.notificationCount,
highlightCount: row.highlightCount,
notificationSettings: 'mention', // TODO: do proper things
// TODO: do proper things
notificationSettings: 'mention',
prev_batch: row.prevBatch,
mInvitedMemberCount: row.invitedMemberCount,
mJoinedMemberCount: row.joinedMemberCount,

View File

@ -2040,6 +2040,8 @@ class FakeMatrixApi extends MockClient {
(var req) => {},
'/client/r0/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data':
(var req) => {},
'/client/r0/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/account_data/com.famedly.marked_unread':
(var req) => {},
'/client/r0/user/%40test%3AfakeServer.notExisting/account_data/m.direct':
(var req) => {},
'/client/r0/user/%40othertest%3AfakeServer.notExisting/account_data/m.direct':

View File

@ -16,22 +16,22 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'dart:convert';
import 'dart:typed_data';
import 'package:famedlysdk/matrix_api.dart';
import 'package:famedlysdk/src/client.dart';
import 'package:famedlysdk/src/database/database.dart'
show DbRoom, DbRoomState, DbRoomAccountData;
import 'package:famedlysdk/src/event.dart';
import 'package:famedlysdk/src/room.dart';
import 'package:famedlysdk/src/user.dart';
import 'package:famedlysdk/src/utils/matrix_file.dart';
import 'package:famedlysdk/src/database/database.dart'
show DbRoom, DbRoomState, DbRoomAccountData;
import 'package:test/test.dart';
import 'fake_client.dart';
import 'fake_matrix_api.dart';
import 'dart:convert';
import 'dart:typed_data';
void main() {
Client matrix;
Room room;
@ -552,6 +552,18 @@ void main() {
await room.setFavourite(false);
});
test('Test marked unread room', () async {
await room.setUnread(true);
await room.setUnread(false);
expect(room.isUnread, false);
room.roomAccountData['com.famedly.marked_unread'] =
BasicRoomEvent.fromJson({
'content': {'unread': true},
'type': 'com.famedly.marked_unread'
});
expect(room.isUnread, true);
});
test('joinRules', () async {
expect(room.canChangeJoinRules, false);
expect(room.joinRules, JoinRules.public);