diff --git a/app/assets/images/icons/google-drive.svg b/app/assets/images/icons/google-drive.svg
new file mode 100644
index 0000000..987eb2c
--- /dev/null
+++ b/app/assets/images/icons/google-drive.svg
@@ -0,0 +1,8 @@
+
diff --git a/app/assets/images/icons/google_photos.svg b/app/assets/images/icons/google_photos.svg
deleted file mode 100644
index 44b3fb3..0000000
--- a/app/assets/images/icons/google_photos.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/app/assets/locales/app_en.arb b/app/assets/locales/app_en.arb
index 81d8549..c467ea3 100644
--- a/app/assets/locales/app_en.arb
+++ b/app/assets/locales/app_en.arb
@@ -20,7 +20,7 @@
"common_delete_from_google_drive": "Delete from Google Drive",
"common_delete_from_device": "Delete from Device",
"common_cancel": "Cancel",
-
+ "common_not_available": "N/A",
"no_internet_connection_error": "No internet connection! Please check your network and try again.",
"something_went_wrong_error": "Something went wrong! Please try again later.",
@@ -71,6 +71,18 @@
"download_in_progress_text": "Download in progress",
"download_require_text": "Download required",
- "download_require_message": "To watch the video, simply download it first. Tap the download button to begin downloading the video."
-
+ "download_require_message": "To watch the video, simply download it first. Tap the download button to begin downloading the video.",
+
+ "name_text": "Name",
+ "size_text": "Size",
+ "created_at_text": "Created at",
+ "modified_at_text": "Modified at",
+ "mimetype_text": "MIME Type",
+ "duration_text": "Duration",
+ "location_text": "Location",
+ "resolution_text": "Resolution",
+ "orientation_text": "Orientation",
+ "path_text": "Path",
+ "display_size_text": "Display Size",
+ "source_text": "Source"
}
\ No newline at end of file
diff --git a/app/lib/components/thumbnail_builder.dart b/app/lib/components/thumbnail_builder.dart
new file mode 100644
index 0000000..0c34678
--- /dev/null
+++ b/app/lib/components/thumbnail_builder.dart
@@ -0,0 +1,119 @@
+import 'dart:typed_data';
+import 'package:cached_network_image/cached_network_image.dart';
+import 'package:data/models/media/media.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:style/extensions/context_extensions.dart';
+import 'package:style/indicators/circular_progress_indicator.dart';
+
+class AppMediaThumbnail extends StatelessWidget {
+ final Object? heroTag;
+ final AppMedia media;
+ final Size size;
+ final double radius;
+ final Future? thumbnailByte;
+
+ const AppMediaThumbnail({
+ super.key,
+ required this.size,
+ this.heroTag,
+ this.radius = 4,
+ required this.thumbnailByte,
+ required this.media,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ if (media.sources.contains(AppMediaSource.local)) {
+ return FutureBuilder(
+ future: thumbnailByte,
+ builder: (context, snapshot) {
+ if (snapshot.connectionState == ConnectionState.done &&
+ snapshot.hasData) {
+ return ClipRRect(
+ borderRadius: BorderRadius.circular(radius),
+ child: Hero(
+ tag: heroTag ?? '',
+ child: Image.memory(
+ snapshot.data!,
+ height: size.height,
+ width: size.width,
+ fit: BoxFit.cover,
+ ),
+ ),
+ );
+ } else if (snapshot.hasError) {
+ return AppMediaErrorPlaceHolder(
+ size: size,
+ );
+ } else {
+ return AppMediaPlaceHolder(
+ showLoader: false,
+ size: size,
+ );
+ }
+ },
+ );
+ } else {
+ return Hero(
+ tag: heroTag ?? '',
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(radius),
+ child: CachedNetworkImage(
+ imageUrl: media.thumbnailLink ?? '',
+ width: size.width,
+ height: size.height,
+ fit: BoxFit.cover,
+ errorWidget: (context, url, error) => AppMediaErrorPlaceHolder(
+ size: size,
+ ),
+ progressIndicatorBuilder: (context, url, progress) =>
+ AppMediaPlaceHolder(
+ size: size,
+ value: progress.progress,
+ )),
+ ),
+ );
+ }
+ }
+}
+
+class AppMediaPlaceHolder extends StatelessWidget {
+ final double? value;
+ final Size? size;
+ final bool showLoader;
+
+ const AppMediaPlaceHolder(
+ {super.key, this.value, this.showLoader = true, this.size});
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ height: size?.height,
+ width: size?.width,
+ color: context.colorScheme.containerHighOnSurface,
+ alignment: Alignment.center,
+ child: showLoader ? AppCircularProgressIndicator(value: value) : null,
+ );
+ }
+}
+
+class AppMediaErrorPlaceHolder extends StatelessWidget {
+ final Size? size;
+
+ const AppMediaErrorPlaceHolder({super.key, this.size});
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ height: size?.height,
+ width: size?.width,
+ color: context.colorScheme.containerNormalOnSurface,
+ alignment: Alignment.center,
+ child: Icon(
+ CupertinoIcons.exclamationmark_circle,
+ color: context.colorScheme.onPrimary,
+ size: 32,
+ ),
+ );
+ }
+}
diff --git a/app/lib/domain/assets/assets_paths.dart b/app/lib/domain/assets/assets_paths.dart
index c4bd56a..332d3d7 100644
--- a/app/lib/domain/assets/assets_paths.dart
+++ b/app/lib/domain/assets/assets_paths.dart
@@ -9,5 +9,5 @@ class PathImages {
}
class PathIcons {
- String get googlePhotos => 'assets/images/icons/google_photos.svg';
+ String get googleDrive => 'assets/images/icons/google-drive.svg';
}
diff --git a/app/lib/ui/flow/home/components/app_media_item.dart b/app/lib/ui/flow/home/components/app_media_item.dart
index 12efc36..4cd07c9 100644
--- a/app/lib/ui/flow/home/components/app_media_item.dart
+++ b/app/lib/ui/flow/home/components/app_media_item.dart
@@ -1,6 +1,5 @@
-import 'dart:async';
import 'dart:typed_data';
-import 'package:cached_network_image/cached_network_image.dart';
+import 'package:cloud_gallery/components/thumbnail_builder.dart';
import 'package:cloud_gallery/domain/formatter/duration_formatter.dart';
import 'package:data/models/app_process/app_process.dart';
import 'package:data/models/media/media.dart';
@@ -35,7 +34,7 @@ class AppMediaItem extends StatefulWidget {
class _AppMediaItemState extends State
with AutomaticKeepAliveClientMixin {
- late Future thumbnailByte;
+ Future? thumbnailByte;
@override
void initState() {
@@ -93,64 +92,14 @@ class _AppMediaItemState extends State
Widget _buildMediaView(
{required BuildContext context, required BoxConstraints constraints}) {
- if (widget.media.sources.contains(AppMediaSource.local)) {
- return FutureBuilder(
- future: thumbnailByte,
- builder: (context, snapshot) {
- if (snapshot.connectionState == ConnectionState.done &&
- snapshot.hasData) {
- return Hero(
- tag: widget.media,
- child: Image.memory(
- snapshot.data!,
- width: constraints.maxWidth,
- height: constraints.maxHeight,
- fit: BoxFit.cover,
- ),
- );
- } else {
- return _buildPlaceholder(context: context, showLoader: false);
- }
- },
- );
- } else {
- return Hero(
- tag: widget.media,
- child: CachedNetworkImage(
- imageUrl: widget.media.thumbnailLink ?? '',
- width: constraints.maxWidth,
- height: constraints.maxHeight,
- fit: BoxFit.cover,
- errorWidget: (context, url, error) => _buildErrorWidget(context),
- progressIndicatorBuilder: (context, url, progress) =>
- _buildPlaceholder(
- context: context,
- value: progress.progress,
- )),
- );
- }
+ return AppMediaThumbnail(
+ size: constraints.biggest,
+ thumbnailByte: thumbnailByte,
+ media: widget.media,
+ heroTag: widget.media,
+ );
}
- Widget _buildPlaceholder(
- {required BuildContext context,
- double? value,
- bool showLoader = true}) =>
- Container(
- color: context.colorScheme.containerHighOnSurface,
- alignment: Alignment.center,
- child: showLoader ? AppCircularProgressIndicator(value: value) : null,
- );
-
- Widget _buildErrorWidget(BuildContext context) => Container(
- color: context.colorScheme.containerNormalOnSurface,
- alignment: Alignment.center,
- child: Icon(
- CupertinoIcons.exclamationmark_circle,
- color: context.colorScheme.onPrimary,
- size: 32,
- ),
- );
-
Widget _sourceIndicators({required BuildContext context}) {
return Row(
children: [
@@ -161,7 +110,7 @@ class _AppMediaItemState extends State
children: [
if (widget.media.sources.contains(AppMediaSource.googleDrive))
SvgPicture.asset(
- Assets.images.icons.googlePhotos,
+ Assets.images.icons.googleDrive,
height: 14,
width: 14,
),
diff --git a/app/lib/ui/flow/home/components/multi_selection_done_button.dart b/app/lib/ui/flow/home/components/multi_selection_done_button.dart
index f806095..32909b8 100644
--- a/app/lib/ui/flow/home/components/multi_selection_done_button.dart
+++ b/app/lib/ui/flow/home/components/multi_selection_done_button.dart
@@ -39,7 +39,7 @@ class MultiSelectionDoneButton extends ConsumerWidget {
if (showUploadToDriveButton)
AppSheetAction(
icon: SvgPicture.asset(
- Assets.images.icons.googlePhotos,
+ Assets.images.icons.googleDrive,
height: 24,
width: 24,
),
diff --git a/app/lib/ui/flow/home/home_screen_view_model.dart b/app/lib/ui/flow/home/home_screen_view_model.dart
index 2994fb4..3892933 100644
--- a/app/lib/ui/flow/home/home_screen_view_model.dart
+++ b/app/lib/ui/flow/home/home_screen_view_model.dart
@@ -3,7 +3,6 @@ import 'package:cloud_gallery/domain/extensions/map_extensions.dart';
import 'package:cloud_gallery/domain/extensions/media_list_extension.dart';
import 'package:data/models/app_process/app_process.dart';
import 'package:data/models/media/media.dart';
-import 'package:data/models/media/media_extension.dart';
import 'package:data/repositories/google_drive_process_repo.dart';
import 'package:data/services/auth_service.dart';
import 'package:data/services/google_drive_service.dart';
@@ -211,7 +210,9 @@ class HomeViewStateNotifier extends StateNotifier
List googleDriveMedia = [];
List uploadedMedia = [];
for (var media in driveMedias) {
- if (await media.isExist) {
+ if (media.path.trim().isNotEmpty &&
+ await _localMediaService.isLocalFileExist(
+ type: media.type, id: media.path)) {
uploadedMedia.add(media);
} else {
googleDriveMedia.add(media);
diff --git a/app/lib/ui/flow/home/home_view_model_helper_mixin.dart b/app/lib/ui/flow/home/home_view_model_helper_mixin.dart
index b258dea..9665c37 100644
--- a/app/lib/ui/flow/home/home_view_model_helper_mixin.dart
+++ b/app/lib/ui/flow/home/home_view_model_helper_mixin.dart
@@ -23,7 +23,7 @@ mixin HomeViewModelHelperMixin {
// Add common media to mergedMedias and remove them from the lists.
for (AppMedia localMedia in localMedias.toList()) {
googleDriveMedias
- .where((googleDriveMedia) => googleDriveMedia.path == localMedia.path)
+ .where((googleDriveMedia) => googleDriveMedia.path == localMedia.id)
.forEach((googleDriveMedia) {
localMedias.removeWhere((media) => media.id == localMedia.id);
@@ -73,8 +73,11 @@ mixin HomeViewModelHelperMixin {
}) {
final processIds = process.map((e) => e.id).toList();
return medias.map((key, value) {
- return MapEntry(key,
- value..replaceMediaRefInMedias(process: process, processIds: processIds));
+ return MapEntry(
+ key,
+ value
+ ..replaceMediaRefInMedias(
+ process: process, processIds: processIds));
});
}
}
diff --git a/app/lib/ui/flow/media_metadata_details/media_metadata_details.dart b/app/lib/ui/flow/media_metadata_details/media_metadata_details.dart
new file mode 100644
index 0000000..8f53390
--- /dev/null
+++ b/app/lib/ui/flow/media_metadata_details/media_metadata_details.dart
@@ -0,0 +1,175 @@
+import 'dart:typed_data';
+import 'package:cloud_gallery/components/app_page.dart';
+import 'package:cloud_gallery/components/thumbnail_builder.dart';
+import 'package:cloud_gallery/domain/assets/assets_paths.dart';
+import 'package:cloud_gallery/domain/extensions/context_extensions.dart';
+import 'package:cloud_gallery/domain/formatter/byte_formatter.dart';
+import 'package:cloud_gallery/domain/formatter/date_formatter.dart';
+import 'package:cloud_gallery/domain/formatter/duration_formatter.dart';
+import 'package:data/models/media/media.dart';
+import 'package:data/models/media/media_extension.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:style/extensions/context_extensions.dart';
+import 'package:style/text/app_text_style.dart';
+
+class MediaMetadataDetailsScreen extends StatefulWidget {
+ final AppMedia media;
+
+ const MediaMetadataDetailsScreen({super.key, required this.media});
+
+ @override
+ State createState() =>
+ _MediaMetadataDetailsScreenState();
+}
+
+class _MediaMetadataDetailsScreenState
+ extends State {
+ Future? thumbnailByte;
+
+ @override
+ void initState() {
+ if (widget.media.sources.contains(AppMediaSource.local)) {
+ thumbnailByte = widget.media.loadThumbnail();
+ }
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return AppPage(
+ title: '',
+ body: Builder(builder: (context) {
+ return Material(
+ color: Colors.transparent,
+ child: ListView(
+ padding: context.systemPadding,
+ children: [
+ Stack(
+ alignment: Alignment.center,
+ children: [
+ AppMediaThumbnail(
+ size: Size(context.mediaQuerySize.width, 200),
+ thumbnailByte: thumbnailByte,
+ media: widget.media,
+ radius: 0,
+ ),
+ if (widget.media.type.isVideo)
+ Icon(Icons.play_arrow_rounded,
+ size: 50, color: context.colorScheme.onPrimary),
+ ],
+ ),
+ const SizedBox(height: 16),
+ DetailsTile(
+ title: context.l10n.name_text,
+ subtitle: (widget.media.name?.trim().isNotEmpty ?? false)
+ ? widget.media.name!
+ : context.l10n.common_not_available,
+ ),
+ DetailsTile(
+ title: context.l10n.path_text,
+ subtitle: widget.media.path,
+ ),
+ DetailsTile(
+ title: context.l10n.created_at_text,
+ subtitle: widget.media.createdTime == null
+ ? context.l10n.common_not_available
+ : "${widget.media.createdTime?.format(context, DateFormatType.dayMonthYear)}, ${widget.media.createdTime?.format(context, DateFormatType.time)}",
+ ),
+ DetailsTile(
+ title: context.l10n.modified_at_text,
+ subtitle: widget.media.modifiedTime == null
+ ? context.l10n.common_not_available
+ : "${widget.media.modifiedTime?.format(context, DateFormatType.dayMonthYear)}, ${widget.media.modifiedTime?.format(context, DateFormatType.time)}",
+ ),
+ DetailsTile(
+ title: context.l10n.mimetype_text,
+ subtitle: widget.media.mimeType ??
+ context.l10n.common_not_available,
+ ),
+ DetailsTile(
+ title: context.l10n.size_text,
+ subtitle:
+ int.tryParse(widget.media.size ?? '')?.formatBytes ??
+ context.l10n.common_not_available,
+ ),
+ if (widget.media.type.isVideo)
+ DetailsTile(
+ title: context.l10n.duration_text,
+ subtitle: widget.media.videoDuration?.format ??
+ context.l10n.common_not_available,
+ ),
+ DetailsTile(
+ title: context.l10n.location_text,
+ subtitle: widget.media.latitude == null ||
+ widget.media.longitude == null
+ ? context.l10n.common_not_available
+ : '${widget.media.latitude}, ${widget.media.longitude}',
+ ),
+ DetailsTile(
+ title: context.l10n.orientation_text,
+ subtitle: widget.media.orientation?.name ?? 'N/A',
+ ),
+ DetailsTile(
+ title: context.l10n.resolution_text,
+ subtitle: widget.media.displayHeight == null ||
+ widget.media.displayWidth == null
+ ? context.l10n.common_not_available
+ : '${widget.media.displayWidth?.toInt()} x ${widget.media.displayHeight?.toInt()}',
+ ),
+ ListTile(
+ contentPadding: const EdgeInsets.symmetric(horizontal: 16),
+ dense: true,
+ title: Text(
+ context.l10n.source_text,
+ style: AppTextStyles.body.copyWith(
+ color: context.colorScheme.textPrimary,
+ ),
+ ),
+ subtitle: Row(
+ children: [
+ if (widget.media.sources.contains(AppMediaSource.local))
+ Icon(Icons.phone_android_rounded,
+ color: context.colorScheme.textSecondary,
+ size: 20),
+ if (widget.media.sources
+ .contains(AppMediaSource.googleDrive))
+ SvgPicture.asset(
+ Assets.images.icons.googleDrive,
+ width: 20,
+ )
+ ],
+ ))
+ ],
+ ),
+ );
+ }));
+ }
+}
+
+class DetailsTile extends StatelessWidget {
+ final String title;
+ final String subtitle;
+
+ const DetailsTile({super.key, required this.title, required this.subtitle});
+
+ @override
+ Widget build(BuildContext context) {
+ return ListTile(
+ contentPadding: const EdgeInsets.symmetric(horizontal: 16),
+ dense: true,
+ title: Text(
+ title,
+ style: AppTextStyles.body.copyWith(
+ color: context.colorScheme.textPrimary,
+ ),
+ ),
+ subtitle: Text(
+ subtitle,
+ style: AppTextStyles.body2.copyWith(
+ color: context.colorScheme.textSecondary,
+ ),
+ ),
+ );
+ }
+}
diff --git a/app/lib/ui/flow/media_preview/components/download_require_view.dart b/app/lib/ui/flow/media_preview/components/download_require_view.dart
index 9dafe1e..8981bec 100644
--- a/app/lib/ui/flow/media_preview/components/download_require_view.dart
+++ b/app/lib/ui/flow/media_preview/components/download_require_view.dart
@@ -30,7 +30,7 @@ class DownloadRequireView extends StatelessWidget {
child: Image.network(
height: double.infinity,
width: double.infinity,
- media.thumbnailLink!,
+ media.thumbnailLink ?? '',
fit: BoxFit.cover,
),
),
diff --git a/app/lib/ui/flow/media_preview/components/top_bar.dart b/app/lib/ui/flow/media_preview/components/top_bar.dart
index 2c5cc58..58cea83 100644
--- a/app/lib/ui/flow/media_preview/components/top_bar.dart
+++ b/app/lib/ui/flow/media_preview/components/top_bar.dart
@@ -1,5 +1,6 @@
import 'dart:io';
import 'package:cloud_gallery/domain/extensions/context_extensions.dart';
+import 'package:cloud_gallery/ui/navigation/app_router.dart';
import 'package:data/models/media/media_extension.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@@ -39,11 +40,11 @@ class PreviewTopBar extends StatelessWidget {
actions: [
ActionButton(
onPressed: () {
- ///TODO: media details
+ AppRouter.mediaMetaDataDetails(media: media).push(context);
},
icon: Icon(
CupertinoIcons.info,
- color: context.colorScheme.textSecondary,
+ color: context.colorScheme.textPrimary,
size: 22,
),
),
@@ -76,7 +77,7 @@ class PreviewTopBar extends StatelessWidget {
child: Row(
children: [
SvgPicture.asset(
- Assets.images.icons.googlePhotos,
+ Assets.images.icons.googleDrive,
width: 20,
height: 20,
),
diff --git a/app/lib/ui/flow/media_transfer/components/transfer_item.dart b/app/lib/ui/flow/media_transfer/components/transfer_item.dart
index aff7a6a..017336f 100644
--- a/app/lib/ui/flow/media_transfer/components/transfer_item.dart
+++ b/app/lib/ui/flow/media_transfer/components/transfer_item.dart
@@ -1,5 +1,4 @@
import 'dart:typed_data';
-import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_gallery/domain/extensions/context_extensions.dart';
import 'package:cloud_gallery/domain/formatter/byte_formatter.dart';
import 'package:data/models/app_process/app_process.dart';
@@ -10,8 +9,8 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:style/buttons/action_button.dart';
import 'package:style/extensions/context_extensions.dart';
-import 'package:style/indicators/circular_progress_indicator.dart';
import 'package:style/text/app_text_style.dart';
+import '../../../../components/thumbnail_builder.dart';
class ProcessItem extends StatefulWidget {
final AppProcess process;
@@ -25,6 +24,16 @@ class ProcessItem extends StatefulWidget {
}
class _ProcessItemState extends State {
+ Future? thumbnailByte;
+
+ @override
+ void initState() {
+ if (widget.process.media.sources.contains(AppMediaSource.local)) {
+ thumbnailByte =
+ widget.process.media.loadThumbnail(size: const Size(80, 80));
+ }
+ super.initState();
+ }
@override
Widget build(BuildContext context) {
@@ -56,7 +65,8 @@ class _ProcessItemState extends State {
color: context.colorScheme.textSecondary,
),
),
- if (widget.process.progress != null && widget.process.status.isProcessing) ...[
+ if (widget.process.progress != null &&
+ widget.process.status.isProcessing) ...[
LinearProgressIndicator(
value: widget.process.progress?.percentageInPoint,
backgroundColor: context.colorScheme.outline,
@@ -96,100 +106,10 @@ class _ProcessItemState extends State {
}
Widget _buildThumbnailView({required BuildContext context}) {
- if (widget.process.media.sources.contains(AppMediaSource.local)) {
- return FutureByteLoader(
- bytes: widget.process.media.loadThumbnail(size: const Size(100, 100)),
- builder: (context, bytes) => Container(
- width: 60,
- height: 60,
- decoration: BoxDecoration(
- color: context.colorScheme.containerHighOnSurface,
- borderRadius: BorderRadius.circular(4),
- image: DecorationImage(
- image: MemoryImage(bytes!),
- fit: BoxFit.cover,
- ),
- ),
- ),
- errorWidget: (context, error) => _buildErrorWidget(context),
- placeholder: (context) => _buildPlaceholder(context: context),
- );
- } else {
- return CachedNetworkImage(
- imageUrl: widget.process.media.thumbnailLink!,
- width: 80,
- height: 80,
- fit: BoxFit.cover,
- errorWidget: (context, url, error) => _buildErrorWidget(context),
- progressIndicatorBuilder: (context, url, progress) =>
- _buildPlaceholder(
- context: context,
- value: progress.progress,
- ));
- }
- }
-
- Widget _buildPlaceholder(
- {required BuildContext context,
- double? value,
- bool showLoader = true}) =>
- Container(
- color: context.colorScheme.containerHighOnSurface,
- alignment: Alignment.center,
- child: showLoader ? AppCircularProgressIndicator(value: value) : null,
- );
-
- Widget _buildErrorWidget(BuildContext context) => Container(
- color: context.colorScheme.containerNormalOnSurface,
- alignment: Alignment.center,
- child: Icon(
- CupertinoIcons.exclamationmark_circle,
- color: context.colorScheme.onPrimary,
- size: 32,
- ),
- );
-}
-
-class FutureByteLoader extends StatefulWidget {
- final Future bytes;
- final Widget Function(BuildContext context, Uint8List? bytes) builder;
- final Widget Function(BuildContext context) placeholder;
- final Widget Function(BuildContext context, Object? error) errorWidget;
-
- const FutureByteLoader(
- {super.key,
- required this.bytes,
- required this.builder,
- required this.placeholder,
- required this.errorWidget});
-
- @override
- State createState() => _FutureByteLoaderState();
-}
-
-class _FutureByteLoaderState extends State {
- late Future bytes;
-
- @override
- void initState() {
- bytes = widget.bytes;
- super.initState();
- }
-
- @override
- Widget build(BuildContext context) {
- return FutureBuilder(
- future: bytes,
- builder: (context, snapshot) {
- if (snapshot.connectionState == ConnectionState.done &&
- snapshot.hasData) {
- return widget.builder(context, snapshot.data);
- } else if (snapshot.hasError) {
- return widget.errorWidget(context, snapshot.error);
- } else {
- return widget.placeholder(context);
- }
- },
+ return AppMediaThumbnail(
+ size: const Size(80, 80),
+ thumbnailByte: thumbnailByte,
+ media: widget.process.media,
);
}
}
diff --git a/app/lib/ui/navigation/app_router.dart b/app/lib/ui/navigation/app_router.dart
index 4fc3f77..0524095 100644
--- a/app/lib/ui/navigation/app_router.dart
+++ b/app/lib/ui/navigation/app_router.dart
@@ -5,6 +5,7 @@ import 'package:data/models/media/media.dart';
import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart';
import '../flow/home/home_screen.dart';
+import '../flow/media_metadata_details/media_metadata_details.dart';
import '../flow/media_preview/media_preview_screen.dart';
import 'app_route.dart';
@@ -39,11 +40,24 @@ class AppRouter {
),
);
+ static AppRoute mediaMetaDataDetails(
+ {required AppMedia media}) =>
+ AppRoute(
+ AppRoutePath.metaDataDetails,
+ builder: (context) => MediaMetadataDetailsScreen(
+ media: media,
+ ),
+ );
+
static final routes = [
home.goRoute,
onBoard.goRoute,
accounts.goRoute,
mediaTransfer.goRoute,
+ GoRoute(
+ path: AppRoutePath.metaDataDetails,
+ builder: (context, state) => state.widget(context),
+ ),
GoRoute(
path: AppRoutePath.preview,
pageBuilder: (context, state) {
@@ -66,4 +80,5 @@ class AppRoutePath {
static const accounts = '/accounts';
static const preview = '/preview';
static const transfer = '/transfer';
+ static const metaDataDetails = '/metadata-details';
}
diff --git a/data/lib/models/media/media.dart b/data/lib/models/media/media.dart
index f7d629c..4a7bf67 100644
--- a/data/lib/models/media/media.dart
+++ b/data/lib/models/media/media.dart
@@ -124,7 +124,7 @@ class AppMedia with _$AppMedia {
: null;
return AppMedia(
id: file.id!,
- path: file.description ?? file.thumbnailLink ?? '',
+ path: file.description ?? '',
thumbnailLink: file.thumbnailLink,
name: file.name,
driveMediaRefId: file.id,
diff --git a/data/lib/models/media/media_extension.dart b/data/lib/models/media/media_extension.dart
index be7857a..8707149 100644
--- a/data/lib/models/media/media_extension.dart
+++ b/data/lib/models/media/media_extension.dart
@@ -1,15 +1,10 @@
import 'dart:async';
-import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:photo_manager/photo_manager.dart';
import 'media.dart';
extension AppMediaExtension on AppMedia {
- Future get isExist async {
- return await File(path).exists();
- }
-
Future loadThumbnail({Size size = const Size(300, 300)}) async {
var rootToken = RootIsolateToken.instance!;
final ThumbNailParameter thumbNailParameter =
diff --git a/data/lib/services/google_drive_service.dart b/data/lib/services/google_drive_service.dart
index 6191b62..d4fc2f7 100644
--- a/data/lib/services/google_drive_service.dart
+++ b/data/lib/services/google_drive_service.dart
@@ -103,7 +103,7 @@ class GoogleDriveService {
final file = drive.File(
name: media.name ?? localFile.path.split('/').last,
- description: media.path,
+ description: media.id,
parents: [folderID],
);
final fileLength = localFile.lengthSync();
diff --git a/data/lib/services/local_media_service.dart b/data/lib/services/local_media_service.dart
index 501c3d2..7a1dac0 100644
--- a/data/lib/services/local_media_service.dart
+++ b/data/lib/services/local_media_service.dart
@@ -15,6 +15,11 @@ final localMediaServiceProvider = Provider(
class LocalMediaService {
const LocalMediaService();
+
+ Future isLocalFileExist({required AppMediaType type, required String id}) async {
+ return await AssetEntity(id: id, typeInt: type.index, width: 0, height: 0).isLocallyAvailable();
+ }
+
Future requestPermission() async {
final state = await PhotoManager.requestPermissionExtend();
return state.hasAccess;