Skip to content

Commit 83c2d46

Browse files
committed
action_sheet [nfc]: Move unsubscribe-from-channel logic to ZulipAction
1 parent fd5b9a3 commit 83c2d46

File tree

2 files changed

+52
-40
lines changed

2 files changed

+52
-40
lines changed

lib/widgets/action_sheet.dart

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import '../model/content.dart';
1717
import '../model/emoji.dart';
1818
import '../model/internal_link.dart';
1919
import '../model/narrow.dart';
20-
import '../model/realm.dart';
2120
import 'actions.dart';
2221
import 'button.dart';
2322
import 'color.dart';
@@ -634,45 +633,7 @@ class UnsubscribeButton extends ActionSheetMenuItemButton {
634633

635634
@override
636635
void onPressed() async {
637-
final store = PerAccountStoreWidget.of(pageContext);
638-
final subscription = store.subscriptions[channelId];
639-
if (subscription == null) return; // TODO could give feedback
640-
641-
// TODO(future) check if the self-user is a guest and the channel is not web-public
642-
final couldResubscribe = !subscription.inviteOnly
643-
|| store.selfHasPermissionForGroupSetting(subscription.canSubscribeGroup,
644-
GroupSettingType.stream, 'can_subscribe_group');
645-
if (!couldResubscribe) {
646-
// TODO(#1788) warn if org would lose content access (nobody can subscribe)
647-
final zulipLocalizations = ZulipLocalizations.of(pageContext);
648-
649-
final dialog = showSuggestedActionDialog(context: pageContext,
650-
title: zulipLocalizations.unsubscribeConfirmationDialogTitle('#${subscription.name}'),
651-
message: zulipLocalizations.unsubscribeConfirmationDialogMessageCannotResubscribe,
652-
destructiveActionButton: true,
653-
actionButtonText: zulipLocalizations.unsubscribeConfirmationDialogConfirmButton);
654-
if (await dialog.result != true) return;
655-
if (!pageContext.mounted) return;
656-
}
657-
658-
try {
659-
await unsubscribeFromChannel(PerAccountStoreWidget.of(pageContext).connection,
660-
subscriptions: [subscription.name]);
661-
} catch (e) {
662-
if (!pageContext.mounted) return;
663-
664-
String? errorMessage;
665-
switch (e) {
666-
case ZulipApiException():
667-
errorMessage = e.message;
668-
// TODO(#741) specific messages for common errors, like network errors
669-
// (support with reusable code)
670-
default:
671-
}
672-
673-
final title = ZulipLocalizations.of(pageContext).unsubscribeFailedTitle;
674-
showErrorDialog(context: pageContext, title: title, message: errorMessage);
675-
}
636+
await ZulipAction.unsubscribeFromChannel(pageContext, channelId: channelId);
676637
}
677638
}
678639

lib/widgets/actions.dart

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import '../api/exception.dart';
77
import '../api/model/model.dart';
88
import '../api/model/narrow.dart';
99
import '../api/route/messages.dart';
10+
import '../api/route/channels.dart' as channels_api;
1011
import '../generated/l10n/zulip_localizations.dart';
1112
import '../model/binding.dart';
1213
import '../model/narrow.dart';
14+
import '../model/realm.dart';
1315
import 'dialog.dart';
1416
import 'store.dart';
1517

@@ -239,6 +241,55 @@ abstract final class ZulipAction {
239241

240242
return fetchedMessage?.content;
241243
}
244+
245+
/// Unsubscribe from a channel, possibly after a confirmation dialog,
246+
/// showing an error dialog on failure.
247+
///
248+
/// A confirmation dialog is shown if the user would not have permission
249+
/// to resubscribe.
250+
static Future<void> unsubscribeFromChannel(BuildContext context, {
251+
required int channelId,
252+
}) async {
253+
final store = PerAccountStoreWidget.of(context);
254+
final subscription = store.subscriptions[channelId];
255+
if (subscription == null) return; // TODO could give feedback
256+
257+
// TODO(future) check if the self-user is a guest and the channel is not web-public
258+
final couldResubscribe = !subscription.inviteOnly
259+
|| store.selfHasPermissionForGroupSetting(subscription.canSubscribeGroup,
260+
GroupSettingType.stream, 'can_subscribe_group');
261+
if (!couldResubscribe) {
262+
// TODO(#1788) warn if org would lose content access (nobody can subscribe)
263+
final zulipLocalizations = ZulipLocalizations.of(context);
264+
265+
final dialog = showSuggestedActionDialog(context: context,
266+
title: zulipLocalizations.unsubscribeConfirmationDialogTitle('#${subscription.name}'),
267+
message: zulipLocalizations.unsubscribeConfirmationDialogMessageCannotResubscribe,
268+
destructiveActionButton: true,
269+
actionButtonText: zulipLocalizations.unsubscribeConfirmationDialogConfirmButton);
270+
if (await dialog.result != true) return;
271+
if (!context.mounted) return;
272+
}
273+
274+
try {
275+
await channels_api.unsubscribeFromChannel(PerAccountStoreWidget.of(context).connection,
276+
subscriptions: [subscription.name]);
277+
} catch (e) {
278+
if (!context.mounted) return;
279+
280+
String? errorMessage;
281+
switch (e) {
282+
case ZulipApiException():
283+
errorMessage = e.message;
284+
// TODO(#741) specific messages for common errors, like network errors
285+
// (support with reusable code)
286+
default:
287+
}
288+
289+
final title = ZulipLocalizations.of(context).unsubscribeFailedTitle;
290+
showErrorDialog(context: context, title: title, message: errorMessage);
291+
}
292+
}
242293
}
243294

244295
/// Methods that act through platform APIs and show feedback in the UI.

0 commit comments

Comments
 (0)