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/bloc/navigation_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/controller/shared_media_controller.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/pages/profile/profile_view.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/shared_media_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,
|
emptyText: t.pages.sharedMedia.empty.chat,
|
||||||
showBackButton: false,
|
showBackButton: false,
|
||||||
key: const PageStorageKey('shared_media_view'),
|
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/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/controller/shared_media_controller.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';
|
import 'package:moxxyv2/ui/widgets/shared_media_view.dart';
|
||||||
|
|
||||||
class StorageSharedMediaPage extends StatefulWidget {
|
class StorageSharedMediaPage extends StatefulWidget {
|
||||||
@ -43,6 +44,9 @@ class StorageSharedMediaPageState extends State<StorageSharedMediaPage> {
|
|||||||
emptyText: t.pages.sharedMedia.empty.general,
|
emptyText: t.pages.sharedMedia.empty.general,
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
title: t.pages.settings.storage.mediaFiles,
|
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:flutter/material.dart';
|
||||||
import 'package:moxxyv2/shared/models/file_metadata.dart';
|
|
||||||
import 'package:moxxyv2/shared/models/message.dart';
|
import 'package:moxxyv2/shared/models/message.dart';
|
||||||
import 'package:moxxyv2/ui/constants.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/audio.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/chat/message/file.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/image.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/chat/message/sticker.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/text.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/chat/message/video.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/audio.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/chat/quote/file.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/image.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/chat/quote/sticker.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/text.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/chat/quote/video.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 {
|
enum MessageType {
|
||||||
text,
|
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(
|
const SharedAudioWidget(
|
||||||
this.path, {
|
this.path, {
|
||||||
this.onTap,
|
this.onTap,
|
||||||
|
this.onLongPress,
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
this.borderRadius = 3,
|
this.borderRadius = 3,
|
||||||
this.size = sharedMediaContainerDimension,
|
this.size = sharedMediaContainerDimension,
|
||||||
@ -14,6 +15,7 @@ class SharedAudioWidget extends StatelessWidget {
|
|||||||
final String path;
|
final String path;
|
||||||
final Color? borderColor;
|
final Color? borderColor;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
final void Function()? onLongPress;
|
||||||
final double borderRadius;
|
final double borderRadius;
|
||||||
final double size;
|
final double size;
|
||||||
|
|
||||||
@ -39,6 +41,7 @@ class SharedAudioWidget extends StatelessWidget {
|
|||||||
color: sharedMediaItemBackgroundColor,
|
color: sharedMediaItemBackgroundColor,
|
||||||
size: size,
|
size: size,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
onLongPress: onLongPress,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ class SharedMediaContainer extends StatelessWidget {
|
|||||||
this.child, {
|
this.child, {
|
||||||
required this.color,
|
required this.color,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
|
this.onLongPress,
|
||||||
this.size = sharedMediaContainerDimension,
|
this.size = sharedMediaContainerDimension,
|
||||||
this.borderRadius = 10,
|
this.borderRadius = 10,
|
||||||
super.key,
|
super.key,
|
||||||
@ -34,30 +35,28 @@ class SharedMediaContainer extends StatelessWidget {
|
|||||||
final double borderRadius;
|
final double borderRadius;
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
final void Function()? onLongPress;
|
||||||
final double size;
|
final double size;
|
||||||
final Color color;
|
final Color color;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final childWidget = SizedBox(
|
|
||||||
height: size,
|
|
||||||
width: size,
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 1,
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return ClipRRect(
|
return ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(borderRadius),
|
borderRadius: BorderRadius.circular(borderRadius),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: color,
|
color: color,
|
||||||
child: onTap != null
|
child: InkWell(
|
||||||
? InkWell(
|
onTap: onTap,
|
||||||
onTap: onTap,
|
onLongPress: onLongPress,
|
||||||
child: childWidget,
|
child: SizedBox(
|
||||||
)
|
height: size,
|
||||||
: childWidget,
|
width: size,
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 1,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,14 @@ class SharedFileWidget extends StatelessWidget {
|
|||||||
const SharedFileWidget(
|
const SharedFileWidget(
|
||||||
this.path, {
|
this.path, {
|
||||||
this.onTap,
|
this.onTap,
|
||||||
|
this.onLongPress,
|
||||||
this.borderRadius = 3,
|
this.borderRadius = 3,
|
||||||
this.size = sharedMediaContainerDimension,
|
this.size = sharedMediaContainerDimension,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
final String path;
|
final String path;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
final void Function()? onLongPress;
|
||||||
final double borderRadius;
|
final double borderRadius;
|
||||||
final double size;
|
final double size;
|
||||||
|
|
||||||
@ -26,6 +28,7 @@ class SharedFileWidget extends StatelessWidget {
|
|||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
size: size,
|
size: size,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
onLongPress: onLongPress,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ class SharedImageWidget extends StatelessWidget {
|
|||||||
const SharedImageWidget(
|
const SharedImageWidget(
|
||||||
this.path, {
|
this.path, {
|
||||||
this.onTap,
|
this.onTap,
|
||||||
|
this.onLongPress,
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
this.child,
|
this.child,
|
||||||
this.borderRadius = 3,
|
this.borderRadius = 3,
|
||||||
@ -15,6 +16,7 @@ class SharedImageWidget extends StatelessWidget {
|
|||||||
final String path;
|
final String path;
|
||||||
final Color? borderColor;
|
final Color? borderColor;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
final void Function()? onLongPress;
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
final double borderRadius;
|
final double borderRadius;
|
||||||
final double size;
|
final double size;
|
||||||
@ -50,6 +52,7 @@ class SharedImageWidget extends StatelessWidget {
|
|||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
size: size,
|
size: size,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
onLongPress: onLongPress,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ class SharedVideoWidget extends StatelessWidget {
|
|||||||
this.conversationJid,
|
this.conversationJid,
|
||||||
this.mime, {
|
this.mime, {
|
||||||
this.onTap,
|
this.onTap,
|
||||||
|
this.onLongPress,
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
this.child,
|
this.child,
|
||||||
this.size = sharedMediaContainerDimension,
|
this.size = sharedMediaContainerDimension,
|
||||||
@ -19,6 +20,7 @@ class SharedVideoWidget extends StatelessWidget {
|
|||||||
final String mime;
|
final String mime;
|
||||||
final Color? borderColor;
|
final Color? borderColor;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
final void Function()? onLongPress;
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
final double size;
|
final double size;
|
||||||
final double borderRadius;
|
final double borderRadius;
|
||||||
@ -40,6 +42,7 @@ class SharedVideoWidget extends StatelessWidget {
|
|||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
size: size,
|
size: size,
|
||||||
onTap: onTap,
|
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/constants.dart';
|
||||||
import 'package:moxxyv2/ui/controller/shared_media_controller.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/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/grouped_grid_view.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/topbar.dart';
|
import 'package:moxxyv2/ui/widgets/topbar.dart';
|
||||||
|
|
||||||
@ -15,7 +15,9 @@ class SharedMediaView extends StatelessWidget {
|
|||||||
this.mediaController, {
|
this.mediaController, {
|
||||||
required this.emptyText,
|
required this.emptyText,
|
||||||
required this.showBackButton,
|
required this.showBackButton,
|
||||||
|
required this.onTap,
|
||||||
this.title,
|
this.title,
|
||||||
|
this.onLongPress,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -33,6 +35,12 @@ class SharedMediaView extends StatelessWidget {
|
|||||||
/// sent/received in the chat.
|
/// sent/received in the chat.
|
||||||
final String emptyText;
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
@ -124,6 +132,8 @@ class SharedMediaView extends StatelessWidget {
|
|||||||
itemBuilder: (_, message) => buildSharedMediaWidget(
|
itemBuilder: (_, message) => buildSharedMediaWidget(
|
||||||
message.fileMetadata!,
|
message.fileMetadata!,
|
||||||
message.conversationJid,
|
message.conversationJid,
|
||||||
|
onTap,
|
||||||
|
onLongPress: onLongPress,
|
||||||
),
|
),
|
||||||
separatorBuilder: (_, timestamp) => Padding(
|
separatorBuilder: (_, timestamp) => Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
|
Loading…
Reference in New Issue
Block a user