moxxy/lib/ui/pages/share_selection.dart

128 lines
4.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import 'package:move_to_background/move_to_background.dart';
import 'package:moxxyv2/i18n/strings.g.dart';
import 'package:moxxyv2/shared/constants.dart';
import 'package:moxxyv2/ui/bloc/navigation_bloc.dart' as navigation;
import 'package:moxxyv2/ui/bloc/share_selection_bloc.dart';
import 'package:moxxyv2/ui/constants.dart';
import 'package:moxxyv2/ui/helpers.dart';
import 'package:moxxyv2/ui/widgets/conversation.dart';
import 'package:moxxyv2/ui/widgets/topbar.dart';
class ShareSelectionPage extends StatelessWidget {
const ShareSelectionPage({ super.key });
static MaterialPageRoute<dynamic> get route => MaterialPageRoute<dynamic>(
builder: (_) => const ShareSelectionPage(),
settings: const RouteSettings(
name: shareSelectionRoute,
),
);
bool _buildWhen(ShareSelectionState prev, ShareSelectionState next) {
// Prevent rebuilding when items changes. This prevents us from having to deal with
// a roster update coming in while we are selecting JIDs to share to.
// TODO(Unknown): But does it work?
return prev.selection != next.selection ||
prev.paths != next.paths ||
prev.text != next.text ||
prev.type != next.type;
}
@override
Widget build(BuildContext context) {
final maxTextWidth = MediaQuery.of(context).size.width * 0.6;
return WillPopScope(
onWillPop: () async {
GetIt.I.get<ShareSelectionBloc>().add(ResetEvent());
// Navigate to the conversations page...
GetIt.I.get<navigation.NavigationBloc>().add(
navigation.PushedNamedAndRemoveUntilEvent(
const navigation.NavigationDestination(conversationsRoute),
(_) => false,
),
);
// ...and put the app back into the background
await MoveToBackground.moveTaskToBack();
return false;
},
child: BlocBuilder<ShareSelectionBloc, ShareSelectionState>(
buildWhen: _buildWhen,
builder: (context, state) => Scaffold(
appBar: BorderlessTopbar.simple(t.pages.shareselection.shareWith),
body: ListView.builder(
itemCount: state.items.length,
itemBuilder: (context, index) {
final item = state.items[index];
final isSelected = state.selection.contains(index);
return InkWell(
onTap: () {
context.read<ShareSelectionBloc>().add(
SelectionToggledEvent(index),
);
},
child: ConversationsListRow(
item.avatarPath,
item.title,
item.jid,
0,
maxTextWidth,
timestampNever,
false,
showLock: item.isEncrypted,
extra: Checkbox(
value: isSelected,
onChanged: (_) {
context.read<ShareSelectionBloc>().add(
SelectionToggledEvent(index),
);
},
),
),
);
},
),
floatingActionButton: state.selection.isNotEmpty ?
FloatingActionButton(
onPressed: () {
final bloc = context.read<ShareSelectionBloc>();
final hasUnencrypted = bloc.state.selection.any((selection) {
return !bloc.state.items[selection].isEncrypted;
});
final hasEncrypted = bloc.state.selection.any((selection) {
return bloc.state.items[selection].isEncrypted;
});
// Warn the user
if (hasUnencrypted && hasEncrypted) {
showConfirmationDialog(
t.pages.shareselection.confirmTitle,
t.pages.shareselection.confirmBody,
context,
() {
bloc.add(SubmittedEvent());
}
);
return;
}
bloc.add(SubmittedEvent());
},
child: const Icon(
Icons.send,
color: Colors.white,
),
) :
null,
),
),
);
}
}