282 lines
9.8 KiB
Dart
282 lines
9.8 KiB
Dart
import "dart:async";
|
|
import 'dart:math';
|
|
|
|
import 'package:collection/collection.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
|
import "package:photos/core/configuration.dart";
|
|
import "package:photos/generated/l10n.dart";
|
|
import 'package:photos/models/collection.dart';
|
|
import 'package:photos/models/collection_items.dart';
|
|
import 'package:photos/models/selected_files.dart';
|
|
import 'package:photos/services/collections_service.dart';
|
|
import 'package:photos/theme/colors.dart';
|
|
import 'package:photos/theme/ente_theme.dart';
|
|
import "package:photos/ui/collections_list_widget.dart";
|
|
import 'package:photos/ui/common/loading_widget.dart';
|
|
import 'package:photos/ui/components/bottom_of_title_bar_widget.dart';
|
|
import 'package:photos/ui/components/buttons/button_widget.dart';
|
|
import 'package:photos/ui/components/models/button_type.dart';
|
|
import "package:photos/ui/components/text_input_widget.dart";
|
|
import 'package:photos/ui/components/title_bar_title_widget.dart';
|
|
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
|
|
|
enum CollectionActionType {
|
|
addFiles,
|
|
moveFiles,
|
|
restoreFiles,
|
|
unHide,
|
|
shareCollection,
|
|
collectPhotos,
|
|
}
|
|
|
|
String _actionName(
|
|
BuildContext context,
|
|
CollectionActionType type,
|
|
int fileCount,
|
|
) {
|
|
String text = "";
|
|
switch (type) {
|
|
case CollectionActionType.addFiles:
|
|
text = S.of(context).addItem(fileCount);
|
|
break;
|
|
case CollectionActionType.moveFiles:
|
|
text = S.of(context).moveItem(fileCount);
|
|
break;
|
|
case CollectionActionType.restoreFiles:
|
|
text = S.of(context).restoreToAlbum;
|
|
break;
|
|
case CollectionActionType.unHide:
|
|
text = S.of(context).unhideToAlbum;
|
|
break;
|
|
case CollectionActionType.shareCollection:
|
|
text = S.of(context).share;
|
|
break;
|
|
case CollectionActionType.collectPhotos:
|
|
text = S.of(context).share;
|
|
break;
|
|
}
|
|
return text;
|
|
}
|
|
|
|
void showCollectionActionSheet(
|
|
BuildContext context, {
|
|
SelectedFiles? selectedFiles,
|
|
List<SharedMediaFile>? sharedFiles,
|
|
CollectionActionType actionType = CollectionActionType.addFiles,
|
|
bool showOptionToCreateNewAlbum = true,
|
|
}) {
|
|
showBarModalBottomSheet(
|
|
context: context,
|
|
builder: (context) {
|
|
return CollectionActionSheet(
|
|
selectedFiles: selectedFiles,
|
|
sharedFiles: sharedFiles,
|
|
actionType: actionType,
|
|
showOptionToCreateNewAlbum: showOptionToCreateNewAlbum,
|
|
);
|
|
},
|
|
shape: const RoundedRectangleBorder(
|
|
side: BorderSide(width: 0),
|
|
borderRadius: BorderRadius.vertical(
|
|
top: Radius.circular(5),
|
|
),
|
|
),
|
|
topControl: const SizedBox.shrink(),
|
|
backgroundColor: getEnteColorScheme(context).backgroundElevated,
|
|
barrierColor: backdropFaintDark,
|
|
enableDrag: false,
|
|
);
|
|
}
|
|
|
|
class CollectionActionSheet extends StatefulWidget {
|
|
final SelectedFiles? selectedFiles;
|
|
final List<SharedMediaFile>? sharedFiles;
|
|
final CollectionActionType actionType;
|
|
final bool showOptionToCreateNewAlbum;
|
|
const CollectionActionSheet({
|
|
required this.selectedFiles,
|
|
required this.sharedFiles,
|
|
required this.actionType,
|
|
required this.showOptionToCreateNewAlbum,
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
State<CollectionActionSheet> createState() => _CollectionActionSheetState();
|
|
}
|
|
|
|
class _CollectionActionSheetState extends State<CollectionActionSheet> {
|
|
static const int cancelButtonSize = 80;
|
|
String _searchQuery = "";
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final filesCount = widget.sharedFiles != null
|
|
? widget.sharedFiles!.length
|
|
: widget.selectedFiles?.files.length ?? 0;
|
|
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
|
|
final isKeyboardUp = bottomInset > 100;
|
|
return Padding(
|
|
padding: EdgeInsets.only(
|
|
bottom: isKeyboardUp ? bottomInset - cancelButtonSize : 0,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
ConstrainedBox(
|
|
constraints: BoxConstraints(
|
|
maxWidth: min(428, MediaQuery.of(context).size.width),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.fromLTRB(0, 32, 0, 8),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.max,
|
|
children: [
|
|
Expanded(
|
|
child: Column(
|
|
children: [
|
|
BottomOfTitleBarWidget(
|
|
title: TitleBarTitleWidget(
|
|
title: _actionName(
|
|
context,
|
|
widget.actionType,
|
|
filesCount,
|
|
),
|
|
),
|
|
caption: widget.showOptionToCreateNewAlbum
|
|
? S.of(context).createOrSelectAlbum
|
|
: S.of(context).selectAlbum,
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.only(
|
|
top: 16,
|
|
left: 16,
|
|
right: 16,
|
|
),
|
|
child: TextInputWidget(
|
|
hintText: S.of(context).searchByAlbumNameHint,
|
|
prefixIcon: Icons.search_rounded,
|
|
onChange: (value) {
|
|
setState(() {
|
|
_searchQuery = value;
|
|
});
|
|
},
|
|
isClearable: true,
|
|
shouldUnfocusOnClearOrSubmit: true,
|
|
borderRadius: 2,
|
|
),
|
|
),
|
|
_getCollectionItems(filesCount),
|
|
],
|
|
),
|
|
),
|
|
SafeArea(
|
|
child: Container(
|
|
//inner stroke of 1pt + 15 pts of top padding = 16 pts
|
|
padding: const EdgeInsets.fromLTRB(16, 15, 16, 8),
|
|
decoration: BoxDecoration(
|
|
border: Border(
|
|
top: BorderSide(
|
|
color: getEnteColorScheme(context).strokeFaint,
|
|
),
|
|
),
|
|
),
|
|
child: ButtonWidget(
|
|
buttonType: ButtonType.secondary,
|
|
buttonAction: ButtonAction.cancel,
|
|
isInAlert: true,
|
|
labelText: S.of(context).cancel,
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Flexible _getCollectionItems(int filesCount) {
|
|
return Flexible(
|
|
child: Padding(
|
|
padding: const EdgeInsets.fromLTRB(16, 24, 4, 0),
|
|
child: FutureBuilder(
|
|
future: _getCollectionsWithThumbnail(),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) {
|
|
//Need to show an error on the UI here
|
|
return const SizedBox.shrink();
|
|
} else if (snapshot.hasData) {
|
|
final collectionsWithThumbnail =
|
|
snapshot.data as List<CollectionWithThumbnail>;
|
|
_removeIncomingCollections(collectionsWithThumbnail);
|
|
final shouldShowCreateAlbum =
|
|
widget.showOptionToCreateNewAlbum && _searchQuery.isEmpty;
|
|
final searchResults = _searchQuery.isNotEmpty
|
|
? collectionsWithThumbnail
|
|
.where(
|
|
(element) => element.collection.displayName
|
|
.toLowerCase()
|
|
.contains(_searchQuery),
|
|
)
|
|
.toList()
|
|
: collectionsWithThumbnail;
|
|
return Scrollbar(
|
|
thumbVisibility: true,
|
|
radius: const Radius.circular(2),
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(right: 12),
|
|
child: CollectionsListWidget(
|
|
searchResults,
|
|
widget.actionType,
|
|
widget.selectedFiles,
|
|
widget.sharedFiles,
|
|
_searchQuery,
|
|
shouldShowCreateAlbum,
|
|
),
|
|
),
|
|
);
|
|
} else {
|
|
return const EnteLoadingWidget();
|
|
}
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<List<CollectionWithThumbnail>> _getCollectionsWithThumbnail() async {
|
|
final List<CollectionWithThumbnail> collectionsWithThumbnail =
|
|
await CollectionsService.instance.getCollectionsWithThumbnails(
|
|
// in collections where user is a collaborator, only addTo and remove
|
|
// action can to be performed
|
|
includeCollabCollections:
|
|
widget.actionType == CollectionActionType.addFiles,
|
|
);
|
|
collectionsWithThumbnail.removeWhere(
|
|
(element) => (element.collection.type == CollectionType.favorites ||
|
|
element.collection.type == CollectionType.uncategorized ||
|
|
element.collection.isSharedFilesCollection()),
|
|
);
|
|
collectionsWithThumbnail.sort((first, second) {
|
|
return compareAsciiLowerCaseNatural(
|
|
first.collection.displayName,
|
|
second.collection.displayName,
|
|
);
|
|
});
|
|
return collectionsWithThumbnail;
|
|
}
|
|
|
|
void _removeIncomingCollections(List<CollectionWithThumbnail> items) {
|
|
if (widget.actionType == CollectionActionType.shareCollection ||
|
|
widget.actionType == CollectionActionType.collectPhotos) {
|
|
final ownerID = Configuration.instance.getUserID();
|
|
items.removeWhere(
|
|
(e) => !e.collection.isOwner(ownerID!),
|
|
);
|
|
}
|
|
}
|
|
}
|