Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] Chat Lists #644

Draft
wants to merge 5 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 127d285aa3bfad2bbd68630172869bd951e40542

COCOAPODS: 1.11.2
COCOAPODS: 1.11.3
8 changes: 4 additions & 4 deletions lib/global/formatters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,20 @@ String formatTimestamp({

final timestamp = DateTime.fromMillisecondsSinceEpoch(lastUpdateMillis);
final sinceLastUpdate = DateTime.now().difference(timestamp);
final hourFormat = timeFormat == TimeFormat.hr24 ? 'H:mm' : 'h:mm';
final hourFormat = timeFormat == TimeFormat.hr24 ? 'H:mm' : 'h:mm a';

if (sinceLastUpdate.inDays > 365) {
return DateFormat(
showTime ? 'MMM d $hourFormat a' : 'MMM d yyyy',
showTime ? 'MMM d $hourFormat' : 'MMM d yyyy',
).format(timestamp);
} else if (sinceLastUpdate.inDays > 6) {
// Abbreviated month and day number - Jan 1
return DateFormat(
showTime ? 'MMM d $hourFormat a' : 'MMM d',
showTime ? 'MMM d $hourFormat' : 'MMM d',
).format(timestamp);
} else if (sinceLastUpdate.inDays > 0) {
// Abbreviated weekday - Fri
return DateFormat(showTime ? 'E $hourFormat a' : 'E').format(timestamp);
return DateFormat(showTime ? 'E $hourFormat' : 'E').format(timestamp);
} else if (sinceLastUpdate.inHours > 0) {
// Abbreviated hours since - 1h
return '${sinceLastUpdate.inHours}h';
Expand Down
2 changes: 1 addition & 1 deletion lib/store/auth/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'package:redux_thunk/redux_thunk.dart';
import 'package:syphon/context/auth.dart';
import 'package:syphon/context/storage.dart';
import 'package:syphon/context/types.dart';
import 'package:syphon/global/algos.dart';
import 'package:syphon/global/libs/matrix/auth.dart';
import 'package:syphon/global/libs/matrix/errors.dart';
import 'package:syphon/global/libs/matrix/index.dart';
Expand All @@ -35,6 +34,7 @@ import 'package:syphon/store/rooms/actions.dart';
import 'package:syphon/store/search/actions.dart';
import 'package:syphon/store/settings/actions.dart';
import 'package:syphon/store/settings/devices-settings/model.dart';
import 'package:syphon/store/settings/notification-settings/actions.dart';
import 'package:syphon/store/settings/notification-settings/remote/actions.dart';
import 'package:syphon/store/sync/actions.dart';
import 'package:syphon/store/sync/background/storage.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/store/index.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Future<Store<AppState>> initStore(
shouldSave: cacheMiddleware,
);

// Finally load persisted store
// finally load persisted store
try {
// TODO: this is pretty hacky - merges availableUsers across stores
if (existingUser) {
Expand Down
6 changes: 0 additions & 6 deletions lib/store/rooms/room/model.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:collection/collection.dart' show IterableExtension;
import 'package:drift/drift.dart' as drift;
import 'package:json_annotation/json_annotation.dart';
import 'package:syphon/global/ids.dart';
import 'package:syphon/global/libs/matrix/constants.dart';
import 'package:syphon/global/print.dart';
import 'package:syphon/global/strings.dart';
Expand All @@ -16,11 +15,6 @@ import 'package:syphon/store/user/model.dart';

part 'model.g.dart';

// TODO: convert to using Identifier wrapper class
class RoomId extends Identifier {
RoomId(id) : super(id: id);
}

class RoomPresets {
static const private = 'private_chat';
static const privateTrusted = 'trusted_private_chat';
Expand Down
13 changes: 13 additions & 0 deletions lib/store/rooms/room/types.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:syphon/global/ids.dart';

// TODO: convert to using Identifier wrapper class
class RoomId extends Identifier {
RoomId(id) : super(id: id);
}

enum RoomType {
invite,
public,
direct,
group,
}
83 changes: 11 additions & 72 deletions lib/store/settings/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import 'package:redux/redux.dart';
import 'package:redux_thunk/redux_thunk.dart';
import 'package:syphon/global/libs/matrix/auth.dart';
import 'package:syphon/global/libs/matrix/index.dart';
import 'package:syphon/global/notifications.dart';
import 'package:syphon/global/print.dart';
import 'package:syphon/global/strings.dart';
import 'package:syphon/global/themes.dart';
import 'package:syphon/global/values.dart';
import 'package:syphon/store/alerts/actions.dart';
Expand All @@ -13,9 +11,7 @@ import 'package:syphon/store/auth/credential/model.dart';
import 'package:syphon/store/index.dart';
import 'package:syphon/store/settings/devices-settings/model.dart';
import 'package:syphon/store/settings/models.dart';
import 'package:syphon/store/settings/storage.dart';
import 'package:syphon/store/settings/theme-settings/model.dart';
import 'package:syphon/store/sync/background/service.dart';

class SetThemeType {
final ThemeType themeType;
Expand Down Expand Up @@ -125,8 +121,6 @@ class ToggleRoomTypeBadges {}

class ToggleMembershipEvents {}

class ToggleNotifications {}

class ToggleTypingIndicators {}

class ToggleTimeFormat {}
Expand Down Expand Up @@ -414,18 +408,21 @@ Future<bool> homeserverSupportsHiddenReadReceipts(Store<AppState> store) async {

final unstableFeatures = version['unstable_features'];

return unstableFeatures != null
&& unstableFeatures.containsKey('org.matrix.msc2285')
&& unstableFeatures['org.matrix.msc2285'];
return unstableFeatures != null &&
unstableFeatures.containsKey('org.matrix.msc2285') &&
unstableFeatures['org.matrix.msc2285'];
}

ThunkAction<AppState> incrementReadReceipts() {
return (Store<AppState> store) async {
final readReceiptsIndex = ReadReceiptTypes.values.indexOf(store.state.settingsStore.readReceipts);
final readReceiptsIndex =
ReadReceiptTypes.values.indexOf(store.state.settingsStore.readReceipts);

final nextReceipt = ReadReceiptTypes.values[(readReceiptsIndex + 1) % ReadReceiptTypes.values.length];
final nextReceipt =
ReadReceiptTypes.values[(readReceiptsIndex + 1) % ReadReceiptTypes.values.length];

if (nextReceipt != ReadReceiptTypes.Hidden) { //short-out
if (nextReceipt != ReadReceiptTypes.Hidden) {
//short-out
return store.dispatch(SetReadReceipts(
readReceipts: nextReceipt,
));
Expand All @@ -438,8 +435,8 @@ ThunkAction<AppState> incrementReadReceipts() {
}

return store.dispatch(SetReadReceipts(
readReceipts: ReadReceiptTypes.values[(readReceiptsIndex + 2) %
ReadReceiptTypes.values.length],
readReceipts:
ReadReceiptTypes.values[(readReceiptsIndex + 2) % ReadReceiptTypes.values.length],
));
};
}
Expand Down Expand Up @@ -497,61 +494,3 @@ ThunkAction<AppState> toggleMembershipEvents() {
store.dispatch(ToggleMembershipEvents());
};
}

ThunkAction<AppState> toggleNotifications() {
return (Store<AppState> store) async {
if (globalNotificationPluginInstance == null) {
return;
}

final permitted = await promptNativeNotificationsRequest(
pluginInstance: globalNotificationPluginInstance!,
);

if (!permitted) {
return;
}

store.dispatch(ToggleNotifications());

final enabled = store.state.settingsStore.notificationSettings.enabled;

if (enabled) {
store.dispatch(startNotifications());
} else {
store.dispatch(stopNotifications());
}
};
}

ThunkAction<AppState> startNotifications() {
return (Store<AppState> store) async {
await BackgroundSync.init();

final Map<String, String?> roomNames = store.state.roomStore.rooms.map(
(roomId, room) => MapEntry(roomId, room.name),
);

await BackgroundSync.start(
roomNames: roomNames,
protocol: store.state.authStore.protocol,
lastSince: store.state.syncStore.lastSince,
currentUser: store.state.authStore.currentUser,
settings: store.state.settingsStore.notificationSettings,
);

showBackgroundServiceNotification(
notificationId: BackgroundSync.service_id,
pluginInstance: globalNotificationPluginInstance!,
);
};
}

ThunkAction<AppState> stopNotifications() {
return (Store<AppState> store) async {
BackgroundSync.stop();
dismissAllNotifications(
pluginInstance: globalNotificationPluginInstance,
);
};
}
41 changes: 41 additions & 0 deletions lib/store/settings/chat-settings/chat-lists/actions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:redux/redux.dart';
import 'package:redux_thunk/redux_thunk.dart';

import 'package:syphon/store/index.dart';
import 'package:syphon/store/settings/actions.dart';
import 'package:syphon/store/settings/chat-settings/chat-lists/model.dart';

class CreateChatList {
const CreateChatList();
}

class UpdateChatList {
final ChatList? list;
const UpdateChatList({this.list});
}

class DeleteChatList {
final ChatList? list;
const DeleteChatList({this.list});
}

ThunkAction<AppState> createChatList() {
return (Store<AppState> store) async {
store.dispatch(CreateChatList());
};
}

ThunkAction<AppState> updateChatList(ChatList? list) {
return (Store<AppState> store) async {
store.dispatch(UpdateChatList(list: list));
};
}

ThunkAction<AppState> removeChatList({String? roomId, int? color}) {
return (Store<AppState> store) async {
store.dispatch(SetRoomPrimaryColor(
roomId: roomId,
color: color,
));
};
}
20 changes: 16 additions & 4 deletions lib/store/settings/chat-settings/chat-lists/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,36 @@ enum SortOrder {
@JsonSerializable()
class ChatList extends Equatable {
final String id;
final SortOrder order;
final String name;
final String symbol; // emoji for now
// List<roomId>
final List<String> roomIds;
// order is used only under the "Custom" sort order
// Map<order, roomId>
final Map<int, String> order;

final int position; // global position in home list

const ChatList({
required this.id,
this.order = SortOrder.Latest, // millis
this.name = 'New List',
this.symbol = '',
this.order = const {},
this.roomIds = const [],
this.position = 0,
});

@override
List<Object?> get props => [
id,
name,
symbol,
order,
roomIds,
position,
];

Map<String, dynamic> toJson() => _$ChatListToJson(this);

factory ChatList.fromJson(Map<String, dynamic> json) =>
_$ChatListFromJson(json);
factory ChatList.fromJson(Map<String, dynamic> json) => _$ChatListFromJson(json);
}
Loading