2020-10-24 23:10:37 +00:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
2020-10-28 15:25:32 +00:00
|
|
|
import 'package:logging/logging.dart';
|
2023-07-18 13:29:59 +00:00
|
|
|
import "package:photos/core/configuration.dart";
|
2020-10-24 23:10:37 +00:00
|
|
|
import 'package:photos/core/event_bus.dart';
|
2020-10-28 12:03:28 +00:00
|
|
|
import 'package:photos/events/collection_updated_event.dart';
|
2020-10-24 23:10:37 +00:00
|
|
|
import 'package:photos/events/local_photos_updated_event.dart';
|
2021-03-17 21:07:17 +00:00
|
|
|
import 'package:photos/events/user_logged_out_event.dart';
|
2023-04-06 09:01:16 +00:00
|
|
|
import "package:photos/generated/l10n.dart";
|
2023-08-25 04:39:30 +00:00
|
|
|
import 'package:photos/models/collection/collection.dart';
|
2021-07-23 12:28:02 +00:00
|
|
|
import 'package:photos/services/collections_service.dart';
|
2023-06-06 16:43:32 +00:00
|
|
|
import "package:photos/ui/collections/button/archived_button.dart";
|
|
|
|
import "package:photos/ui/collections/button/hidden_button.dart";
|
|
|
|
import "package:photos/ui/collections/button/trash_button.dart";
|
|
|
|
import "package:photos/ui/collections/button/uncategorized_button.dart";
|
2023-07-04 03:41:49 +00:00
|
|
|
import "package:photos/ui/collections/collection_list_page.dart";
|
2023-06-24 06:04:47 +00:00
|
|
|
import "package:photos/ui/collections/device/device_folders_grid_view.dart";
|
2023-06-24 07:17:53 +00:00
|
|
|
import "package:photos/ui/collections/device/device_folders_vertical_grid_view.dart";
|
2023-07-04 03:41:49 +00:00
|
|
|
import "package:photos/ui/collections/flex_grid_view.dart";
|
2023-08-25 04:31:03 +00:00
|
|
|
import "package:photos/ui/collections/new_album_icon.dart";
|
2022-07-01 14:18:05 +00:00
|
|
|
import 'package:photos/ui/common/loading_widget.dart';
|
2023-03-10 08:08:51 +00:00
|
|
|
import 'package:photos/ui/components/buttons/icon_button_widget.dart';
|
2023-07-18 13:29:59 +00:00
|
|
|
import "package:photos/ui/tabs/section_title.dart";
|
|
|
|
import "package:photos/ui/viewer/actions/delete_empty_albums.dart";
|
|
|
|
import "package:photos/ui/viewer/gallery/empty_state.dart";
|
2021-09-08 20:06:37 +00:00
|
|
|
import 'package:photos/utils/local_settings.dart';
|
2023-06-22 19:11:23 +00:00
|
|
|
import "package:photos/utils/navigation_util.dart";
|
2021-09-17 04:44:10 +00:00
|
|
|
|
2023-06-06 09:57:17 +00:00
|
|
|
class UserCollectionsTab extends StatefulWidget {
|
|
|
|
const UserCollectionsTab({Key? key}) : super(key: key);
|
2020-10-24 23:10:37 +00:00
|
|
|
|
|
|
|
@override
|
2023-06-06 09:57:17 +00:00
|
|
|
State<UserCollectionsTab> createState() => _UserCollectionsTabState();
|
2020-10-24 23:10:37 +00:00
|
|
|
}
|
|
|
|
|
2023-06-06 09:57:17 +00:00
|
|
|
class _UserCollectionsTabState extends State<UserCollectionsTab>
|
2020-11-10 11:36:51 +00:00
|
|
|
with AutomaticKeepAliveClientMixin {
|
2023-06-06 09:57:17 +00:00
|
|
|
final _logger = Logger((_UserCollectionsTabState).toString());
|
2022-12-30 12:10:17 +00:00
|
|
|
late StreamSubscription<LocalPhotosUpdatedEvent> _localFilesSubscription;
|
2023-01-03 08:29:26 +00:00
|
|
|
late StreamSubscription<CollectionUpdatedEvent>
|
|
|
|
_collectionUpdatesSubscription;
|
2022-12-30 12:10:17 +00:00
|
|
|
late StreamSubscription<UserLoggedOutEvent> _loggedOutEvent;
|
|
|
|
AlbumSortKey? sortKey;
|
2022-05-05 06:46:31 +00:00
|
|
|
String _loadReason = "init";
|
2023-07-20 09:45:30 +00:00
|
|
|
final _scrollController = ScrollController();
|
2020-10-24 23:10:37 +00:00
|
|
|
|
2023-07-03 13:19:15 +00:00
|
|
|
static const int _kOnEnteItemLimitCount = 10;
|
2020-10-24 23:10:37 +00:00
|
|
|
@override
|
|
|
|
void initState() {
|
2022-07-03 09:49:33 +00:00
|
|
|
_localFilesSubscription =
|
|
|
|
Bus.instance.on<LocalPhotosUpdatedEvent>().listen((event) {
|
2022-11-11 10:44:12 +00:00
|
|
|
_loadReason = event.reason;
|
2020-10-28 12:03:28 +00:00
|
|
|
setState(() {});
|
|
|
|
});
|
2022-07-03 09:49:33 +00:00
|
|
|
_collectionUpdatesSubscription =
|
|
|
|
Bus.instance.on<CollectionUpdatedEvent>().listen((event) {
|
2022-11-11 10:44:12 +00:00
|
|
|
_loadReason = event.reason;
|
2020-10-24 23:10:37 +00:00
|
|
|
setState(() {});
|
|
|
|
});
|
2021-03-17 21:07:17 +00:00
|
|
|
_loggedOutEvent = Bus.instance.on<UserLoggedOutEvent>().listen((event) {
|
2022-11-11 10:44:12 +00:00
|
|
|
_loadReason = event.reason;
|
2021-03-17 21:07:17 +00:00
|
|
|
setState(() {});
|
|
|
|
});
|
2021-09-08 20:06:37 +00:00
|
|
|
sortKey = LocalSettings.instance.albumSortKey();
|
2020-10-24 23:10:37 +00:00
|
|
|
super.initState();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2020-11-16 08:00:31 +00:00
|
|
|
super.build(context);
|
2022-05-05 06:46:31 +00:00
|
|
|
_logger.info("Building, trigger: $_loadReason");
|
2023-06-22 08:30:20 +00:00
|
|
|
return FutureBuilder<List<Collection>>(
|
2023-07-26 10:15:58 +00:00
|
|
|
future: CollectionsService.instance.getCollectionForOnEnteSection(),
|
2020-10-24 23:10:37 +00:00
|
|
|
builder: (context, snapshot) {
|
|
|
|
if (snapshot.hasData) {
|
2023-06-22 19:37:15 +00:00
|
|
|
return _getCollectionsGalleryWidget(snapshot.data!);
|
2020-10-24 23:10:37 +00:00
|
|
|
} else if (snapshot.hasError) {
|
|
|
|
return Text(snapshot.error.toString());
|
|
|
|
} else {
|
2022-07-03 06:04:42 +00:00
|
|
|
return const EnteLoadingWidget();
|
2020-10-24 23:10:37 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-22 19:37:15 +00:00
|
|
|
Widget _getCollectionsGalleryWidget(List<Collection> collections) {
|
2023-06-22 08:30:20 +00:00
|
|
|
final TextStyle trashAndHiddenTextStyle =
|
|
|
|
Theme.of(context).textTheme.titleMedium!.copyWith(
|
|
|
|
color: Theme.of(context)
|
|
|
|
.textTheme
|
|
|
|
.titleMedium!
|
|
|
|
.color!
|
|
|
|
.withOpacity(0.5),
|
|
|
|
);
|
2022-08-11 12:28:06 +00:00
|
|
|
|
2023-07-18 13:29:59 +00:00
|
|
|
return CustomScrollView(
|
2023-10-07 12:52:53 +00:00
|
|
|
physics: const BouncingScrollPhysics(),
|
2023-07-20 09:45:30 +00:00
|
|
|
controller: _scrollController,
|
2023-07-18 13:29:59 +00:00
|
|
|
slivers: [
|
|
|
|
SliverToBoxAdapter(
|
2023-07-20 10:09:46 +00:00
|
|
|
child: SectionOptions(
|
|
|
|
Hero(
|
|
|
|
tag: "OnDeviceAppTitle",
|
|
|
|
child: SectionTitle(title: S.of(context).onDevice),
|
|
|
|
),
|
|
|
|
trailingWidget: IconButtonWidget(
|
|
|
|
icon: Icons.chevron_right,
|
|
|
|
iconButtonType: IconButtonType.secondary,
|
|
|
|
onTap: () {
|
|
|
|
unawaited(
|
|
|
|
routeToPage(
|
|
|
|
context,
|
|
|
|
DeviceFolderVerticalGridView(
|
|
|
|
appTitle: SectionTitle(
|
|
|
|
title: S.of(context).onDevice,
|
2023-06-24 07:17:53 +00:00
|
|
|
),
|
2023-07-20 10:09:46 +00:00
|
|
|
tag: "OnDeviceAppTitle",
|
2023-06-24 07:17:53 +00:00
|
|
|
),
|
2023-07-20 10:09:46 +00:00
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
2021-09-09 06:14:07 +00:00
|
|
|
),
|
2023-07-18 13:29:59 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
const SliverToBoxAdapter(child: DeviceFoldersGridView()),
|
|
|
|
SliverToBoxAdapter(
|
|
|
|
child: SectionOptions(
|
|
|
|
SectionTitle(titleWithBrand: getOnEnteSection(context)),
|
|
|
|
trailingWidget: _sortMenu(collections),
|
|
|
|
padding: const EdgeInsets.only(left: 12, right: 6),
|
|
|
|
),
|
|
|
|
),
|
2023-09-11 03:53:06 +00:00
|
|
|
SliverToBoxAdapter(child: DeleteEmptyAlbums(collections)),
|
2023-07-18 13:29:59 +00:00
|
|
|
Configuration.instance.hasConfiguredAccount()
|
|
|
|
? CollectionsFlexiGridViewWidget(
|
|
|
|
collections,
|
|
|
|
displayLimitCount: _kOnEnteItemLimitCount,
|
|
|
|
shrinkWrap: true,
|
|
|
|
)
|
|
|
|
: const SliverToBoxAdapter(child: EmptyState()),
|
|
|
|
collections.length > _kOnEnteItemLimitCount
|
|
|
|
? SliverToBoxAdapter(
|
|
|
|
child: GestureDetector(
|
|
|
|
behavior: HitTestBehavior.opaque,
|
|
|
|
onTap: () {
|
|
|
|
unawaited(
|
|
|
|
routeToPage(
|
|
|
|
context,
|
|
|
|
CollectionListPage(
|
|
|
|
collections,
|
2023-07-26 10:18:45 +00:00
|
|
|
sectionType: UISectionType.homeCollections,
|
2023-07-18 13:29:59 +00:00
|
|
|
appTitle: SectionTitle(
|
|
|
|
titleWithBrand: getOnEnteSection(context),
|
2023-07-03 09:48:57 +00:00
|
|
|
),
|
2023-07-26 10:19:11 +00:00
|
|
|
initialScrollOffset: _scrollController.offset,
|
2023-07-03 09:48:57 +00:00
|
|
|
),
|
2023-07-03 09:47:32 +00:00
|
|
|
),
|
2023-07-18 13:29:59 +00:00
|
|
|
);
|
|
|
|
},
|
|
|
|
child: SectionOptions(
|
|
|
|
SectionTitle(
|
|
|
|
title: S.of(context).viewAll,
|
|
|
|
mutedTitle: true,
|
|
|
|
),
|
|
|
|
trailingWidget: const IconButtonWidget(
|
|
|
|
icon: Icons.chevron_right,
|
|
|
|
iconButtonType: IconButtonType.secondary,
|
2023-07-03 09:47:32 +00:00
|
|
|
),
|
2023-07-18 13:29:59 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
: const SliverToBoxAdapter(child: SizedBox.shrink()),
|
|
|
|
const SliverToBoxAdapter(child: Divider()),
|
|
|
|
const SliverToBoxAdapter(child: SizedBox(height: 12)),
|
|
|
|
SliverToBoxAdapter(
|
|
|
|
child: Padding(
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
UnCategorizedCollections(trashAndHiddenTextStyle),
|
|
|
|
const SizedBox(height: 12),
|
|
|
|
ArchivedCollectionsButton(trashAndHiddenTextStyle),
|
|
|
|
const SizedBox(height: 12),
|
|
|
|
HiddenCollectionsButtonWidget(trashAndHiddenTextStyle),
|
|
|
|
const SizedBox(height: 12),
|
|
|
|
TrashSectionButton(trashAndHiddenTextStyle),
|
|
|
|
],
|
2021-10-13 12:05:20 +00:00
|
|
|
),
|
2023-07-18 13:29:59 +00:00
|
|
|
),
|
2021-02-08 09:26:49 +00:00
|
|
|
),
|
2023-08-09 11:17:28 +00:00
|
|
|
SliverToBoxAdapter(
|
|
|
|
child: SizedBox(height: 64 + MediaQuery.of(context).padding.bottom),
|
|
|
|
),
|
2023-07-18 13:29:59 +00:00
|
|
|
],
|
2020-12-12 01:11:12 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-22 19:37:15 +00:00
|
|
|
Widget _sortMenu(List<Collection> collections) {
|
2021-09-09 06:14:07 +00:00
|
|
|
Text sortOptionText(AlbumSortKey key) {
|
|
|
|
String text = key.toString();
|
2021-09-08 20:19:25 +00:00
|
|
|
switch (key) {
|
|
|
|
case AlbumSortKey.albumName:
|
2023-04-06 09:01:16 +00:00
|
|
|
text = S.of(context).name;
|
2021-09-09 06:14:07 +00:00
|
|
|
break;
|
2022-04-28 13:08:27 +00:00
|
|
|
case AlbumSortKey.newestPhoto:
|
2023-04-06 09:01:16 +00:00
|
|
|
text = S.of(context).newest;
|
2021-09-09 06:14:07 +00:00
|
|
|
break;
|
2022-04-28 13:08:27 +00:00
|
|
|
case AlbumSortKey.lastUpdated:
|
2023-04-06 09:01:16 +00:00
|
|
|
text = S.of(context).lastUpdated;
|
2021-09-08 20:19:25 +00:00
|
|
|
}
|
2022-06-11 08:23:52 +00:00
|
|
|
return Text(
|
|
|
|
text,
|
2023-06-13 06:41:31 +00:00
|
|
|
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
2022-04-28 13:08:27 +00:00
|
|
|
fontSize: 14,
|
2022-12-30 12:10:17 +00:00
|
|
|
color: Theme.of(context).iconTheme.color!.withOpacity(0.7),
|
2022-06-11 08:23:52 +00:00
|
|
|
),
|
|
|
|
);
|
2021-09-08 20:19:25 +00:00
|
|
|
}
|
2021-09-09 06:14:07 +00:00
|
|
|
|
2023-06-23 12:24:26 +00:00
|
|
|
return Theme(
|
|
|
|
data: Theme.of(context).copyWith(
|
|
|
|
highlightColor: Colors.transparent,
|
|
|
|
splashColor: Colors.transparent,
|
|
|
|
),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
2023-11-04 08:08:14 +00:00
|
|
|
const NewAlbumIcon(
|
|
|
|
icon: Icons.add_rounded,
|
|
|
|
iconButtonType: IconButtonType.secondary,
|
|
|
|
),
|
2023-06-23 12:24:26 +00:00
|
|
|
GestureDetector(
|
|
|
|
onTapDown: (TapDownDetails details) async {
|
|
|
|
final int? selectedValue = await showMenu<int>(
|
|
|
|
context: context,
|
|
|
|
position: RelativeRect.fromLTRB(
|
|
|
|
details.globalPosition.dx,
|
|
|
|
details.globalPosition.dy,
|
|
|
|
details.globalPosition.dx,
|
|
|
|
details.globalPosition.dy + 50,
|
|
|
|
),
|
|
|
|
items: List.generate(AlbumSortKey.values.length, (index) {
|
|
|
|
return PopupMenuItem(
|
|
|
|
value: index,
|
|
|
|
child: sortOptionText(AlbumSortKey.values[index]),
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
if (selectedValue != null) {
|
|
|
|
sortKey = AlbumSortKey.values[selectedValue];
|
|
|
|
await LocalSettings.instance.setAlbumSortKey(sortKey!);
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
child: const IconButtonWidget(
|
|
|
|
icon: Icons.sort_outlined,
|
2023-06-22 19:11:23 +00:00
|
|
|
iconButtonType: IconButtonType.secondary,
|
2023-06-23 12:24:26 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
2021-09-09 06:14:07 +00:00
|
|
|
),
|
|
|
|
);
|
2021-09-08 20:19:25 +00:00
|
|
|
}
|
|
|
|
|
2021-04-27 15:29:34 +00:00
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
_localFilesSubscription.cancel();
|
|
|
|
_collectionUpdatesSubscription.cancel();
|
|
|
|
_loggedOutEvent.cancel();
|
2023-07-20 09:45:30 +00:00
|
|
|
_scrollController.dispose();
|
2021-04-27 15:29:34 +00:00
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool get wantKeepAlive => true;
|
|
|
|
}
|