feat(ui): Prepare for selectively removing media files
This commit is contained in:
parent
d6416c77b8
commit
53e3b3c561
@ -4,6 +4,7 @@ import 'package:moxxyv2/i18n/strings.g.dart';
|
||||
import 'package:moxxyv2/ui/bloc/navigation_bloc.dart';
|
||||
import 'package:moxxyv2/ui/constants.dart';
|
||||
import 'package:moxxyv2/ui/controller/shared_media_controller.dart';
|
||||
import 'package:moxxyv2/ui/helpers.dart';
|
||||
import 'package:moxxyv2/ui/pages/profile/profile_view.dart';
|
||||
import 'package:moxxyv2/ui/widgets/shared_media_view.dart';
|
||||
|
||||
@ -117,6 +118,9 @@ class ProfilePageState extends State<ProfilePage> {
|
||||
emptyText: t.pages.sharedMedia.empty.chat,
|
||||
showBackButton: false,
|
||||
key: const PageStorageKey('shared_media_view'),
|
||||
onTap: (fm) => openFile(fm.path!),
|
||||
// TODO(Unknown): Allow deleting singular items
|
||||
//onLongPress: (fm) {},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||
import 'package:moxxyv2/ui/constants.dart';
|
||||
import 'package:moxxyv2/ui/controller/shared_media_controller.dart';
|
||||
import 'package:moxxyv2/ui/helpers.dart';
|
||||
import 'package:moxxyv2/ui/widgets/shared_media_view.dart';
|
||||
|
||||
class StorageSharedMediaPage extends StatefulWidget {
|
||||
@ -43,6 +44,9 @@ class StorageSharedMediaPageState extends State<StorageSharedMediaPage> {
|
||||
emptyText: t.pages.sharedMedia.empty.general,
|
||||
showBackButton: true,
|
||||
title: t.pages.settings.storage.mediaFiles,
|
||||
onTap: (fm) => openFile(fm.path!),
|
||||
// TODO(Unknown): Allow deleting singular items
|
||||
//onLongPress: (fm) {},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:moxxyv2/shared/models/file_metadata.dart';
|
||||
import 'package:moxxyv2/shared/models/message.dart';
|
||||
import 'package:moxxyv2/ui/constants.dart';
|
||||
import 'package:moxxyv2/ui/helpers.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/message/audio.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/message/file.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/message/image.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/message/sticker.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/message/text.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/message/video.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/playbutton.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/quote/audio.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/quote/file.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/quote/image.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/quote/sticker.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/quote/text.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/quote/video.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared/audio.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared/file.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared/image.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared/video.dart';
|
||||
|
||||
enum MessageType {
|
||||
text,
|
||||
@ -180,30 +173,3 @@ Widget buildQuoteMessageWidget(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildSharedMediaWidget(FileMetadata metadata, String conversationJid) {
|
||||
if (metadata.mimeType!.startsWith('image/')) {
|
||||
return SharedImageWidget(
|
||||
metadata.path!,
|
||||
onTap: () => openFile(metadata.path!),
|
||||
);
|
||||
} else if (metadata.mimeType!.startsWith('video/')) {
|
||||
return SharedVideoWidget(
|
||||
metadata.path!,
|
||||
conversationJid,
|
||||
metadata.mimeType!,
|
||||
onTap: () => openFile(metadata.path!),
|
||||
child: const PlayButton(size: 32),
|
||||
);
|
||||
} else if (metadata.mimeType!.startsWith('audio/')) {
|
||||
return SharedAudioWidget(
|
||||
metadata.path!,
|
||||
onTap: () => openFile(metadata.path!),
|
||||
);
|
||||
}
|
||||
|
||||
return SharedFileWidget(
|
||||
metadata.path!,
|
||||
onTap: () => openFile(metadata.path!),
|
||||
);
|
||||
}
|
||||
|
50
lib/ui/widgets/chat/shared.dart
Normal file
50
lib/ui/widgets/chat/shared.dart
Normal file
@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:moxxyv2/shared/models/file_metadata.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/playbutton.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared/audio.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared/file.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared/image.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared/video.dart';
|
||||
|
||||
typedef SharedMediaWidgetCallback = void Function(FileMetadata);
|
||||
|
||||
/// Build a widget to represent a shared media file.
|
||||
Widget buildSharedMediaWidget(
|
||||
FileMetadata metadata,
|
||||
String conversationJid,
|
||||
SharedMediaWidgetCallback onTap, {
|
||||
SharedMediaWidgetCallback? onLongPress,
|
||||
}) {
|
||||
// Prevent having the phone vibrate if no onLongPress is passed
|
||||
final longPressCallback =
|
||||
onLongPress != null ? () => onLongPress(metadata) : null;
|
||||
|
||||
if (metadata.mimeType!.startsWith('image/')) {
|
||||
return SharedImageWidget(
|
||||
metadata.path!,
|
||||
onTap: () => onTap(metadata),
|
||||
onLongPress: longPressCallback,
|
||||
);
|
||||
} else if (metadata.mimeType!.startsWith('video/')) {
|
||||
return SharedVideoWidget(
|
||||
metadata.path!,
|
||||
conversationJid,
|
||||
metadata.mimeType!,
|
||||
onTap: () => onTap(metadata),
|
||||
onLongPress: () => onLongPress?.call(metadata),
|
||||
child: const PlayButton(size: 32),
|
||||
);
|
||||
} else if (metadata.mimeType!.startsWith('audio/')) {
|
||||
return SharedAudioWidget(
|
||||
metadata.path!,
|
||||
onTap: () => onTap(metadata),
|
||||
onLongPress: longPressCallback,
|
||||
);
|
||||
}
|
||||
|
||||
return SharedFileWidget(
|
||||
metadata.path!,
|
||||
onTap: () => onTap(metadata),
|
||||
onLongPress: longPressCallback,
|
||||
);
|
||||
}
|
@ -6,6 +6,7 @@ class SharedAudioWidget extends StatelessWidget {
|
||||
const SharedAudioWidget(
|
||||
this.path, {
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.borderColor,
|
||||
this.borderRadius = 3,
|
||||
this.size = sharedMediaContainerDimension,
|
||||
@ -14,6 +15,7 @@ class SharedAudioWidget extends StatelessWidget {
|
||||
final String path;
|
||||
final Color? borderColor;
|
||||
final void Function()? onTap;
|
||||
final void Function()? onLongPress;
|
||||
final double borderRadius;
|
||||
final double size;
|
||||
|
||||
@ -39,6 +41,7 @@ class SharedAudioWidget extends StatelessWidget {
|
||||
color: sharedMediaItemBackgroundColor,
|
||||
size: size,
|
||||
onTap: onTap,
|
||||
onLongPress: onLongPress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ class SharedMediaContainer extends StatelessWidget {
|
||||
this.child, {
|
||||
required this.color,
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.size = sharedMediaContainerDimension,
|
||||
this.borderRadius = 10,
|
||||
super.key,
|
||||
@ -34,30 +35,28 @@ class SharedMediaContainer extends StatelessWidget {
|
||||
final double borderRadius;
|
||||
final Widget? child;
|
||||
final void Function()? onTap;
|
||||
final void Function()? onLongPress;
|
||||
final double size;
|
||||
final Color color;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final childWidget = SizedBox(
|
||||
height: size,
|
||||
width: size,
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
child: Material(
|
||||
color: color,
|
||||
child: onTap != null
|
||||
? InkWell(
|
||||
onTap: onTap,
|
||||
child: childWidget,
|
||||
)
|
||||
: childWidget,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
onLongPress: onLongPress,
|
||||
child: SizedBox(
|
||||
height: size,
|
||||
width: size,
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -6,12 +6,14 @@ class SharedFileWidget extends StatelessWidget {
|
||||
const SharedFileWidget(
|
||||
this.path, {
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.borderRadius = 3,
|
||||
this.size = sharedMediaContainerDimension,
|
||||
super.key,
|
||||
});
|
||||
final String path;
|
||||
final void Function()? onTap;
|
||||
final void Function()? onLongPress;
|
||||
final double borderRadius;
|
||||
final double size;
|
||||
|
||||
@ -26,6 +28,7 @@ class SharedFileWidget extends StatelessWidget {
|
||||
borderRadius: borderRadius,
|
||||
size: size,
|
||||
onTap: onTap,
|
||||
onLongPress: onLongPress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ class SharedImageWidget extends StatelessWidget {
|
||||
const SharedImageWidget(
|
||||
this.path, {
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.borderColor,
|
||||
this.child,
|
||||
this.borderRadius = 3,
|
||||
@ -15,6 +16,7 @@ class SharedImageWidget extends StatelessWidget {
|
||||
final String path;
|
||||
final Color? borderColor;
|
||||
final void Function()? onTap;
|
||||
final void Function()? onLongPress;
|
||||
final Widget? child;
|
||||
final double borderRadius;
|
||||
final double size;
|
||||
@ -50,6 +52,7 @@ class SharedImageWidget extends StatelessWidget {
|
||||
color: Colors.transparent,
|
||||
size: size,
|
||||
onTap: onTap,
|
||||
onLongPress: onLongPress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ class SharedVideoWidget extends StatelessWidget {
|
||||
this.conversationJid,
|
||||
this.mime, {
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.borderColor,
|
||||
this.child,
|
||||
this.size = sharedMediaContainerDimension,
|
||||
@ -19,6 +20,7 @@ class SharedVideoWidget extends StatelessWidget {
|
||||
final String mime;
|
||||
final Color? borderColor;
|
||||
final void Function()? onTap;
|
||||
final void Function()? onLongPress;
|
||||
final Widget? child;
|
||||
final double size;
|
||||
final double borderRadius;
|
||||
@ -40,6 +42,7 @@ class SharedVideoWidget extends StatelessWidget {
|
||||
color: Colors.transparent,
|
||||
size: size,
|
||||
onTap: onTap,
|
||||
onLongPress: onLongPress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import 'package:moxxyv2/shared/models/message.dart';
|
||||
import 'package:moxxyv2/ui/constants.dart';
|
||||
import 'package:moxxyv2/ui/controller/shared_media_controller.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/bubbles/date.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/message.dart';
|
||||
import 'package:moxxyv2/ui/widgets/chat/shared.dart';
|
||||
import 'package:moxxyv2/ui/widgets/grouped_grid_view.dart';
|
||||
import 'package:moxxyv2/ui/widgets/topbar.dart';
|
||||
|
||||
@ -15,7 +15,9 @@ class SharedMediaView extends StatelessWidget {
|
||||
this.mediaController, {
|
||||
required this.emptyText,
|
||||
required this.showBackButton,
|
||||
required this.onTap,
|
||||
this.title,
|
||||
this.onLongPress,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@ -33,6 +35,12 @@ class SharedMediaView extends StatelessWidget {
|
||||
/// sent/received in the chat.
|
||||
final String emptyText;
|
||||
|
||||
/// Callback for when a widget has been tapped.
|
||||
final SharedMediaWidgetCallback onTap;
|
||||
|
||||
/// Callback for when a widget has been long pressed.
|
||||
final SharedMediaWidgetCallback? onLongPress;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final now = DateTime.now();
|
||||
@ -124,6 +132,8 @@ class SharedMediaView extends StatelessWidget {
|
||||
itemBuilder: (_, message) => buildSharedMediaWidget(
|
||||
message.fileMetadata!,
|
||||
message.conversationJid,
|
||||
onTap,
|
||||
onLongPress: onLongPress,
|
||||
),
|
||||
separatorBuilder: (_, timestamp) => Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
|
Loading…
Reference in New Issue
Block a user