Skip to content

startup: Add beta-complete dialog #1797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: beta-prelaunch
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/widgets/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ class _ZulipAppState extends State<ZulipApp> with WidgetsBindingObserver {
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);

// On every startup is fine; the goal is to be assertive but stop short of a
// rug-pull where we just disable all the app's features.
showBetaCompleteDialog();
}

@override
Expand Down
76 changes: 76 additions & 0 deletions lib/widgets/dialog.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import '../generated/l10n/zulip_localizations.dart';
import 'actions.dart';
import 'app.dart';

Widget _dialogActionText(String text) {
return Text(
Expand Down Expand Up @@ -112,3 +116,75 @@ DialogStatus<bool> showSuggestedActionDialog({
]));
return DialogStatus(future);
}

bool debugDisableBetaCompleteDialog = false;
void resetDebugDisableBetaCompleteDialog() {
debugDisableBetaCompleteDialog = false;
}

/// Show a brief dialog box saying that this beta channel has ended,
/// offering a way to get the app from prod.
void showBetaCompleteDialog() async {
if (debugDisableBetaCompleteDialog) return;

final navigator = await ZulipApp.navigator;
final context = navigator.context;
assert(context.mounted);
if (!context.mounted) return; // TODO(linter): this is impossible as there's no actual async gap, but the use_build_context_synchronously lint doesn't see that

switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
break;
case TargetPlatform.macOS:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
// Do nothing on these unsupported platforms.
return;
}

final zulipLocalizations = ZulipLocalizations.of(context);

final message = 'Since Zulip’s new Flutter app has launched, this beta app is no longer maintained. We strongly recommend uninstalling it and switching to the main Zulip application to get the latest features and bug fixes. Thank you for being a beta tester!';

unawaited(showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: Text('Time to switch to the new app'),
content: SingleChildScrollView(child: Text(message)),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: _dialogActionText('Got it')),
...(switch (defaultTargetPlatform) {
TargetPlatform.android => [
TextButton(
onPressed: () {
Navigator.pop(context);
PlatformActions.launchUrl(context,
Uri.parse('https://github.com/zulip/zulip-flutter/releases/latest'));
},
child: _dialogActionText('Download official APKs (less common)')),
TextButton(
onPressed: () {
Navigator.pop(context);
PlatformActions.launchUrl(context,
Uri.parse('https://play.google.com/store/apps/details?id=com.zulipmobile'));
},
child: _dialogActionText('Open Google Play Store'))
],
TargetPlatform.iOS => [
TextButton(
onPressed: () {
Navigator.pop(context);
PlatformActions.launchUrl(context,
Uri.parse('https://apps.apple.com/app/zulip/id1203036395'));
},
child: _dialogActionText('Open App Store')),
],
TargetPlatform.macOS || TargetPlatform.fuchsia
|| TargetPlatform.linux || TargetPlatform.windows => throw UnimplementedError(),
}),
])));
}
3 changes: 3 additions & 0 deletions test/notifications/open_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:zulip/model/narrow.dart';
import 'package:zulip/notifications/open.dart';
import 'package:zulip/notifications/receive.dart';
import 'package:zulip/widgets/app.dart';
import 'package:zulip/widgets/dialog.dart';
import 'package:zulip/widgets/home.dart';
import 'package:zulip/widgets/message_list.dart';
import 'package:zulip/widgets/page.dart';
Expand Down Expand Up @@ -76,6 +77,8 @@ void main() {
final zulipLocalizations = GlobalLocalizations.zulipLocalizations;

Future<void> init({bool addSelfAccount = true}) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
if (addSelfAccount) {
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
}
Expand Down
13 changes: 13 additions & 0 deletions test/widgets/app_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:zulip/log.dart';
import 'package:zulip/model/actions.dart';
import 'package:zulip/model/database.dart';
import 'package:zulip/widgets/app.dart';
import 'package:zulip/widgets/dialog.dart';
import 'package:zulip/widgets/home.dart';
import 'package:zulip/widgets/page.dart';

Expand All @@ -27,6 +28,8 @@ void main() {
late List<Route<dynamic>> pushedRoutes = [];

Future<void> prepare(WidgetTester tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);

pushedRoutes = [];
Expand Down Expand Up @@ -64,6 +67,8 @@ void main() {
late List<Route<void>> poppedRoutes;

Future<void> prepare(WidgetTester tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);

pushedRoutes = [];
Expand Down Expand Up @@ -279,6 +284,8 @@ void main() {
});

testWidgets('choosing an account clears the navigator stack', (tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
await testBinding.globalStore.add(eg.otherAccount, eg.initialSnapshot());
Expand Down Expand Up @@ -391,6 +398,8 @@ void main() {
});

testWidgets('reportErrorToUserBriefly with details', (tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);
await tester.pumpWidget(const ZulipApp());
const message = 'test error message';
Expand Down Expand Up @@ -418,6 +427,8 @@ void main() {
});

Future<void> prepareSnackBarWithDetails(WidgetTester tester, String message, String details) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);
await tester.pumpWidget(const ZulipApp());
await tester.pump();
Expand Down Expand Up @@ -484,6 +495,8 @@ void main() {
});

testWidgets('reportErrorToUserModally', (tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);
await tester.pumpWidget(const ZulipApp());
const title = 'test title';
Expand Down
11 changes: 11 additions & 0 deletions test/widgets/home_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:zulip/model/store.dart';
import 'package:zulip/widgets/about_zulip.dart';
import 'package:zulip/widgets/app.dart';
import 'package:zulip/widgets/app_bar.dart';
import 'package:zulip/widgets/dialog.dart';
import 'package:zulip/widgets/home.dart';
import 'package:zulip/widgets/icons.dart';
import 'package:zulip/widgets/inbox.dart';
Expand Down Expand Up @@ -48,6 +49,8 @@ void main () {
..onPopped = ((route, prevRoute) => lastPoppedRoute = route);

Future<void> prepare(WidgetTester tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);
topRoute = null;
previousTopRoute = null;
Expand Down Expand Up @@ -272,6 +275,8 @@ void main () {
});

testWidgets('menu buttons dismiss the menu', (tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);
topRoute = null;
previousTopRoute = null;
Expand Down Expand Up @@ -328,6 +333,8 @@ void main () {
}

Future<void> prepare(WidgetTester tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);
topRoute = null;
previousTopRoute = null;
Expand Down Expand Up @@ -521,6 +528,8 @@ void main () {
});

testWidgets('logging out while still loading', (tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
// Regression test for: https://github.com/zulip/zulip-flutter/issues/1219
addTearDown(testBinding.reset);
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
Expand All @@ -537,6 +546,8 @@ void main () {
});

testWidgets('logging out after fully loaded', (tester) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
// Regression test for: https://github.com/zulip/zulip-flutter/issues/1219
addTearDown(testBinding.reset);
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
Expand Down
3 changes: 3 additions & 0 deletions test/widgets/login_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:zulip/model/binding.dart';
import 'package:zulip/model/database.dart';
import 'package:zulip/model/localizations.dart';
import 'package:zulip/widgets/app.dart';
import 'package:zulip/widgets/dialog.dart';
import 'package:zulip/widgets/home.dart';
import 'package:zulip/widgets/login.dart';
import 'package:zulip/widgets/page.dart';
Expand Down Expand Up @@ -83,6 +84,8 @@ void main() {

Future<void> prepare(WidgetTester tester,
GetServerSettingsResult serverSettings) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
addTearDown(testBinding.reset);

connection = testBinding.globalStore.apiConnection(
Expand Down
3 changes: 3 additions & 0 deletions test/widgets/message_list_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import 'package:zulip/widgets/autocomplete.dart';
import 'package:zulip/widgets/color.dart';
import 'package:zulip/widgets/compose_box.dart';
import 'package:zulip/widgets/content.dart';
import 'package:zulip/widgets/dialog.dart';
import 'package:zulip/widgets/icons.dart';
import 'package:zulip/widgets/message_list.dart';
import 'package:zulip/widgets/page.dart';
Expand Down Expand Up @@ -73,6 +74,8 @@ void main() {
bool skipAssertAccountExists = false,
bool skipPumpAndSettle = false,
}) async {
debugDisableBetaCompleteDialog = true;
addTearDown(resetDebugDisableBetaCompleteDialog);
TypingNotifier.debugEnable = false;
addTearDown(TypingNotifier.debugReset);
addTearDown(testBinding.reset);
Expand Down
Loading