import 'package:flutter/material.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; class InviteStoryPage extends StatefulWidget { final Room? storiesRoom; const InviteStoryPage({ required this.storiesRoom, Key? key, }) : super(key: key); @override InviteStoryPageState createState() => InviteStoryPageState(); } class InviteStoryPageState extends State { Set _undecided = {}; final Set _invite = {}; void _inviteAction() async { final confirmed = await showOkCancelAlertDialog( context: context, message: L10n.of(context)!.storyPrivacyWarning, okLabel: L10n.of(context)!.iUnderstand, cancelLabel: L10n.of(context)!.cancel, ); if (confirmed != OkCancelResult.ok) return; final result = await showFutureLoadingDialog( context: context, future: () async { final client = Matrix.of(context).client; var room = await client.getStoriesRoom(context); final inviteList = _invite.toList(); if (room == null) { room = await client.createStoriesRoom(inviteList.take(10).toList()); if (inviteList.length > 10) { inviteList.removeRange(0, 10); } else { inviteList.clear(); } } for (final userId in inviteList) { room.invite(userId); } _undecided.removeAll(_invite); _undecided.addAll(client.storiesBlockList); await client.setStoriesBlockList(_undecided.toList()); }, ); if (result.error != null) return; Navigator.of(context).pop(true); } Future>? loadContacts; @override Widget build(BuildContext context) { loadContacts ??= Matrix.of(context) .client .getUndecidedContactsForStories(widget.storiesRoom) .then((contacts) { return contacts; }); return Scaffold( appBar: AppBar( leading: IconButton( icon: const Icon(Icons.close), onPressed: () => Navigator.of(context).pop(false), ), title: Text(L10n.of(context)!.whoCanSeeMyStories), elevation: 0, ), body: Column( children: [ ListTile( title: Text(L10n.of(context)!.whoCanSeeMyStoriesDesc), leading: CircleAvatar( backgroundColor: Theme.of(context).secondaryHeaderColor, foregroundColor: Theme.of(context).colorScheme.secondary, child: const Icon(Icons.lock), ), ), const Divider(height: 1), Expanded( child: FutureBuilder>( future: loadContacts, builder: (context, snapshot) { final contacts = snapshot.data; if (contacts == null) { final error = snapshot.error; if (error != null) { return Center( child: Text(error.toLocalizedString(context))); } return const Center( child: CircularProgressIndicator.adaptive()); } _undecided = contacts.map((u) => u.id).toSet(); return ListView.builder( itemCount: contacts.length, itemBuilder: (context, i) => SwitchListTile.adaptive( value: _invite.contains(contacts[i].id), onChanged: (b) => setState(() => b ? _invite.add(contacts[i].id) : _invite.remove(contacts[i].id)), secondary: Avatar( mxContent: contacts[i].avatarUrl, name: contacts[i].calcDisplayname(), ), title: Text(contacts[i].calcDisplayname()), ), ); }), ), ], ), floatingActionButton: FloatingActionButton.extended( onPressed: _inviteAction, label: Text(L10n.of(context)!.publish), backgroundColor: Theme.of(context).colorScheme.surface, foregroundColor: Theme.of(context).colorScheme.onSurface, icon: const Icon(Icons.send_rounded), ), ); } }