mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-20 02:59:26 +01:00
fix: Archive
This commit is contained in:
parent
8632154832
commit
a1f60b7ff9
@ -94,6 +94,13 @@ class AppRoutes {
|
|||||||
VWidget(
|
VWidget(
|
||||||
path: '/archive',
|
path: '/archive',
|
||||||
widget: const Archive(),
|
widget: const Archive(),
|
||||||
|
stackedRoutes: [
|
||||||
|
VWidget(
|
||||||
|
path: ':roomid',
|
||||||
|
widget: const Chat(),
|
||||||
|
buildTransition: _dynamicTransition,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '/newprivatechat',
|
path: '/newprivatechat',
|
||||||
@ -220,13 +227,25 @@ class AppRoutes {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
VWidget(
|
VNester(
|
||||||
path: '/archive',
|
path: '/archive',
|
||||||
widget: const TwoColumnLayout(
|
widgetBuilder: (child) => TwoColumnLayout(
|
||||||
mainView: Archive(),
|
mainView: const Archive(),
|
||||||
sideView: EmptyPage(),
|
sideView: child,
|
||||||
),
|
),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
|
nestedRoutes: [
|
||||||
|
VWidget(
|
||||||
|
path: '',
|
||||||
|
widget: const EmptyPage(),
|
||||||
|
buildTransition: _dynamicTransition,
|
||||||
|
),
|
||||||
|
VWidget(
|
||||||
|
path: ':roomid',
|
||||||
|
widget: const Chat(),
|
||||||
|
buildTransition: _dynamicTransition,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -21,11 +21,9 @@ class ArchiveController extends State<Archive> {
|
|||||||
Future<List<Room>> getArchive(BuildContext context) async {
|
Future<List<Room>> getArchive(BuildContext context) async {
|
||||||
final archive = this.archive;
|
final archive = this.archive;
|
||||||
if (archive != null) return archive;
|
if (archive != null) return archive;
|
||||||
return await Matrix.of(context).client.loadArchive();
|
return this.archive = await Matrix.of(context).client.loadArchive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void forgetAction(int i) => setState(() => archive?.removeAt(i));
|
|
||||||
|
|
||||||
void forgetAllAction() async {
|
void forgetAllAction() async {
|
||||||
final archive = this.archive;
|
final archive = this.archive;
|
||||||
if (archive == null) return;
|
if (archive == null) return;
|
||||||
|
@ -21,10 +21,14 @@ class ArchiveView extends StatelessWidget {
|
|||||||
leading: const BackButton(),
|
leading: const BackButton(),
|
||||||
title: Text(L10n.of(context)!.archive),
|
title: Text(L10n.of(context)!.archive),
|
||||||
actions: [
|
actions: [
|
||||||
if (snapshot.hasData && archive != null && archive!.isNotEmpty)
|
if (snapshot.data?.isNotEmpty ?? false)
|
||||||
TextButton(
|
Padding(
|
||||||
onPressed: controller.forgetAllAction,
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(L10n.of(context)!.clearArchive),
|
child: TextButton.icon(
|
||||||
|
onPressed: controller.forgetAllAction,
|
||||||
|
label: Text(L10n.of(context)!.clearArchive),
|
||||||
|
icon: const Icon(Icons.cleaning_services_outlined),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -50,7 +54,6 @@ class ArchiveView extends StatelessWidget {
|
|||||||
itemCount: archive!.length,
|
itemCount: archive!.length,
|
||||||
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
||||||
archive![i],
|
archive![i],
|
||||||
onForget: controller.forgetAction,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -630,6 +630,7 @@ class ChatController extends State<Chat> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool get canRedactSelectedEvents {
|
bool get canRedactSelectedEvents {
|
||||||
|
if (isArchived) return false;
|
||||||
final clients = matrix!.currentBundle;
|
final clients = matrix!.currentBundle;
|
||||||
for (final event in selectedEvents) {
|
for (final event in selectedEvents) {
|
||||||
if (event.canRedact == false &&
|
if (event.canRedact == false &&
|
||||||
@ -639,7 +640,9 @@ class ChatController extends State<Chat> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool get canEditSelectedEvents {
|
bool get canEditSelectedEvents {
|
||||||
if (selectedEvents.length != 1 || !selectedEvents.first.status.isSent) {
|
if (isArchived ||
|
||||||
|
selectedEvents.length != 1 ||
|
||||||
|
!selectedEvents.first.status.isSent) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return currentRoomBundle
|
return currentRoomBundle
|
||||||
@ -757,6 +760,15 @@ class ChatController extends State<Chat> {
|
|||||||
return sendEmojiAction(emoji.emoji);
|
return sendEmojiAction(emoji.emoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void forgetRoom() async {
|
||||||
|
final result = await showFutureLoadingDialog(
|
||||||
|
context: context,
|
||||||
|
future: room!.forget,
|
||||||
|
);
|
||||||
|
if (result.error != null) return;
|
||||||
|
VRouter.of(context).to('/archive');
|
||||||
|
}
|
||||||
|
|
||||||
void typeEmoji(Emoji? emoji) {
|
void typeEmoji(Emoji? emoji) {
|
||||||
if (emoji == null) return;
|
if (emoji == null) return;
|
||||||
final text = sendController.text;
|
final text = sendController.text;
|
||||||
@ -1008,6 +1020,9 @@ class ChatController extends State<Chat> {
|
|||||||
setState(() => inputText = text);
|
setState(() => inputText = text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get isArchived =>
|
||||||
|
{Membership.leave, Membership.ban}.contains(room?.membership);
|
||||||
|
|
||||||
void showEventInfo([Event? event]) =>
|
void showEventInfo([Event? event]) =>
|
||||||
(event ?? selectedEvents.single).showInfoDialog(context);
|
(event ?? selectedEvents.single).showInfoDialog(context);
|
||||||
|
|
||||||
|
@ -37,7 +37,10 @@ class ChatAppBarTitle extends StatelessWidget {
|
|||||||
'${room.unsafeGetUserFromMemoryOrFallback(directChatMatrixID).mention} ',
|
'${room.unsafeGetUserFromMemoryOrFallback(directChatMatrixID).mention} ',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: () => VRouter.of(context).toSegments(['rooms', room.id, 'details']),
|
: controller.isArchived
|
||||||
|
? null
|
||||||
|
: () =>
|
||||||
|
VRouter.of(context).toSegments(['rooms', room.id, 'details']),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Hero(
|
Hero(
|
||||||
|
@ -108,6 +108,20 @@ class ChatView extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
} else if (controller.isArchived) {
|
||||||
|
return [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: TextButton.icon(
|
||||||
|
onPressed: controller.forgetRoom,
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
foregroundColor: Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
|
icon: const Icon(Icons.delete_forever_outlined),
|
||||||
|
label: Text(L10n.of(context)!.delete),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
return [
|
return [
|
||||||
if (Matrix.of(context).voipPlugin != null &&
|
if (Matrix.of(context).voipPlugin != null &&
|
||||||
|
@ -21,10 +21,11 @@ class PinnedEvents extends StatelessWidget {
|
|||||||
BuildContext context, List<Event?> events) async {
|
BuildContext context, List<Event?> events) async {
|
||||||
final eventId = events.length == 1
|
final eventId = events.length == 1
|
||||||
? events.single?.eventId
|
? events.single?.eventId
|
||||||
: await showModalActionSheet<String>(
|
: await showConfirmationDialog<String>(
|
||||||
context: context,
|
context: context,
|
||||||
|
title: L10n.of(context)!.pinMessage,
|
||||||
actions: events
|
actions: events
|
||||||
.map((event) => SheetAction(
|
.map((event) => AlertDialogAction(
|
||||||
key: event?.eventId ?? '',
|
key: event?.eventId ?? '',
|
||||||
label: event?.calcLocalizedBodyFallback(
|
label: event?.calcLocalizedBodyFallback(
|
||||||
MatrixLocals(L10n.of(context)!),
|
MatrixLocals(L10n.of(context)!),
|
||||||
|
@ -21,7 +21,6 @@ class ChatListItem extends StatelessWidget {
|
|||||||
final Room room;
|
final Room room;
|
||||||
final bool activeChat;
|
final bool activeChat;
|
||||||
final bool selected;
|
final bool selected;
|
||||||
final Function? onForget;
|
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
final void Function()? onLongPress;
|
final void Function()? onLongPress;
|
||||||
|
|
||||||
@ -31,7 +30,6 @@ class ChatListItem extends StatelessWidget {
|
|||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.onLongPress,
|
this.onLongPress,
|
||||||
this.onForget,
|
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@ -62,35 +60,7 @@ class ChatListItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (room.membership == Membership.leave) {
|
if (room.membership == Membership.leave) {
|
||||||
final action = await showModalActionSheet<ArchivedRoomAction>(
|
VRouter.of(context).toSegments(['archive', room.id]);
|
||||||
context: context,
|
|
||||||
title: L10n.of(context)!.archivedRoom,
|
|
||||||
message: L10n.of(context)!.thisRoomHasBeenArchived,
|
|
||||||
actions: [
|
|
||||||
SheetAction(
|
|
||||||
label: L10n.of(context)!.rejoin,
|
|
||||||
key: ArchivedRoomAction.rejoin,
|
|
||||||
),
|
|
||||||
SheetAction(
|
|
||||||
label: L10n.of(context)!.delete,
|
|
||||||
key: ArchivedRoomAction.delete,
|
|
||||||
isDestructiveAction: true,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
if (action != null) {
|
|
||||||
switch (action) {
|
|
||||||
case ArchivedRoomAction.delete:
|
|
||||||
await archiveAction(context);
|
|
||||||
break;
|
|
||||||
case ArchivedRoomAction.rejoin:
|
|
||||||
await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () => room.join(),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (room.membership == Membership.join) {
|
if (room.membership == Membership.join) {
|
||||||
@ -122,13 +92,10 @@ class ChatListItem extends StatelessWidget {
|
|||||||
Future<void> archiveAction(BuildContext context) async {
|
Future<void> archiveAction(BuildContext context) async {
|
||||||
{
|
{
|
||||||
if ([Membership.leave, Membership.ban].contains(room.membership)) {
|
if ([Membership.leave, Membership.ban].contains(room.membership)) {
|
||||||
final success = await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => room.forget(),
|
future: () => room.forget(),
|
||||||
);
|
);
|
||||||
if (success.error == null) {
|
|
||||||
if (onForget != null) onForget!();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final confirmed = await showOkCancelAlertDialog(
|
final confirmed = await showOkCancelAlertDialog(
|
||||||
|
@ -66,6 +66,16 @@ class ClientChooserButton extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: SettingsAction.archive,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.archive_outlined),
|
||||||
|
const SizedBox(width: 18),
|
||||||
|
Text(L10n.of(context)!.archive),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: SettingsAction.settings,
|
value: SettingsAction.settings,
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -259,6 +269,9 @@ class ClientChooserButton extends StatelessWidget {
|
|||||||
case SettingsAction.settings:
|
case SettingsAction.settings:
|
||||||
VRouter.of(context).to('/settings');
|
VRouter.of(context).to('/settings');
|
||||||
break;
|
break;
|
||||||
|
case SettingsAction.archive:
|
||||||
|
VRouter.of(context).to('/archive');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,4 +349,5 @@ enum SettingsAction {
|
|||||||
newSpace,
|
newSpace,
|
||||||
invite,
|
invite,
|
||||||
settings,
|
settings,
|
||||||
|
archive,
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,14 @@ Future<T?> showAdaptiveBottomSheet<T>({
|
|||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required Widget Function(BuildContext) builder,
|
required Widget Function(BuildContext) builder,
|
||||||
bool isDismissible = true,
|
bool isDismissible = true,
|
||||||
|
bool isScrollControlled = false,
|
||||||
}) =>
|
}) =>
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: builder,
|
builder: builder,
|
||||||
useRootNavigator: !PlatformInfos.isMobile,
|
useRootNavigator: !PlatformInfos.isMobile,
|
||||||
isDismissible: isDismissible,
|
isDismissible: isDismissible,
|
||||||
|
isScrollControlled: isScrollControlled,
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: MediaQuery.of(context).size.height - 128,
|
maxHeight: MediaQuery.of(context).size.height - 128,
|
||||||
maxWidth: FluffyThemes.columnWidth * 1.5,
|
maxWidth: FluffyThemes.columnWidth * 1.5,
|
||||||
|
@ -29,12 +29,12 @@ extension on PermissionLevel {
|
|||||||
|
|
||||||
Future<int?> showPermissionChooser(BuildContext context,
|
Future<int?> showPermissionChooser(BuildContext context,
|
||||||
{int currentLevel = 0}) async {
|
{int currentLevel = 0}) async {
|
||||||
final permissionLevel = await showModalActionSheet(
|
final permissionLevel = await showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
title: L10n.of(context)!.setPermissionsLevel,
|
title: L10n.of(context)!.setPermissionsLevel,
|
||||||
actions: PermissionLevel.values
|
actions: PermissionLevel.values
|
||||||
.map(
|
.map(
|
||||||
(level) => SheetAction(
|
(level) => AlertDialogAction(
|
||||||
key: level,
|
key: level,
|
||||||
label: level.toLocalizedString(context),
|
label: level.toLocalizedString(context),
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user