mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-12-18 10:52:34 +01:00
99 lines
3.4 KiB
Dart
99 lines
3.4 KiB
Dart
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
|
import 'package:matrix/matrix.dart';
|
|
|
|
extension ClientStoriesExtension on Client {
|
|
static const String storiesRoomType = 'msc3588.stories.stories-room';
|
|
static const String storiesBlockListType = 'msc3588.stories.block-list';
|
|
|
|
static const int lifeTimeInHours = 24;
|
|
static const int maxPostsPerStory = 20;
|
|
|
|
List<User> get contacts => rooms
|
|
.where((room) => room.isDirectChat)
|
|
.map((room) =>
|
|
room.unsafeGetUserFromMemoryOrFallback(room.directChatMatrixID!))
|
|
.toList();
|
|
|
|
List<Room> get storiesRooms =>
|
|
rooms.where((room) => room.isStoryRoom).toList();
|
|
|
|
Future<List<User>> getUndecidedContactsForStories(Room? storiesRoom) async {
|
|
if (storiesRoom == null) return contacts;
|
|
final invitedContacts =
|
|
(await storiesRoom.requestParticipants()).map((user) => user.id);
|
|
final decidedContacts = storiesBlockList.toSet()..addAll(invitedContacts);
|
|
return contacts
|
|
.where((contact) => !decidedContacts.contains(contact.id))
|
|
.toList();
|
|
}
|
|
|
|
List<String> get storiesBlockList =>
|
|
accountData[storiesBlockListType]?.content.tryGetList<String>('users') ??
|
|
[];
|
|
|
|
Future<void> setStoriesBlockList(List<String> users) => setAccountData(
|
|
userID!,
|
|
storiesBlockListType,
|
|
{'users': users},
|
|
);
|
|
|
|
Future<Room> createStoriesRoom([List<String>? invite]) async {
|
|
final roomId = await createRoom(
|
|
creationContent: {"type": "msc3588.stories.stories-room"},
|
|
preset: CreateRoomPreset.privateChat,
|
|
powerLevelContentOverride: {"events_default": 100},
|
|
name: 'Stories from ${userID!.localpart}',
|
|
topic:
|
|
'This is a room for stories sharing, not unlike the similarly named features in other messaging networks. For best experience please use FluffyChat or minesTrix. Feature development can be followed on: https://github.com/matrix-org/matrix-doc/pull/3588',
|
|
initialState: [
|
|
StateEvent(
|
|
type: EventTypes.Encryption,
|
|
stateKey: '',
|
|
content: {
|
|
'algorithm': 'm.megolm.v1.aes-sha2',
|
|
},
|
|
),
|
|
StateEvent(
|
|
type: 'm.room.retention',
|
|
stateKey: '',
|
|
content: {
|
|
'min_lifetime': 86400000,
|
|
'max_lifetime': 86400000,
|
|
},
|
|
),
|
|
],
|
|
invite: invite,
|
|
);
|
|
if (getRoomById(roomId) == null) {
|
|
// Wait for room actually appears in sync
|
|
await onSync.stream
|
|
.firstWhere((sync) => sync.rooms?.join?.containsKey(roomId) ?? false);
|
|
}
|
|
return getRoomById(roomId)!;
|
|
}
|
|
|
|
Future<Room?> getStoriesRoom(BuildContext context) async {
|
|
final candidates = rooms.where((room) =>
|
|
room.getState(EventTypes.RoomCreate)?.content.tryGet<String>('type') ==
|
|
storiesRoomType &&
|
|
room.ownPowerLevel >= 100);
|
|
if (candidates.isEmpty) return null;
|
|
if (candidates.length == 1) return candidates.single;
|
|
return await showModalActionSheet<Room>(
|
|
context: context,
|
|
actions: candidates
|
|
.map(
|
|
(room) => SheetAction(label: room.displayname, key: room),
|
|
)
|
|
.toList());
|
|
}
|
|
}
|
|
|
|
extension StoryRoom on Room {
|
|
bool get isStoryRoom =>
|
|
getState(EventTypes.RoomCreate)?.content.tryGet<String>('type') ==
|
|
ClientStoriesExtension.storiesRoomType;
|
|
}
|