@@ -7,9 +7,11 @@ import '../api/exception.dart';
77import '../api/model/model.dart' ;
88import '../api/model/narrow.dart' ;
99import '../api/route/messages.dart' ;
10+ import '../api/route/channels.dart' as channels_api;
1011import '../generated/l10n/zulip_localizations.dart' ;
1112import '../model/binding.dart' ;
1213import '../model/narrow.dart' ;
14+ import '../model/realm.dart' ;
1315import 'dialog.dart' ;
1416import 'store.dart' ;
1517
@@ -239,6 +241,50 @@ abstract final class ZulipAction {
239241
240242 return fetchedMessage? .content;
241243 }
244+
245+ static Future <void > unsubscribeFromChannel (BuildContext context, {
246+ required int channelId,
247+ }) async {
248+ final store = PerAccountStoreWidget .of (context);
249+ final subscription = store.subscriptions[channelId];
250+ if (subscription == null ) return ; // TODO could give feedback
251+
252+ // TODO(future) check if the self-user is a guest and the channel is not web-public
253+ final couldResubscribe = ! subscription.inviteOnly
254+ || store.selfHasPermissionForGroupSetting (subscription.canSubscribeGroup,
255+ GroupSettingType .stream, 'can_subscribe_group' );
256+ if (! couldResubscribe) {
257+ // TODO(#1788) warn if org would lose content access (nobody can subscribe)
258+ final zulipLocalizations = ZulipLocalizations .of (context);
259+
260+ final dialog = showSuggestedActionDialog (context: context,
261+ title: zulipLocalizations.unsubscribeConfirmationDialogTitle (subscription.name),
262+ message: zulipLocalizations.unsubscribeConfirmationDialogMessageCannotResubscribe,
263+ destructiveActionButton: true ,
264+ actionButtonText: zulipLocalizations.unsubscribeConfirmationDialogConfirmButton);
265+ if (await dialog.result != true ) return ;
266+ if (! context.mounted) return ;
267+ }
268+
269+ try {
270+ await channels_api.unsubscribeFromChannel (PerAccountStoreWidget .of (context).connection,
271+ subscriptions: [subscription.name]);
272+ } catch (e) {
273+ if (! context.mounted) return ;
274+
275+ String ? errorMessage;
276+ switch (e) {
277+ case ZulipApiException ():
278+ errorMessage = e.message;
279+ // TODO(#741) specific messages for common errors, like network errors
280+ // (support with reusable code)
281+ default :
282+ }
283+
284+ final title = ZulipLocalizations .of (context).unsubscribeFailedTitle;
285+ showErrorDialog (context: context, title: title, message: errorMessage);
286+ }
287+ }
242288}
243289
244290/// Methods that act through platform APIs and show feedback in the UI.
0 commit comments