mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 08:46:18 +01:00
Set/unset favorite in viewer
This commit is contained in:
parent
3b8f0f09d4
commit
abe997f274
7 changed files with 192 additions and 8 deletions
|
@ -575,6 +575,7 @@ class FileRepo {
|
|||
OrNull<Metadata>? metadata,
|
||||
OrNull<bool>? isArchived,
|
||||
OrNull<DateTime>? overrideDateTime,
|
||||
bool? favorite,
|
||||
}) =>
|
||||
dataSrc.updateProperty(
|
||||
account,
|
||||
|
@ -582,6 +583,7 @@ class FileRepo {
|
|||
metadata: metadata,
|
||||
isArchived: isArchived,
|
||||
overrideDateTime: overrideDateTime,
|
||||
favorite: favorite,
|
||||
);
|
||||
|
||||
/// See [FileDataSource.copy]
|
||||
|
@ -642,6 +644,7 @@ abstract class FileDataSource {
|
|||
OrNull<Metadata>? metadata,
|
||||
OrNull<bool>? isArchived,
|
||||
OrNull<DateTime>? overrideDateTime,
|
||||
bool? favorite,
|
||||
});
|
||||
|
||||
/// Copy [f] to [destination]
|
||||
|
|
|
@ -148,6 +148,7 @@ class FileWebdavDataSource implements FileDataSource {
|
|||
OrNull<Metadata>? metadata,
|
||||
OrNull<bool>? isArchived,
|
||||
OrNull<DateTime>? overrideDateTime,
|
||||
bool? favorite,
|
||||
}) async {
|
||||
_log.info("[updateProperty] ${f.path}");
|
||||
if (metadata?.obj != null && metadata!.obj!.fileEtag != f.etag) {
|
||||
|
@ -161,6 +162,7 @@ class FileWebdavDataSource implements FileDataSource {
|
|||
if (overrideDateTime?.obj != null)
|
||||
"app:override-date-time":
|
||||
overrideDateTime!.obj!.toUtc().toIso8601String(),
|
||||
if (favorite != null) "oc:favorite": favorite ? 1 : 0,
|
||||
};
|
||||
final removeProps = [
|
||||
if (OrNull.isSetNull(metadata)) "app:metadata",
|
||||
|
@ -171,6 +173,7 @@ class FileWebdavDataSource implements FileDataSource {
|
|||
path: f.path,
|
||||
namespaces: {
|
||||
"com.nkming.nc_photos": "app",
|
||||
"http://owncloud.org/ns": "oc",
|
||||
},
|
||||
set: setProps.isNotEmpty ? setProps : null,
|
||||
remove: removeProps.isNotEmpty ? removeProps : null,
|
||||
|
@ -373,6 +376,7 @@ class FileAppDbDataSource implements FileDataSource {
|
|||
OrNull<Metadata>? metadata,
|
||||
OrNull<bool>? isArchived,
|
||||
OrNull<DateTime>? overrideDateTime,
|
||||
bool? favorite,
|
||||
}) {
|
||||
_log.info("[updateProperty] ${f.path}");
|
||||
return appDb.use((db) async {
|
||||
|
@ -384,6 +388,7 @@ class FileAppDbDataSource implements FileDataSource {
|
|||
metadata: metadata,
|
||||
isArchived: isArchived,
|
||||
overrideDateTime: overrideDateTime,
|
||||
isFavorite: favorite,
|
||||
);
|
||||
final fileStore = transaction.objectStore(AppDb.file2StoreName);
|
||||
await fileStore.put(AppDbFile2Entry.fromFile(account, newFile).toJson(),
|
||||
|
@ -501,6 +506,7 @@ class FileCachedDataSource implements FileDataSource {
|
|||
OrNull<Metadata>? metadata,
|
||||
OrNull<bool>? isArchived,
|
||||
OrNull<DateTime>? overrideDateTime,
|
||||
bool? favorite,
|
||||
}) async {
|
||||
await _remoteSrc
|
||||
.updateProperty(
|
||||
|
@ -509,6 +515,7 @@ class FileCachedDataSource implements FileDataSource {
|
|||
metadata: metadata,
|
||||
isArchived: isArchived,
|
||||
overrideDateTime: overrideDateTime,
|
||||
favorite: favorite,
|
||||
)
|
||||
.then((_) => _appDbSrc.updateProperty(
|
||||
account,
|
||||
|
@ -516,6 +523,7 @@ class FileCachedDataSource implements FileDataSource {
|
|||
metadata: metadata,
|
||||
isArchived: isArchived,
|
||||
overrideDateTime: overrideDateTime,
|
||||
favorite: favorite,
|
||||
));
|
||||
|
||||
// generate a new random token
|
||||
|
|
|
@ -1127,6 +1127,30 @@
|
|||
"@collectionFavoritesLabel": {
|
||||
"description": "Browse photos added to favorites"
|
||||
},
|
||||
"favoriteTooltip": "Favorite",
|
||||
"@favoriteTooltip": {
|
||||
"description": "Add photo to favorites"
|
||||
},
|
||||
"favoriteSuccessNotification": "Added to favorites",
|
||||
"@favoriteSuccessNotification": {
|
||||
"description": "Successfully added photos to favorites"
|
||||
},
|
||||
"favoriteFailureNotification": "Failed adding to favorites",
|
||||
"@favoriteFailureNotification": {
|
||||
"description": "Failed adding photos to favorites"
|
||||
},
|
||||
"unfavoriteTooltip": "Unfavorite",
|
||||
"@unfavoriteTooltip": {
|
||||
"description": "Remove photo to favorites"
|
||||
},
|
||||
"unfavoriteSuccessNotification": "Removed from favorites",
|
||||
"@unfavoriteSuccessNotification": {
|
||||
"description": "Successfully removed photos from favorites"
|
||||
},
|
||||
"unfavoriteFailureNotification": "Failed removing from favorites",
|
||||
"@unfavoriteFailureNotification": {
|
||||
"description": "Failed removing photos from favorites"
|
||||
},
|
||||
|
||||
"errorUnauthenticated": "Unauthenticated access. Please sign-in again if the problem continues",
|
||||
"@errorUnauthenticated": {
|
||||
|
|
|
@ -72,6 +72,12 @@
|
|||
"convertAlbumConfirmationDialogContent",
|
||||
"convertAlbumSuccessNotification",
|
||||
"collectionFavoritesLabel",
|
||||
"favoriteTooltip",
|
||||
"favoriteSuccessNotification",
|
||||
"favoriteFailureNotification",
|
||||
"unfavoriteTooltip",
|
||||
"unfavoriteSuccessNotification",
|
||||
"unfavoriteFailureNotification",
|
||||
"errorAlbumDowngrade"
|
||||
],
|
||||
|
||||
|
@ -162,6 +168,12 @@
|
|||
"convertAlbumConfirmationDialogContent",
|
||||
"convertAlbumSuccessNotification",
|
||||
"collectionFavoritesLabel",
|
||||
"favoriteTooltip",
|
||||
"favoriteSuccessNotification",
|
||||
"favoriteFailureNotification",
|
||||
"unfavoriteTooltip",
|
||||
"unfavoriteSuccessNotification",
|
||||
"unfavoriteFailureNotification",
|
||||
"errorAlbumDowngrade"
|
||||
],
|
||||
|
||||
|
@ -307,6 +319,12 @@
|
|||
"convertAlbumConfirmationDialogContent",
|
||||
"convertAlbumSuccessNotification",
|
||||
"collectionFavoritesLabel",
|
||||
"favoriteTooltip",
|
||||
"favoriteSuccessNotification",
|
||||
"favoriteFailureNotification",
|
||||
"unfavoriteTooltip",
|
||||
"unfavoriteSuccessNotification",
|
||||
"unfavoriteFailureNotification",
|
||||
"errorAlbumDowngrade"
|
||||
],
|
||||
|
||||
|
@ -335,6 +353,12 @@
|
|||
"convertAlbumConfirmationDialogContent",
|
||||
"convertAlbumSuccessNotification",
|
||||
"collectionFavoritesLabel",
|
||||
"favoriteTooltip",
|
||||
"favoriteSuccessNotification",
|
||||
"favoriteFailureNotification",
|
||||
"unfavoriteTooltip",
|
||||
"unfavoriteSuccessNotification",
|
||||
"unfavoriteFailureNotification",
|
||||
"errorAlbumDowngrade"
|
||||
],
|
||||
|
||||
|
@ -347,7 +371,13 @@
|
|||
"convertAlbumTooltip",
|
||||
"convertAlbumConfirmationDialogContent",
|
||||
"convertAlbumSuccessNotification",
|
||||
"collectionFavoritesLabel"
|
||||
"collectionFavoritesLabel",
|
||||
"favoriteTooltip",
|
||||
"favoriteSuccessNotification",
|
||||
"favoriteFailureNotification",
|
||||
"unfavoriteTooltip",
|
||||
"unfavoriteSuccessNotification",
|
||||
"unfavoriteFailureNotification"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
|
@ -472,6 +502,12 @@
|
|||
"convertAlbumConfirmationDialogContent",
|
||||
"convertAlbumSuccessNotification",
|
||||
"collectionFavoritesLabel",
|
||||
"favoriteTooltip",
|
||||
"favoriteSuccessNotification",
|
||||
"favoriteFailureNotification",
|
||||
"unfavoriteTooltip",
|
||||
"unfavoriteSuccessNotification",
|
||||
"unfavoriteFailureNotification",
|
||||
"errorAlbumDowngrade"
|
||||
],
|
||||
|
||||
|
@ -484,7 +520,13 @@
|
|||
"convertAlbumTooltip",
|
||||
"convertAlbumConfirmationDialogContent",
|
||||
"convertAlbumSuccessNotification",
|
||||
"collectionFavoritesLabel"
|
||||
"collectionFavoritesLabel",
|
||||
"favoriteTooltip",
|
||||
"favoriteSuccessNotification",
|
||||
"favoriteFailureNotification",
|
||||
"unfavoriteTooltip",
|
||||
"unfavoriteSuccessNotification",
|
||||
"unfavoriteFailureNotification"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
|
@ -582,6 +624,12 @@
|
|||
"convertAlbumConfirmationDialogContent",
|
||||
"convertAlbumSuccessNotification",
|
||||
"collectionFavoritesLabel",
|
||||
"favoriteTooltip",
|
||||
"favoriteSuccessNotification",
|
||||
"favoriteFailureNotification",
|
||||
"unfavoriteTooltip",
|
||||
"unfavoriteSuccessNotification",
|
||||
"unfavoriteFailureNotification",
|
||||
"errorAlbumDowngrade"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -15,8 +15,12 @@ class UpdateProperty {
|
|||
OrNull<Metadata>? metadata,
|
||||
OrNull<bool>? isArchived,
|
||||
OrNull<DateTime>? overrideDateTime,
|
||||
bool? favorite,
|
||||
}) async {
|
||||
if (metadata == null && isArchived == null && overrideDateTime == null) {
|
||||
if (metadata == null &&
|
||||
isArchived == null &&
|
||||
overrideDateTime == null &&
|
||||
favorite == null) {
|
||||
// ?
|
||||
_log.warning("[call] Nothing to update");
|
||||
return;
|
||||
|
@ -32,6 +36,7 @@ class UpdateProperty {
|
|||
metadata: metadata,
|
||||
isArchived: isArchived,
|
||||
overrideDateTime: overrideDateTime,
|
||||
favorite: favorite,
|
||||
);
|
||||
|
||||
int properties = 0;
|
||||
|
@ -44,6 +49,9 @@ class UpdateProperty {
|
|||
if (overrideDateTime != null) {
|
||||
properties |= FilePropertyUpdatedEvent.propOverrideDateTime;
|
||||
}
|
||||
if (favorite != null) {
|
||||
properties |= FilePropertyUpdatedEvent.propFavorite;
|
||||
}
|
||||
assert(properties != 0);
|
||||
KiwiContainer()
|
||||
.resolve<EventBus>()
|
||||
|
|
|
@ -5,17 +5,21 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:kiwi/kiwi.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/di_container.dart';
|
||||
import 'package:nc_photos/download_handler.dart';
|
||||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/notified_action.dart';
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/share_handler.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/update_property.dart';
|
||||
import 'package:nc_photos/widget/animated_visibility.dart';
|
||||
import 'package:nc_photos/widget/disposable.dart';
|
||||
import 'package:nc_photos/widget/handler/remove_selection_handler.dart';
|
||||
|
@ -125,6 +129,9 @@ class _ViewerState extends State<Viewer>
|
|||
}
|
||||
|
||||
Widget _buildAppBar(BuildContext context) {
|
||||
final index =
|
||||
_isViewerLoaded ? _viewerController.currentPage : widget.startIndex;
|
||||
final file = widget.streamFiles[index];
|
||||
return Wrap(
|
||||
children: [
|
||||
AnimatedVisibility(
|
||||
|
@ -151,12 +158,25 @@ class _ViewerState extends State<Viewer>
|
|||
shadowColor: Colors.transparent,
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
actions: [
|
||||
if (!_isDetailPaneActive && _canOpenDetailPane())
|
||||
if (!_isDetailPaneActive && _canOpenDetailPane()) ...[
|
||||
(_pageStates[index]?.favoriteOverride ?? file.isFavorite) ==
|
||||
true
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.star),
|
||||
tooltip: L10n.global().unfavoriteTooltip,
|
||||
onPressed: () => _onUnfavoritePressed(index),
|
||||
)
|
||||
: IconButton(
|
||||
icon: const Icon(Icons.star_border),
|
||||
tooltip: L10n.global().favoriteTooltip,
|
||||
onPressed: () => _onFavoritePressed(index),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
tooltip: L10n.global().detailsTooltip,
|
||||
onPressed: _onDetailsPressed,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
|
@ -454,6 +474,72 @@ class _ViewerState extends State<Viewer>
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _onFavoritePressed(int index) async {
|
||||
if (_pageStates[index]!.isProcessingFavorite) {
|
||||
_log.fine("[_onFavoritePressed] Process ongoing, ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
final file = widget.streamFiles[_viewerController.currentPage];
|
||||
final c = KiwiContainer().resolve<DiContainer>();
|
||||
setState(() {
|
||||
_pageStates[index]!.favoriteOverride = true;
|
||||
});
|
||||
_pageStates[index]!.isProcessingFavorite = true;
|
||||
try {
|
||||
await NotifiedAction(
|
||||
() => UpdateProperty(c.fileRepo)(
|
||||
widget.account,
|
||||
file,
|
||||
favorite: true,
|
||||
),
|
||||
null,
|
||||
L10n.global().favoriteSuccessNotification,
|
||||
failureText: L10n.global().favoriteFailureNotification,
|
||||
)();
|
||||
} catch (e, stackTrace) {
|
||||
_log.shout(
|
||||
"[_onFavoritePressed] Failed while UpdateProperty", e, stackTrace);
|
||||
setState(() {
|
||||
_pageStates[index]!.favoriteOverride = false;
|
||||
});
|
||||
}
|
||||
_pageStates[index]!.isProcessingFavorite = false;
|
||||
}
|
||||
|
||||
Future<void> _onUnfavoritePressed(int index) async {
|
||||
if (_pageStates[index]!.isProcessingFavorite) {
|
||||
_log.fine("[_onUnfavoritePressed] Process ongoing, ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
final file = widget.streamFiles[_viewerController.currentPage];
|
||||
final c = KiwiContainer().resolve<DiContainer>();
|
||||
setState(() {
|
||||
_pageStates[index]!.favoriteOverride = false;
|
||||
});
|
||||
_pageStates[index]!.isProcessingFavorite = true;
|
||||
try {
|
||||
await NotifiedAction(
|
||||
() => UpdateProperty(c.fileRepo)(
|
||||
widget.account,
|
||||
file,
|
||||
favorite: false,
|
||||
),
|
||||
null,
|
||||
L10n.global().unfavoriteSuccessNotification,
|
||||
failureText: L10n.global().unfavoriteFailureNotification,
|
||||
)();
|
||||
} catch (e, stackTrace) {
|
||||
_log.shout(
|
||||
"[_onUnfavoritePressed] Failed while UpdateProperty", e, stackTrace);
|
||||
setState(() {
|
||||
_pageStates[index]!.favoriteOverride = true;
|
||||
});
|
||||
}
|
||||
_pageStates[index]!.isProcessingFavorite = false;
|
||||
}
|
||||
|
||||
void _onDetailsPressed() {
|
||||
if (!_isDetailPaneActive) {
|
||||
setState(() {
|
||||
|
@ -614,4 +700,7 @@ class _PageState {
|
|||
ScrollController scrollController;
|
||||
double? itemHeight;
|
||||
bool hasLoaded = false;
|
||||
|
||||
bool isProcessingFavorite = false;
|
||||
bool? favoriteOverride;
|
||||
}
|
||||
|
|
|
@ -242,10 +242,14 @@ class MockFileRepo implements FileRepo {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> updateProperty(Account account, File file,
|
||||
{OrNull<Metadata>? metadata,
|
||||
OrNull<bool>? isArchived,
|
||||
OrNull<DateTime>? overrideDateTime}) {
|
||||
Future<void> updateProperty(
|
||||
Account account,
|
||||
File file, {
|
||||
OrNull<Metadata>? metadata,
|
||||
OrNull<bool>? isArchived,
|
||||
OrNull<DateTime>? overrideDateTime,
|
||||
bool? favorite,
|
||||
}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue