Skip to content

api: Don't allow connecting to servers <4.0 #1410

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

Merged
merged 12 commits into from
Apr 2, 2025
Merged
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
13 changes: 13 additions & 0 deletions assets/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,10 @@
"@dialogClose": {
"description": "Button label in dialogs to close."
},
"errorDialogLearnMore": "Learn more",
"@errorDialogLearnMore": {
"description": "Button label in error dialogs to open a web page with more information."
},
"errorDialogContinue": "OK",
"@errorDialogContinue": {
"description": "Button label in error dialogs to acknowledge the error and close the dialog."
Expand Down Expand Up @@ -534,6 +538,15 @@
"@topicValidationErrorMandatoryButEmpty": {
"description": "Topic validation error when topic is required but was empty."
},
"errorServerVersionUnsupportedMessage": "{url} is running Zulip Server {zulipVersion}, which is unsupported. The minimum supported version is Zulip Server {minSupportedZulipVersion}.",
"@errorServerVersionUnsupportedMessage": {
"description": "Error message in the dialog for when the Zulip Server version is unsupported.",
"placeholders": {
"url": {"type": "String", "example": "http://chat.example.com/"},
"zulipVersion": {"type": "String", "example": "3.2"},
"minSupportedZulipVersion": {"type": "String", "example": "4.0"}
}
},
"errorInvalidApiKeyMessage": "Your account at {url} could not be authenticated. Please try logging in again or use another account.",
"@errorInvalidApiKeyMessage": {
"description": "Error message in the dialog for invalid API key.",
Expand Down
18 changes: 18 additions & 0 deletions lib/api/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ import '../model/binding.dart';
import '../model/localizations.dart';
import 'exception.dart';

/// The Zulip Server version below which we should refuse to connect.
///
/// When updating this, also update [kMinSupportedZulipFeatureLevel]
/// and the README.
const kMinSupportedZulipVersion = '4.0';

/// The Zulip feature level reserved for the [kMinSupportedZulipVersion] release.
///
/// For this value, see the API changelog:
/// https://zulip.com/api/changelog
const kMinSupportedZulipFeatureLevel = 65;

/// The doc stating our oldest supported server version.
// TODO: Instead, link to new Help Center doc once we have it:
// https://github.com/zulip/zulip/issues/23842
final kServerSupportDocUrl = Uri.parse(
'https://zulip.readthedocs.io/en/latest/overview/release-lifecycle.html#client-apps');

/// A fused JSON + UTF-8 decoder.
///
/// This object is an instance of [`_JsonUtf8Decoder`][1] which is
Expand Down
12 changes: 12 additions & 0 deletions lib/generated/l10n/zulip_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,12 @@ abstract class ZulipLocalizations {
/// **'Close'**
String get dialogClose;

/// Button label in error dialogs to open a web page with more information.
///
/// In en, this message translates to:
/// **'Learn more'**
String get errorDialogLearnMore;

/// Button label in error dialogs to acknowledge the error and close the dialog.
///
/// In en, this message translates to:
Expand Down Expand Up @@ -819,6 +825,12 @@ abstract class ZulipLocalizations {
/// **'Topics are required in this organization.'**
String get topicValidationErrorMandatoryButEmpty;

/// Error message in the dialog for when the Zulip Server version is unsupported.
///
/// In en, this message translates to:
/// **'{url} is running Zulip Server {zulipVersion}, which is unsupported. The minimum supported version is Zulip Server {minSupportedZulipVersion}.'**
String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion);

/// Error message in the dialog for invalid API key.
///
/// In en, this message translates to:
Expand Down
8 changes: 8 additions & 0 deletions lib/generated/l10n/zulip_localizations_ar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
@override
String get dialogClose => 'Close';

@override
String get errorDialogLearnMore => 'Learn more';

@override
String get errorDialogContinue => 'OK';

Expand Down Expand Up @@ -413,6 +416,11 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
@override
String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.';

@override
String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) {
return '$url is running Zulip Server $zulipVersion, which is unsupported. The minimum supported version is Zulip Server $minSupportedZulipVersion.';
}

@override
String errorInvalidApiKeyMessage(String url) {
return 'Your account at $url could not be authenticated. Please try logging in again or use another account.';
Expand Down
8 changes: 8 additions & 0 deletions lib/generated/l10n/zulip_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
@override
String get dialogClose => 'Close';

@override
String get errorDialogLearnMore => 'Learn more';

@override
String get errorDialogContinue => 'OK';

Expand Down Expand Up @@ -413,6 +416,11 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
@override
String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.';

@override
String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) {
return '$url is running Zulip Server $zulipVersion, which is unsupported. The minimum supported version is Zulip Server $minSupportedZulipVersion.';
}

@override
String errorInvalidApiKeyMessage(String url) {
return 'Your account at $url could not be authenticated. Please try logging in again or use another account.';
Expand Down
8 changes: 8 additions & 0 deletions lib/generated/l10n/zulip_localizations_ja.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
@override
String get dialogClose => 'Close';

@override
String get errorDialogLearnMore => 'Learn more';

@override
String get errorDialogContinue => 'OK';

Expand Down Expand Up @@ -413,6 +416,11 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
@override
String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.';

@override
String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) {
return '$url is running Zulip Server $zulipVersion, which is unsupported. The minimum supported version is Zulip Server $minSupportedZulipVersion.';
}

@override
String errorInvalidApiKeyMessage(String url) {
return 'Your account at $url could not be authenticated. Please try logging in again or use another account.';
Expand Down
8 changes: 8 additions & 0 deletions lib/generated/l10n/zulip_localizations_nb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
@override
String get dialogClose => 'Close';

@override
String get errorDialogLearnMore => 'Learn more';

@override
String get errorDialogContinue => 'OK';

Expand Down Expand Up @@ -413,6 +416,11 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
@override
String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.';

@override
String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) {
return '$url is running Zulip Server $zulipVersion, which is unsupported. The minimum supported version is Zulip Server $minSupportedZulipVersion.';
}

@override
String errorInvalidApiKeyMessage(String url) {
return 'Your account at $url could not be authenticated. Please try logging in again or use another account.';
Expand Down
8 changes: 8 additions & 0 deletions lib/generated/l10n/zulip_localizations_pl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
@override
String get dialogClose => 'Zamknij';

@override
String get errorDialogLearnMore => 'Learn more';

@override
String get errorDialogContinue => 'OK';

Expand Down Expand Up @@ -413,6 +416,11 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
@override
String get topicValidationErrorMandatoryButEmpty => 'Wątki są wymagane przez tę organizację.';

@override
String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) {
return '$url is running Zulip Server $zulipVersion, which is unsupported. The minimum supported version is Zulip Server $minSupportedZulipVersion.';
}

@override
String errorInvalidApiKeyMessage(String url) {
return 'Konto w ramach $url nie zostało przyjęte. Spróbuj ponownie lub skorzystaj z innego konta.';
Expand Down
8 changes: 8 additions & 0 deletions lib/generated/l10n/zulip_localizations_ru.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
@override
String get dialogClose => 'Закрыть';

@override
String get errorDialogLearnMore => 'Learn more';

@override
String get errorDialogContinue => 'OK';

Expand Down Expand Up @@ -413,6 +416,11 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
@override
String get topicValidationErrorMandatoryButEmpty => 'Темы обязательны в этой организации.';

@override
String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) {
return '$url is running Zulip Server $zulipVersion, which is unsupported. The minimum supported version is Zulip Server $minSupportedZulipVersion.';
}

@override
String errorInvalidApiKeyMessage(String url) {
return 'Your account at $url could not be authenticated. Please try logging in again or use another account.';
Expand Down
8 changes: 8 additions & 0 deletions lib/generated/l10n/zulip_localizations_sk.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
@override
String get dialogClose => 'Zavrieť';

@override
String get errorDialogLearnMore => 'Learn more';

@override
String get errorDialogContinue => 'OK';

Expand Down Expand Up @@ -413,6 +416,11 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
@override
String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.';

@override
String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) {
return '$url is running Zulip Server $zulipVersion, which is unsupported. The minimum supported version is Zulip Server $minSupportedZulipVersion.';
}

@override
String errorInvalidApiKeyMessage(String url) {
return 'Your account at $url could not be authenticated. Please try logging in again or use another account.';
Expand Down
12 changes: 10 additions & 2 deletions lib/log.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ void profilePrint(String message) {
// `null` for the `message` parameter and promptly dismiss the reported errors.
typedef ReportErrorCancellablyCallback = void Function(String? message, {String? details});

typedef ReportErrorCallback = void Function(String title, {String? message});
typedef ReportErrorCallback = void Function(
String title, {
String? message,
Uri? learnMoreButtonUrl,
});

/// Show the user an error message, without requiring them to interact with it.
///
Expand Down Expand Up @@ -96,7 +100,11 @@ void defaultReportErrorToUserBriefly(String? message, {String? details}) {
_reportErrorToConsole(message, details);
}

void defaultReportErrorToUserModally(String title, {String? message}) {
void defaultReportErrorToUserModally(
String title, {
String? message,
Uri? learnMoreButtonUrl,
}) {
_reportErrorToConsole(title, message);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/model/binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef FirebaseRemoteMessage = firebase_messaging.RemoteMessage;
///
/// Most code should not interact with the bindings directly.
/// Instead, use the corresponding higher-level APIs that expose the bindings'
/// functionality in a widget-oriented way.
/// functionality in a widget-oriented way; see [PlatformActions] for some.
///
/// This piece of architecture is modelled on the "binding" classes in Flutter
/// itself. For discussion, see [BindingBase], [WidgetsFlutterBinding], and
Expand Down
Loading