mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-25 02:48:54 +01:00
List pending shard albums
This commit is contained in:
parent
6d2bfb2831
commit
c0f65745f7
7 changed files with 505 additions and 10 deletions
183
lib/bloc/list_pending_shared_album.dart
Normal file
183
lib/bloc/list_pending_shared_album.dart
Normal file
|
@ -0,0 +1,183 @@
|
|||
import 'package:bloc/bloc.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file/data_source.dart';
|
||||
import 'package:nc_photos/event/event.dart';
|
||||
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
||||
import 'package:nc_photos/use_case/list_pending_shared_album.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class ListPendingSharedAlbumBlocItem {
|
||||
ListPendingSharedAlbumBlocItem(this.album);
|
||||
|
||||
final Album album;
|
||||
}
|
||||
|
||||
abstract class ListPendingSharedAlbumBlocEvent {
|
||||
const ListPendingSharedAlbumBlocEvent();
|
||||
}
|
||||
|
||||
class ListPendingSharedAlbumBlocQuery
|
||||
extends ListPendingSharedAlbumBlocEvent {
|
||||
const ListPendingSharedAlbumBlocQuery(
|
||||
this.account,
|
||||
);
|
||||
|
||||
@override
|
||||
toString() {
|
||||
return "$runtimeType {"
|
||||
"account: $account, "
|
||||
"}";
|
||||
}
|
||||
|
||||
final Account account;
|
||||
}
|
||||
|
||||
/// An external event has happened and may affect the state of this bloc
|
||||
class _ListPendingSharedAlbumBlocExternalEvent
|
||||
extends ListPendingSharedAlbumBlocEvent {
|
||||
const _ListPendingSharedAlbumBlocExternalEvent();
|
||||
|
||||
@override
|
||||
toString() {
|
||||
return "$runtimeType {"
|
||||
"}";
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ListPendingSharedAlbumBlocState {
|
||||
const ListPendingSharedAlbumBlocState(this.items);
|
||||
|
||||
@override
|
||||
toString() {
|
||||
return "$runtimeType {"
|
||||
"items: List {length: ${items.length}}, "
|
||||
"}";
|
||||
}
|
||||
|
||||
final List<ListPendingSharedAlbumBlocItem> items;
|
||||
}
|
||||
|
||||
class ListPendingSharedAlbumBlocInit
|
||||
extends ListPendingSharedAlbumBlocState {
|
||||
ListPendingSharedAlbumBlocInit() : super(const []);
|
||||
}
|
||||
|
||||
class ListPendingSharedAlbumBlocLoading
|
||||
extends ListPendingSharedAlbumBlocState {
|
||||
const ListPendingSharedAlbumBlocLoading(
|
||||
List<ListPendingSharedAlbumBlocItem> items)
|
||||
: super(items);
|
||||
}
|
||||
|
||||
class ListPendingSharedAlbumBlocSuccess
|
||||
extends ListPendingSharedAlbumBlocState {
|
||||
const ListPendingSharedAlbumBlocSuccess(
|
||||
List<ListPendingSharedAlbumBlocItem> items)
|
||||
: super(items);
|
||||
}
|
||||
|
||||
class ListPendingSharedAlbumBlocFailure
|
||||
extends ListPendingSharedAlbumBlocState {
|
||||
const ListPendingSharedAlbumBlocFailure(
|
||||
List<ListPendingSharedAlbumBlocItem> items, this.exception)
|
||||
: super(items);
|
||||
|
||||
@override
|
||||
toString() {
|
||||
return "$runtimeType {"
|
||||
"super: ${super.toString()}, "
|
||||
"exception: $exception, "
|
||||
"}";
|
||||
}
|
||||
|
||||
final dynamic exception;
|
||||
}
|
||||
|
||||
/// The state of this bloc is inconsistent. This typically means that the data
|
||||
/// may have been changed externally
|
||||
class ListPendingSharedAlbumBlocInconsistent
|
||||
extends ListPendingSharedAlbumBlocState {
|
||||
const ListPendingSharedAlbumBlocInconsistent(
|
||||
List<ListPendingSharedAlbumBlocItem> items)
|
||||
: super(items);
|
||||
}
|
||||
|
||||
/// Return a list of importable shared albums in the pending dir
|
||||
class ListPendingSharedAlbumBloc extends Bloc<
|
||||
ListPendingSharedAlbumBlocEvent, ListPendingSharedAlbumBlocState> {
|
||||
ListPendingSharedAlbumBloc() : super(ListPendingSharedAlbumBlocInit()) {
|
||||
_fileMovedEventListener.begin();
|
||||
}
|
||||
|
||||
@override
|
||||
mapEventToState(ListPendingSharedAlbumBlocEvent event) async* {
|
||||
_log.info("[mapEventToState] $event");
|
||||
if (event is ListPendingSharedAlbumBlocQuery) {
|
||||
yield* _onEventQuery(event);
|
||||
} else if (event is _ListPendingSharedAlbumBlocExternalEvent) {
|
||||
yield* _onExternalEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
close() {
|
||||
_fileMovedEventListener.end();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
Stream<ListPendingSharedAlbumBlocState> _onEventQuery(
|
||||
ListPendingSharedAlbumBlocQuery ev) async* {
|
||||
yield ListPendingSharedAlbumBlocLoading([]);
|
||||
try {
|
||||
final fileRepo = FileRepo(FileCachedDataSource());
|
||||
final albumRepo = AlbumRepo(AlbumCachedDataSource());
|
||||
final albums = <Album>[];
|
||||
final errors = <dynamic>[];
|
||||
await for (final result
|
||||
in ListPendingSharedAlbum(fileRepo, albumRepo)(ev.account)) {
|
||||
if (result is Tuple2) {
|
||||
_log.severe("[_onEventQuery] Exception while ListPendingSharedAlbum",
|
||||
result.item1, result.item2);
|
||||
errors.add(result.item1);
|
||||
} else if (result is Album) {
|
||||
albums.add(result);
|
||||
}
|
||||
}
|
||||
final items =
|
||||
albums.map((e) => ListPendingSharedAlbumBlocItem(e)).toList();
|
||||
if (errors.isEmpty) {
|
||||
yield ListPendingSharedAlbumBlocSuccess(items);
|
||||
} else {
|
||||
yield ListPendingSharedAlbumBlocFailure(items, errors.first);
|
||||
}
|
||||
} catch (e) {
|
||||
_log.severe("[_onEventQuery] Exception", e);
|
||||
yield ListPendingSharedAlbumBlocFailure(state.items, e);
|
||||
}
|
||||
}
|
||||
|
||||
Stream<ListPendingSharedAlbumBlocState> _onExternalEvent(
|
||||
_ListPendingSharedAlbumBlocExternalEvent ev) async* {
|
||||
yield ListPendingSharedAlbumBlocInconsistent(state.items);
|
||||
}
|
||||
|
||||
void _onFileMovedEvent(FileMovedEvent ev) {
|
||||
if (state is ListPendingSharedAlbumBlocInit) {
|
||||
// no data in this bloc, ignore
|
||||
return;
|
||||
}
|
||||
if (ev.file.path.startsWith(
|
||||
remote_storage_util.getRemotePendingSharedAlbumsDir(ev.account))) {
|
||||
add(_ListPendingSharedAlbumBlocExternalEvent());
|
||||
}
|
||||
}
|
||||
|
||||
late final _fileMovedEventListener =
|
||||
AppEventListener<FileMovedEvent>(_onFileMovedEvent);
|
||||
|
||||
static final _log =
|
||||
Logger("bloc.list_pending_shared_album.ListPendingSharedAlbumBloc");
|
||||
}
|
59
lib/use_case/list_pending_shared_album.dart
Normal file
59
lib/use_case/list_pending_shared_album.dart
Normal file
|
@ -0,0 +1,59 @@
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/exception.dart';
|
||||
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
||||
import 'package:nc_photos/use_case/ls.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class ListPendingSharedAlbum {
|
||||
ListPendingSharedAlbum(this.fileRepo, this.albumRepo);
|
||||
|
||||
/// Return shared albums that are known to us (in pending dir) but not added
|
||||
/// to the user library
|
||||
///
|
||||
/// The returned stream would emit either Album data or a tuple of exception
|
||||
/// and stacktrace
|
||||
Stream<dynamic> call(Account account) async* {
|
||||
List<File> ls;
|
||||
try {
|
||||
ls = await Ls(fileRepo)(
|
||||
account,
|
||||
File(
|
||||
path: remote_storage_util.getRemotePendingSharedAlbumsDir(account),
|
||||
));
|
||||
} catch (e, stacktrace) {
|
||||
if (e is ApiException && e.response.statusCode == 404) {
|
||||
// no albums
|
||||
return;
|
||||
}
|
||||
yield Tuple2(e, stacktrace);
|
||||
return;
|
||||
}
|
||||
final albumFiles =
|
||||
ls.where((element) => element.isCollection != true).toList();
|
||||
for (final f in albumFiles) {
|
||||
try {
|
||||
yield await albumRepo.get(account, f);
|
||||
} catch (e, stacktrace) {
|
||||
yield Tuple2(e, stacktrace);
|
||||
}
|
||||
}
|
||||
try {
|
||||
albumRepo.cleanUp(
|
||||
account,
|
||||
remote_storage_util.getRemotePendingSharedAlbumsDir(account),
|
||||
albumFiles);
|
||||
} catch (e, stacktrace) {
|
||||
// not important, log and ignore
|
||||
_log.shout("[_call] Failed while cleanUp", e, stacktrace);
|
||||
}
|
||||
}
|
||||
|
||||
final FileRepo fileRepo;
|
||||
final AlbumRepo albumRepo;
|
||||
|
||||
static final _log =
|
||||
Logger("user_case.list_pending_shared_album.ListPendingSharedAlbum");
|
||||
}
|
|
@ -109,7 +109,7 @@ class _AlbumBrowserState extends State<AlbumBrowser>
|
|||
}
|
||||
|
||||
@protected
|
||||
get canEdit => _album != null;
|
||||
get canEdit => _album?.albumFile?.isOwned(widget.account.username) == true;
|
||||
|
||||
@override
|
||||
enterEditMode() {
|
||||
|
|
|
@ -110,7 +110,7 @@ class _DynamicAlbumBrowserState extends State<DynamicAlbumBrowser>
|
|||
}
|
||||
|
||||
@protected
|
||||
get canEdit => _album != null;
|
||||
get canEdit => _album?.albumFile?.isOwned(widget.account.username) == true;
|
||||
|
||||
@override
|
||||
enterEditMode() {
|
||||
|
@ -261,12 +261,14 @@ class _DynamicAlbumBrowserState extends State<DynamicAlbumBrowser>
|
|||
context,
|
||||
widget.account,
|
||||
_album!,
|
||||
menuItemBuilder: (context) => [
|
||||
menuItemBuilder: canEdit
|
||||
? (context) => [
|
||||
PopupMenuItem(
|
||||
value: _menuValueConvertBasic,
|
||||
child: Text(L10n.of(context).convertBasicAlbumMenuLabel),
|
||||
),
|
||||
],
|
||||
]
|
||||
: null,
|
||||
onSelectedMenuItem: (option) {
|
||||
switch (option) {
|
||||
case _menuValueConvertBasic:
|
||||
|
|
|
@ -15,6 +15,8 @@ import 'package:nc_photos/entity/file/data_source.dart';
|
|||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/lab.dart';
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/remove.dart';
|
||||
|
@ -27,6 +29,7 @@ import 'package:nc_photos/widget/dynamic_album_browser.dart';
|
|||
import 'package:nc_photos/widget/home_app_bar.dart';
|
||||
import 'package:nc_photos/widget/new_album_dialog.dart';
|
||||
import 'package:nc_photos/widget/page_visibility_mixin.dart';
|
||||
import 'package:nc_photos/widget/pending_albums.dart';
|
||||
import 'package:nc_photos/widget/selection_app_bar.dart';
|
||||
import 'package:nc_photos/widget/trashbin_browser.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
@ -192,7 +195,9 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
|||
return _buildArchiveItem(context);
|
||||
} else if (index == 1) {
|
||||
return _buildTrashbinItem(context);
|
||||
} else if (index == 2) {
|
||||
} else if (index == 2 && Lab().enableSharedAlbum) {
|
||||
return _buildShareItem(context);
|
||||
} else if (index == 2 + (Lab().enableSharedAlbum ? 1 : 0)) {
|
||||
return _buildNewAlbumItem(context);
|
||||
} else if (index == _extraGridItemCount) {
|
||||
return Container();
|
||||
|
@ -239,6 +244,20 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildShareItem(BuildContext context) {
|
||||
return _NonAlbumGridItem(
|
||||
icon: Icons.share_outlined,
|
||||
label: "Sharing",
|
||||
isShowIndicator: Pref.inst().hasNewSharedAlbumOr(false),
|
||||
onTap: _isSelectionMode
|
||||
? null
|
||||
: () {
|
||||
Navigator.of(context).pushNamed(PendingAlbums.routeName,
|
||||
arguments: PendingAlbumsArguments(widget.account));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNewAlbumItem(BuildContext context) {
|
||||
return _NonAlbumGridItem(
|
||||
icon: Icons.add,
|
||||
|
@ -437,7 +456,7 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
|||
static final _log = Logger("widget.home_albums._HomeAlbumsState");
|
||||
static const _menuValueImport = 0;
|
||||
|
||||
static const _extraGridItemCount = 3;
|
||||
static final _extraGridItemCount = 3 + (Lab().enableSharedAlbum ? 1 : 0);
|
||||
}
|
||||
|
||||
class _GridItem {
|
||||
|
@ -454,6 +473,7 @@ class _NonAlbumGridItem extends StatelessWidget {
|
|||
required this.icon,
|
||||
required this.label,
|
||||
this.onTap,
|
||||
this.isShowIndicator = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -486,6 +506,12 @@ class _NonAlbumGridItem extends StatelessWidget {
|
|||
Expanded(
|
||||
child: Text(label),
|
||||
),
|
||||
if (isShowIndicator)
|
||||
Icon(
|
||||
Icons.circle,
|
||||
color: Colors.red,
|
||||
size: 8,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -498,4 +524,5 @@ class _NonAlbumGridItem extends StatelessWidget {
|
|||
final IconData icon;
|
||||
final String label;
|
||||
final VoidCallback? onTap;
|
||||
final bool isShowIndicator;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:nc_photos/widget/connect.dart';
|
|||
import 'package:nc_photos/widget/dynamic_album_browser.dart';
|
||||
import 'package:nc_photos/widget/home.dart';
|
||||
import 'package:nc_photos/widget/lab_settings.dart';
|
||||
import 'package:nc_photos/widget/pending_albums.dart';
|
||||
import 'package:nc_photos/widget/root_picker.dart';
|
||||
import 'package:nc_photos/widget/settings.dart';
|
||||
import 'package:nc_photos/widget/setup.dart';
|
||||
|
@ -115,6 +116,7 @@ class _MyAppState extends State<MyApp> implements SnackBarHandler {
|
|||
route ??= _handleAlbumImporterRoute(settings);
|
||||
route ??= _handleTrashbinBrowserRoute(settings);
|
||||
route ??= _handleTrashbinViewerRoute(settings);
|
||||
route ??= _handlePendingAlbumsRoute(settings);
|
||||
return route;
|
||||
}
|
||||
|
||||
|
@ -293,6 +295,19 @@ class _MyAppState extends State<MyApp> implements SnackBarHandler {
|
|||
return null;
|
||||
}
|
||||
|
||||
Route<dynamic>? _handlePendingAlbumsRoute(RouteSettings settings) {
|
||||
try {
|
||||
if (settings.name == PendingAlbums.routeName &&
|
||||
settings.arguments != null) {
|
||||
final args = settings.arguments as PendingAlbumsArguments;
|
||||
return PendingAlbums.buildRoute(args);
|
||||
}
|
||||
} catch (e) {
|
||||
_log.severe("[_handlePendingAlbumsRoute] Failed while handling route", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
|
||||
|
||||
late AppEventListener<ThemeChangedEvent> _themeChangedListener;
|
||||
|
|
209
lib/widget/pending_albums.dart
Normal file
209
lib/widget/pending_albums.dart
Normal file
|
@ -0,0 +1,209 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/bloc/list_pending_shared_album.dart';
|
||||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file/data_source.dart';
|
||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/import_potential_shared_album.dart';
|
||||
import 'package:nc_photos/widget/album_browser_util.dart' as album_browser_util;
|
||||
import 'package:nc_photos/widget/builder/album_grid_item_builder.dart';
|
||||
import 'package:nc_photos/widget/empty_list_indicator.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class PendingAlbumsArguments {
|
||||
PendingAlbumsArguments(this.account);
|
||||
|
||||
final Account account;
|
||||
}
|
||||
|
||||
class PendingAlbums extends StatefulWidget {
|
||||
static const routeName = "/pending-albums";
|
||||
|
||||
static Route buildRoute(PendingAlbumsArguments args) =>
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PendingAlbums.fromArgs(args),
|
||||
);
|
||||
|
||||
PendingAlbums({
|
||||
Key? key,
|
||||
required this.account,
|
||||
}) : super(key: key);
|
||||
|
||||
PendingAlbums.fromArgs(PendingAlbumsArguments args, {Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
account: args.account,
|
||||
);
|
||||
|
||||
@override
|
||||
createState() => _PendingAlbumsState();
|
||||
|
||||
final Account account;
|
||||
}
|
||||
|
||||
class _PendingAlbumsState extends State<PendingAlbums> {
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
_importPotentialSharedAlbum().then((_) {
|
||||
_bloc.add(ListPendingSharedAlbumBlocQuery(widget.account));
|
||||
});
|
||||
Pref.inst().setNewSharedAlbum(false);
|
||||
}
|
||||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListPendingSharedAlbumBloc,
|
||||
ListPendingSharedAlbumBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListPendingSharedAlbumBloc,
|
||||
ListPendingSharedAlbumBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContent(
|
||||
BuildContext context, ListPendingSharedAlbumBlocState state) {
|
||||
if (state is ListPendingSharedAlbumBlocSuccess && _items.isEmpty) {
|
||||
return Column(
|
||||
children: [
|
||||
AppBar(
|
||||
title: Text("Sharing with you"),
|
||||
elevation: 0,
|
||||
),
|
||||
Expanded(
|
||||
child: EmptyListIndicator(
|
||||
icon: Icons.share_outlined,
|
||||
text: L10n.of(context).listEmptyText,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Stack(
|
||||
children: [
|
||||
Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
accentColor: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
title: Text("Sharing with you"),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
sliver: SliverStaggeredGrid.extentBuilder(
|
||||
maxCrossAxisExtent: 256,
|
||||
mainAxisSpacing: 8,
|
||||
itemCount: _items.length,
|
||||
itemBuilder: _buildItem,
|
||||
staggeredTileBuilder: (_) =>
|
||||
const StaggeredTile.count(1, 1),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!_isReady || state is ListPendingSharedAlbumBlocLoading)
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: const LinearProgressIndicator(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildItem(BuildContext context, int index) {
|
||||
final item = _items[index];
|
||||
return AlbumGridItemBuilder(
|
||||
account: widget.account,
|
||||
album: item.album,
|
||||
onTap: () => _onItemTap(context, item),
|
||||
).build(context);
|
||||
}
|
||||
|
||||
void _onStateChange(
|
||||
BuildContext context, ListPendingSharedAlbumBlocState state) {
|
||||
if (state is ListPendingSharedAlbumBlocSuccess ||
|
||||
state is ListPendingSharedAlbumBlocLoading) {
|
||||
_transformItems(state.items);
|
||||
} else if (state is ListPendingSharedAlbumBlocFailure) {
|
||||
SnackBarManager().showSnackBar(SnackBar(
|
||||
content: Text(exception_util.toUserString(state.exception, context)),
|
||||
duration: k.snackBarDurationNormal,
|
||||
));
|
||||
} else if (state is ListPendingSharedAlbumBlocInconsistent) {
|
||||
_bloc.add(ListPendingSharedAlbumBlocQuery(widget.account));
|
||||
}
|
||||
_isReady = true;
|
||||
}
|
||||
|
||||
void _onItemTap(BuildContext context, _GridItem item) {
|
||||
album_browser_util.open(context, widget.account, item.album);
|
||||
}
|
||||
|
||||
void _transformItems(List<ListPendingSharedAlbumBlocItem> items) {
|
||||
final sortedAlbums = items
|
||||
.map((e) => Tuple2(
|
||||
e.album.provider.latestItemTime ?? e.album.lastUpdated, e.album))
|
||||
.sorted((a, b) {
|
||||
// then sort in descending order
|
||||
final tmp = b.item1.compareTo(a.item1);
|
||||
if (tmp != 0) {
|
||||
return tmp;
|
||||
} else {
|
||||
return a.item2.name.compareTo(b.item2.name);
|
||||
}
|
||||
}).map((e) => e.item2);
|
||||
_items.clear();
|
||||
_items.addAll(sortedAlbums.map((e) => _GridItem(e)));
|
||||
}
|
||||
|
||||
Future<void> _importPotentialSharedAlbum() async {
|
||||
final fileRepo = FileRepo(FileWebdavDataSource());
|
||||
// don't want the potential albums to be cached at this moment
|
||||
final albumRepo = AlbumRepo(AlbumRemoteDataSource());
|
||||
try {
|
||||
await ImportPotentialSharedAlbum(fileRepo, albumRepo)(widget.account);
|
||||
} catch (e, stacktrace) {
|
||||
_log.shout(
|
||||
"[_importPotentialSharedAlbum] Failed while ImportPotentialSharedAlbum",
|
||||
e,
|
||||
stacktrace);
|
||||
}
|
||||
}
|
||||
|
||||
final _bloc = ListPendingSharedAlbumBloc();
|
||||
bool _isReady = false;
|
||||
|
||||
var _items = <_GridItem>[];
|
||||
|
||||
static final _log =
|
||||
Logger("widget.pending_albums._PendingAlbumsState");
|
||||
}
|
||||
|
||||
class _GridItem {
|
||||
_GridItem(this.album);
|
||||
|
||||
Album album;
|
||||
}
|
Loading…
Reference in a new issue