nc-photos/lib/widget/share_album_dialog.dart
2021-09-16 03:53:10 +08:00

187 lines
5.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.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_share.dart';
import 'package:nc_photos/bloc/list_sharee.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/share.dart';
import 'package:nc_photos/entity/share/data_source.dart';
import 'package:nc_photos/entity/sharee.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/snack_bar_manager.dart';
class ShareAlbumDialog extends StatefulWidget {
const ShareAlbumDialog({
Key? key,
required this.account,
required this.file,
}) : super(key: key);
@override
createState() => _ShareAlbumDialogState();
final Account account;
final File file;
}
class _ShareAlbumDialogState extends State<ShareAlbumDialog> {
@override
initState() {
super.initState();
_shareeBloc.add(ListShareeBlocQuery(widget.account));
_shareBloc.add(ListShareBlocQuery(widget.account, widget.file));
}
@override
build(BuildContext context) {
return BlocListener<ListShareeBloc, ListShareeBlocState>(
bloc: _shareeBloc,
listener: (context, shareeState) =>
_onListShareeBlocStateChanged(context, shareeState),
child: BlocBuilder<ListShareeBloc, ListShareeBlocState>(
bloc: _shareeBloc,
builder: (_, shareeState) =>
BlocBuilder<ListShareBloc, ListShareBlocState>(
bloc: _shareBloc,
builder: (context, shareState) =>
_buildContent(context, shareeState, shareState),
),
),
);
}
Widget _buildContent(BuildContext context, ListShareeBlocState shareeState,
ListShareBlocState shareState) {
final List<Widget> children;
if (shareeState is ListShareeBlocLoading ||
shareState is ListShareBlocLoading) {
children = [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 24),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const CircularProgressIndicator(),
const SizedBox(width: 24),
Text(L10n.global().genericProcessingDialogContent),
],
),
),
];
} else {
children = shareeState.items
.where((element) => element.type == ShareeType.user)
.sorted((a, b) => a.label.compareTo(b.label))
.map((sharee) => _buildItem(context, shareState, sharee))
.toList();
}
return SimpleDialog(
title: const Text("Share with user"),
children: children,
);
}
Widget _buildItem(
BuildContext context, ListShareBlocState shareState, Sharee sharee) {
final Share? share;
if (_overrideSharee.containsKey(sharee.shareWith)) {
share = _overrideSharee[sharee.shareWith];
} else {
share = shareState.items
.where((element) => element.shareWith == sharee.shareWith)
.firstOrNull;
}
final isProcessing =
_processingSharee.any((element) => element == sharee.shareWith);
final Widget trailing;
if (isProcessing) {
trailing = const Padding(
padding: EdgeInsetsDirectional.only(end: 12),
child: SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(),
),
);
} else {
trailing = Checkbox(
value: share != null,
onChanged: (value) {},
);
}
return SimpleDialogOption(
child: ListTile(
dense: true,
title: Text(sharee.label),
// pass through the tap event
trailing: IgnorePointer(
child: trailing,
),
),
onPressed: () => _onShareePressed(sharee, share),
);
}
void _onListShareeBlocStateChanged(
BuildContext context, ListShareeBlocState state) {
if (state is ListShareeBlocFailure) {
SnackBarManager().showSnackBar(SnackBar(
content: Text(exception_util.toUserString(state.exception)),
duration: k.snackBarDurationNormal,
));
}
}
void _onShareePressed(Sharee sharee, Share? share) async {
final shareRepo = ShareRepo(ShareRemoteDataSource());
setState(() {
_processingSharee.add(sharee.shareWith);
});
if (share == null) {
// create new share
try {
final newShare = await shareRepo.create(
widget.account, widget.file, sharee.shareWith);
_overrideSharee[sharee.shareWith] = newShare;
} catch (e, stackTrace) {
_log.shout("[_onShareePressed] Failed while create", e, stackTrace);
SnackBarManager().showSnackBar(SnackBar(
content: Text(exception_util.toUserString(e)),
duration: k.snackBarDurationNormal,
));
}
} else {
// remove share
try {
await Future.delayed(const Duration(seconds: 3));
await shareRepo.delete(widget.account, share);
_overrideSharee[sharee.shareWith] = null;
} catch (e, stackTrace) {
_log.shout("[_onShareePressed] Failed while delete", e, stackTrace);
SnackBarManager().showSnackBar(SnackBar(
content: Text(exception_util.toUserString(e)),
duration: k.snackBarDurationNormal,
));
}
}
setState(() {
_processingSharee.remove(sharee.shareWith);
});
}
final _shareeBloc = ListShareeBloc();
final _shareBloc = ListShareBloc();
final _processingSharee = <String>[];
/// Store the modified value of each sharee
final _overrideSharee = <String, Share?>{};
static final _log =
Logger("widget.share_album_dialog._ShareAlbumDialogState");
}