List files shared with you in Sharing

This commit is contained in:
Ming Ming 2021-10-12 01:03:37 +08:00
parent 50ba293345
commit afd859d414
8 changed files with 108 additions and 19 deletions

View file

@ -538,10 +538,12 @@ class _OcsFilesSharingShares {
/// Get Shares from a specific file or folder /// Get Shares from a specific file or folder
/// ///
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#get-shares-from-a-specific-file-or-folder /// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#get-shares-from-a-specific-file-or-folder
/// See: https://doc.owncloud.com/server/latest/developer_manual/core/apis/ocs-share-api.html#get-all-shares
Future<Response> get({ Future<Response> get({
String? path, String? path,
bool? reshares, bool? reshares,
bool? subfiles, bool? subfiles,
bool? sharedWithMe,
}) async { }) async {
try { try {
return await _filesSharing._ocs._api.request( return await _filesSharing._ocs._api.request(
@ -555,6 +557,7 @@ class _OcsFilesSharingShares {
if (path != null) "path": path, if (path != null) "path": path,
if (reshares != null) "reshares": reshares.toString(), if (reshares != null) "reshares": reshares.toString(),
if (subfiles != null) "subfiles": subfiles.toString(), if (subfiles != null) "subfiles": subfiles.toString(),
if (sharedWithMe != null) "shared_with_me": sharedWithMe.toString(),
}, },
); );
} catch (e) { } catch (e) {

View file

@ -174,6 +174,15 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
} }
Future<List<ListSharingItem>> _query(ListSharingBlocQuery ev) async { Future<List<ListSharingItem>> _query(ListSharingBlocQuery ev) async {
return (await Future.wait([
_querySharesByMe(ev),
_querySharesWithMe(ev),
]))
.reduce((value, element) => value + element);
}
Future<List<ListSharingItem>> _querySharesByMe(
ListSharingBlocQuery ev) async {
final shareRepo = ShareRepo(ShareRemoteDataSource()); final shareRepo = ShareRepo(ShareRemoteDataSource());
final shares = await shareRepo.listAll(ev.account); final shares = await shareRepo.listAll(ev.account);
final futures = shares.map((e) async { final futures = shares.map((e) async {
@ -206,7 +215,32 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
final file = await FindFile()(ev.account, e.itemSource); final file = await FindFile()(ev.account, e.itemSource);
return ListSharingItem(e, file); return ListSharingItem(e, file);
} catch (_) { } catch (_) {
_log.warning("[_query] File not found: ${e.itemSource}"); _log.warning("[_querySharesByMe] File not found: ${e.itemSource}");
return null;
}
});
return (await Future.wait(futures)).whereType<ListSharingItem>().toList();
}
Future<List<ListSharingItem>> _querySharesWithMe(
ListSharingBlocQuery ev) async {
final shareRepo = ShareRepo(ShareRemoteDataSource());
final shares = await shareRepo.reverseListAll(ev.account);
final futures = shares.map((e) async {
if (!file_util.isSupportedMime(e.mimeType)) {
return null;
}
if (ev.account.roots
.every((r) => r.isNotEmpty && !e.path.startsWith("/$r/"))) {
// ignore files not under root dirs
return null;
}
try {
final file = await FindFile()(ev.account, e.itemSource);
return ListSharingItem(e, file);
} catch (_) {
_log.warning("[_querySharesWithMe] File not found: ${e.itemSource}");
return null; return null;
} }
}); });

View file

@ -88,6 +88,8 @@ class Share with EquatableMixin {
required this.id, required this.id,
required this.shareType, required this.shareType,
required this.stime, required this.stime,
required this.uidOwner,
required this.displaynameOwner,
required String path, required String path,
required this.itemType, required this.itemType,
required this.mimeType, required this.mimeType,
@ -103,6 +105,8 @@ class Share with EquatableMixin {
"id: $id, " "id: $id, "
"shareType: $shareType, " "shareType: $shareType, "
"stime: $stime, " "stime: $stime, "
"uidOwner: $uidOwner, "
"displaynameOwner: $displaynameOwner, "
"path: $path, " "path: $path, "
"itemType: $itemType, " "itemType: $itemType, "
"mimeType: $mimeType, " "mimeType: $mimeType, "
@ -118,6 +122,8 @@ class Share with EquatableMixin {
id, id,
shareType, shareType,
stime, stime,
uidOwner,
displaynameOwner,
path, path,
itemType, itemType,
mimeType, mimeType,
@ -131,6 +137,8 @@ class Share with EquatableMixin {
final String id; final String id;
final ShareType shareType; final ShareType shareType;
final DateTime stime; final DateTime stime;
final String uidOwner;
final String displaynameOwner;
final String path; final String path;
final ShareItemType itemType; final ShareItemType itemType;
final String mimeType; final String mimeType;
@ -158,6 +166,10 @@ class ShareRepo {
/// See [ShareDataSource.listAll] /// See [ShareDataSource.listAll]
Future<List<Share>> listAll(Account account) => dataSrc.listAll(account); Future<List<Share>> listAll(Account account) => dataSrc.listAll(account);
/// See [ShareDataSource.reverseListAll]
Future<List<Share>> reverseListAll(Account account) =>
dataSrc.reverseListAll(account);
/// See [ShareDataSource.create] /// See [ShareDataSource.create]
Future<Share> create(Account account, File file, String shareWith) => Future<Share> create(Account account, File file, String shareWith) =>
dataSrc.create(account, file, shareWith); dataSrc.create(account, file, shareWith);
@ -187,6 +199,9 @@ abstract class ShareDataSource {
/// List all shares from a given user /// List all shares from a given user
Future<List<Share>> listAll(Account account); Future<List<Share>> listAll(Account account);
/// List all shares by other users with a given user
Future<List<Share>> reverseListAll(Account account);
/// Share a file/folder with a user /// Share a file/folder with a user
Future<Share> create(Account account, File file, String shareWith); Future<Share> create(Account account, File file, String shareWith);

View file

@ -6,6 +6,7 @@ import 'package:nc_photos/api/api.dart';
import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/share.dart'; import 'package:nc_photos/entity/share.dart';
import 'package:nc_photos/exception.dart'; import 'package:nc_photos/exception.dart';
import 'package:nc_photos/iterable_extension.dart';
import 'package:nc_photos/type.dart'; import 'package:nc_photos/type.dart';
class ShareRemoteDataSource implements ShareDataSource { class ShareRemoteDataSource implements ShareDataSource {
@ -35,6 +36,15 @@ class ShareRemoteDataSource implements ShareDataSource {
return _onListResult(response); return _onListResult(response);
} }
@override
reverseListAll(Account account) async {
_log.info("[reverseListAll] $account");
final response = await Api(account).ocs().filesSharing().shares().get(
sharedWithMe: true,
);
return _onListResult(response);
}
@override @override
create(Account account, File file, String shareWith) async { create(Account account, File file, String shareWith) async {
_log.info("[create] Share '${file.path}' with '$shareWith'"); _log.info("[create] Share '${file.path}' with '$shareWith'");
@ -127,8 +137,9 @@ class _ShareParser {
return Share( return Share(
id: json["id"], id: json["id"],
shareType: shareType, shareType: shareType,
stime: stime: DateTime.fromMillisecondsSinceEpoch(json["stime"] * 1000),
DateTime.fromMillisecondsSinceEpoch(json["stime"] * 1000), uidOwner: json["uid_owner"],
displaynameOwner: json["displayname_owner"],
path: json["path"], path: json["path"],
itemType: itemType, itemType: itemType,
mimeType: json["mimetype"], mimeType: json["mimetype"],

View file

@ -869,6 +869,19 @@
} }
} }
}, },
"fileLastSharedByOthersDescription": "{user} shared with you on {date}",
"@fileLastSharedByOthersDescription": {
"description": "The date when this file was shared with you",
"placeholders": {
"user": {
"example": "Alice"
},
"date": {
"example": "Jan 1, 2021",
"description": "The date string is formatted according to the current locale"
}
}
},
"sharedWithLabel": "Shared with", "sharedWithLabel": "Shared with",
"@sharedWithLabel": { "@sharedWithLabel": {
"description": "A list of users or links where this file is sharing with" "description": "A list of users or links where this file is sharing with"

View file

@ -8,6 +8,7 @@
"sortOptionManualLabel", "sortOptionManualLabel",
"collectionSharingLabel", "collectionSharingLabel",
"fileLastSharedDescription", "fileLastSharedDescription",
"fileLastSharedByOthersDescription",
"sharedWithLabel", "sharedWithLabel",
"unshareTooltip", "unshareTooltip",
"unshareSuccessNotification", "unshareSuccessNotification",
@ -45,6 +46,7 @@
"shareMethodPasswordLinkDescription", "shareMethodPasswordLinkDescription",
"collectionSharingLabel", "collectionSharingLabel",
"fileLastSharedDescription", "fileLastSharedDescription",
"fileLastSharedByOthersDescription",
"sharedWithLabel", "sharedWithLabel",
"unshareTooltip", "unshareTooltip",
"unshareSuccessNotification", "unshareSuccessNotification",
@ -137,6 +139,7 @@
"shareMethodPasswordLinkDescription", "shareMethodPasswordLinkDescription",
"collectionSharingLabel", "collectionSharingLabel",
"fileLastSharedDescription", "fileLastSharedDescription",
"fileLastSharedByOthersDescription",
"sharedWithLabel", "sharedWithLabel",
"unshareTooltip", "unshareTooltip",
"unshareSuccessNotification", "unshareSuccessNotification",
@ -160,6 +163,7 @@
"sortOptionManualLabel", "sortOptionManualLabel",
"collectionSharingLabel", "collectionSharingLabel",
"fileLastSharedDescription", "fileLastSharedDescription",
"fileLastSharedByOthersDescription",
"sharedWithLabel", "sharedWithLabel",
"unshareTooltip", "unshareTooltip",
"unshareSuccessNotification", "unshareSuccessNotification",
@ -232,6 +236,7 @@
"shareMethodPasswordLinkDescription", "shareMethodPasswordLinkDescription",
"collectionSharingLabel", "collectionSharingLabel",
"fileLastSharedDescription", "fileLastSharedDescription",
"fileLastSharedByOthersDescription",
"sharedWithLabel", "sharedWithLabel",
"unshareTooltip", "unshareTooltip",
"unshareSuccessNotification", "unshareSuccessNotification",
@ -277,6 +282,7 @@
"shareMethodPasswordLinkDescription", "shareMethodPasswordLinkDescription",
"collectionSharingLabel", "collectionSharingLabel",
"fileLastSharedDescription", "fileLastSharedDescription",
"fileLastSharedByOthersDescription",
"sharedWithLabel", "sharedWithLabel",
"unshareTooltip", "unshareTooltip",
"unshareSuccessNotification", "unshareSuccessNotification",

View file

@ -127,23 +127,25 @@ class _SharedFileViewerState extends State<SharedFileViewer> {
title: Text(widget.file.strippedPath), title: Text(widget.file.strippedPath),
), ),
), ),
SliverToBoxAdapter( if (widget.shares.first.uidOwner == widget.account.username) ...[
child: Padding( SliverToBoxAdapter(
padding: const EdgeInsets.all(16), child: Padding(
child: Text( padding: const EdgeInsets.all(16),
L10n.global().sharedWithLabel, child: Text(
style: TextStyle( L10n.global().sharedWithLabel,
color: Theme.of(context).colorScheme.primary, style: TextStyle(
color: Theme.of(context).colorScheme.primary,
),
), ),
), ),
), ),
), SliverList(
SliverList( delegate: SliverChildBuilderDelegate(
delegate: SliverChildBuilderDelegate( (context, index) => _buildShareItem(context, _shares[index]),
(context, index) => _buildShareItem(context, _shares[index]), childCount: _shares.length,
childCount: _shares.length, ),
), ),
), ],
], ],
); );
} }

View file

@ -201,7 +201,10 @@ class _SharingBrowserState extends State<SharingBrowser> {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
Text( Text(
L10n.global().fileLastSharedDescription(dateStr), shares.first.share.uidOwner == widget.account.username
? L10n.global().fileLastSharedDescription(dateStr)
: L10n.global().fileLastSharedByOthersDescription(
shares.first.share.displaynameOwner, dateStr),
style: TextStyle( style: TextStyle(
color: AppTheme.getSecondaryTextColor(context), color: AppTheme.getSecondaryTextColor(context),
), ),
@ -238,8 +241,10 @@ class _SharingBrowserState extends State<SharingBrowser> {
// group shares of the same file // group shares of the same file
final map = <String, List<ListSharingItem>>{}; final map = <String, List<ListSharingItem>>{};
for (final i in items) { for (final i in items) {
map[i.share.path] ??= <ListSharingItem>[]; final isSharedByMe = i.share.uidOwner == widget.account.username;
map[i.share.path]!.add(i); final groupKey = "${i.share.path}?$isSharedByMe";
map[groupKey] ??= <ListSharingItem>[];
map[groupKey]!.add(i);
} }
// sort the sub-lists // sort the sub-lists
for (final list in map.values) { for (final list in map.values) {