refactor: Replace stories feature with presence status msg

This commit is contained in:
Krille 2023-12-22 17:15:14 +01:00
commit 895de76e70
No known key found for this signature in database
GPG key ID: E067ECD60F1A0652
21 changed files with 364 additions and 2386 deletions

View file

@ -31,7 +31,6 @@ import 'package:http/http.dart' as http;
import 'package:matrix/matrix.dart';
import 'package:unifiedpush/unifiedpush.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart';
import 'package:fluffychat/utils/push_helper.dart';
import 'package:fluffychat/widgets/fluffy_chat_app.dart';
import '../config/app_config.dart';
@ -314,14 +313,7 @@ class BackgroundPush {
}
await client.roomsLoading;
await client.accountDataLoading;
final isStory = client
.getRoomById(roomId)
?.getState(EventTypes.RoomCreate)
?.content
.tryGet<String>('type') ==
ClientStoriesExtension.storiesRoomType;
FluffyChatApp.router
.go('/${isStory ? 'rooms/stories' : 'rooms'}/$roomId');
FluffyChatApp.router.go('/rooms/$roomId');
} catch (e, s) {
Logs().e('[Push] Failed to open room', e, s);
}

View file

@ -111,8 +111,6 @@ abstract class ClientManager {
importantStateEvents: <String>{
// To make room emotes work
'im.ponies.room_emotes',
// To check which story room we can post in
EventTypes.RoomPowerLevels,
},
logLevel: kReleaseMode ? Level.warning : Level.verbose,
databaseBuilder: flutterMatrixSdkDatabaseBuilder,

View file

@ -1,125 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.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 and is encrypted. This is a
// workaround for https://github.com/krille-chan/fluffychat/issues/520
await onSync.stream.firstWhere(
(sync) =>
sync.rooms?.join?[roomId]?.state
?.any((state) => state.type == EventTypes.Encrypted) ??
false,
);
}
final room = getRoomById(roomId);
if (room == null || !room.encrypted) {
throw Exception(
'Unable to create and wait for encrypted room to appear in Sync.',
);
}
return room;
}
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.getLocalizedDisplayname(
MatrixLocals(L10n.of(context)!),
),
key: room,
),
)
.toList(),
);
}
}
extension StoryRoom on Room {
bool get isStoryRoom =>
getState(EventTypes.RoomCreate)?.content.tryGet<String>('type') ==
ClientStoriesExtension.storiesRoomType;
}

View file

@ -1,44 +0,0 @@
import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
class StoryThemeData {
final Color? color1;
final Color? color2;
final BoxFit fit;
final int alignmentX;
final int alignmentY;
static const String contentKey = 'msc3588.stories.design';
const StoryThemeData({
this.color1,
this.color2,
this.fit = BoxFit.contain,
this.alignmentX = 0,
this.alignmentY = 0,
});
factory StoryThemeData.fromJson(Map<String, dynamic> json) {
final color1Int = json.tryGet<int>('color1');
final color2Int = json.tryGet<int>('color2');
final color1 = color1Int == null ? null : Color(color1Int);
final color2 = color2Int == null ? null : Color(color2Int);
return StoryThemeData(
color1: color1,
color2: color2,
fit:
json.tryGet<String>('fit') == 'cover' ? BoxFit.cover : BoxFit.contain,
alignmentX: json.tryGet<int>('alignment_x') ?? 0,
alignmentY: json.tryGet<int>('alignment_y') ?? 0,
);
}
Map<String, dynamic> toJson() => {
if (color1 != null) 'color1': color1?.value,
if (color2 != null) 'color2': color2?.value,
'fit': fit.name,
'alignment_x': alignmentX,
'alignment_y': alignmentY,
};
}