diff --git a/lib/generated/l10n/zulip_localizations.dart b/lib/generated/l10n/zulip_localizations.dart index e8b15440e3..e326703e4b 100644 --- a/lib/generated/l10n/zulip_localizations.dart +++ b/lib/generated/l10n/zulip_localizations.dart @@ -68,7 +68,8 @@ import 'zulip_localizations_uk.dart'; /// be consistent with the languages listed in the ZulipLocalizations.supportedLocales /// property. abstract class ZulipLocalizations { - ZulipLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString()); + ZulipLocalizations(String locale) + : localeName = intl.Intl.canonicalizedLocale(locale.toString()); final String localeName; @@ -76,7 +77,8 @@ abstract class ZulipLocalizations { return Localizations.of(context, ZulipLocalizations)!; } - static const LocalizationsDelegate delegate = _ZulipLocalizationsDelegate(); + static const LocalizationsDelegate delegate = + _ZulipLocalizationsDelegate(); /// A list of this localizations delegate along with the default localizations /// delegates. @@ -88,12 +90,13 @@ abstract class ZulipLocalizations { /// Additional delegates can be added by appending to this list in /// MaterialApp. This list does not have to be used at all if a custom list /// of delegates is preferred or required. - static const List> localizationsDelegates = >[ - delegate, - GlobalMaterialLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ]; + static const List> localizationsDelegates = + >[ + delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; /// A list of this localizations delegate's supported locales. static const List supportedLocales = [ @@ -104,7 +107,7 @@ abstract class ZulipLocalizations { Locale('pl'), Locale('ru'), Locale('sk'), - Locale('uk') + Locale('uk'), ]; /// Title for About Zulip page. @@ -381,7 +384,11 @@ abstract class ZulipLocalizations { /// /// In en, this message translates to: /// **'{num, plural, =1{File is} other{{num} files are}} larger than the server\'s limit of {maxFileUploadSizeMib} MiB and will not be uploaded:\n\n{listMessage}'** - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage); + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ); /// Error title when attached files are too large in size. /// @@ -459,7 +466,11 @@ abstract class ZulipLocalizations { /// /// In en, this message translates to: /// **'Error handling a Zulip event from {serverUrl}; will retry.\n\nError: {error}\n\nEvent: {event}'** - String errorHandlingEventDetails(String serverUrl, String error, String event); + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ); /// Error title when opening a link failed. /// @@ -831,7 +842,11 @@ abstract class ZulipLocalizations { /// /// 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); + String errorServerVersionUnsupportedMessage( + String url, + String zulipVersion, + String minSupportedZulipVersion, + ); /// Error message in the dialog for invalid API key. /// @@ -1290,40 +1305,58 @@ abstract class ZulipLocalizations { String get zulipAppTitle; } -class _ZulipLocalizationsDelegate extends LocalizationsDelegate { +class _ZulipLocalizationsDelegate + extends LocalizationsDelegate { const _ZulipLocalizationsDelegate(); @override Future load(Locale locale) { - return SynchronousFuture(lookupZulipLocalizations(locale)); + return SynchronousFuture( + lookupZulipLocalizations(locale), + ); } @override - bool isSupported(Locale locale) => ['ar', 'en', 'ja', 'nb', 'pl', 'ru', 'sk', 'uk'].contains(locale.languageCode); + bool isSupported(Locale locale) => [ + 'ar', + 'en', + 'ja', + 'nb', + 'pl', + 'ru', + 'sk', + 'uk', + ].contains(locale.languageCode); @override bool shouldReload(_ZulipLocalizationsDelegate old) => false; } ZulipLocalizations lookupZulipLocalizations(Locale locale) { - - // Lookup logic when only language code is specified. switch (locale.languageCode) { - case 'ar': return ZulipLocalizationsAr(); - case 'en': return ZulipLocalizationsEn(); - case 'ja': return ZulipLocalizationsJa(); - case 'nb': return ZulipLocalizationsNb(); - case 'pl': return ZulipLocalizationsPl(); - case 'ru': return ZulipLocalizationsRu(); - case 'sk': return ZulipLocalizationsSk(); - case 'uk': return ZulipLocalizationsUk(); + case 'ar': + return ZulipLocalizationsAr(); + case 'en': + return ZulipLocalizationsEn(); + case 'ja': + return ZulipLocalizationsJa(); + case 'nb': + return ZulipLocalizationsNb(); + case 'pl': + return ZulipLocalizationsPl(); + case 'ru': + return ZulipLocalizationsRu(); + case 'sk': + return ZulipLocalizationsSk(); + case 'uk': + return ZulipLocalizationsUk(); } throw FlutterError( 'ZulipLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' 'an issue with the localizations generation tool. Please file an issue ' 'on GitHub with a reproducible sample app and the gen-l10n configuration ' - 'that was used.' + 'that was used.', ); } diff --git a/lib/generated/l10n/zulip_localizations_ar.dart b/lib/generated/l10n/zulip_localizations_ar.dart index c2478f4613..8d36fa6bd0 100644 --- a/lib/generated/l10n/zulip_localizations_ar.dart +++ b/lib/generated/l10n/zulip_localizations_ar.dart @@ -44,7 +44,8 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get logOutConfirmationDialogTitle => 'Log out?'; @override - String get logOutConfirmationDialogMessage => 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; + String get logOutConfirmationDialogMessage => + 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; @override String get logOutConfirmationDialogConfirmButton => 'Log out'; @@ -65,10 +66,12 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get permissionsNeededOpenSettings => 'Open settings'; @override - String get permissionsDeniedCameraAccess => 'To upload an image, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedCameraAccess => + 'To upload an image, please grant Zulip additional permissions in Settings.'; @override - String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedReadExternalStorage => + 'To upload files, please grant Zulip additional permissions in Settings.'; @override String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read'; @@ -95,7 +98,8 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved'; @override - String get errorUnresolveTopicFailedTitle => 'Failed to mark topic as unresolved'; + String get errorUnresolveTopicFailedTitle => + 'Failed to mark topic as unresolved'; @override String get actionSheetOptionCopyMessageText => 'Copy message text'; @@ -136,7 +140,8 @@ class ZulipLocalizationsAr extends ZulipLocalizations { } @override - String get errorCouldNotFetchMessageSource => 'Could not fetch message source'; + String get errorCouldNotFetchMessageSource => + 'Could not fetch message source'; @override String get errorCopyingFailed => 'Copying failed'; @@ -152,7 +157,11 @@ class ZulipLocalizationsAr extends ZulipLocalizations { } @override - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage) { + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ) { String _temp0 = intl.Intl.pluralLogic( num, locale: localeName, @@ -191,7 +200,8 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get errorCouldNotConnectTitle => 'Could not connect'; @override - String get errorMessageDoesNotSeemToExist => 'That message does not seem to exist.'; + String get errorMessageDoesNotSeemToExist => + 'That message does not seem to exist.'; @override String get errorQuotationFailed => 'Quotation failed'; @@ -202,7 +212,8 @@ class ZulipLocalizationsAr extends ZulipLocalizations { } @override - String get errorConnectingToServerShort => 'Error connecting to Zulip. Retrying…'; + String get errorConnectingToServerShort => + 'Error connecting to Zulip. Retrying…'; @override String errorConnectingToServerDetails(String serverUrl, String error) { @@ -210,10 +221,15 @@ class ZulipLocalizationsAr extends ZulipLocalizations { } @override - String get errorHandlingEventTitle => 'Error handling a Zulip event. Retrying connection…'; + String get errorHandlingEventTitle => + 'Error handling a Zulip event. Retrying connection…'; @override - String errorHandlingEventDetails(String serverUrl, String error, String event) { + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ) { return 'Error handling a Zulip event from $serverUrl; will retry.\n\nError: $error\n\nEvent: $event'; } @@ -256,10 +272,12 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get successMessageLinkCopied => 'Message link copied'; @override - String get errorBannerDeactivatedDmLabel => 'You cannot send messages to deactivated users.'; + String get errorBannerDeactivatedDmLabel => + 'You cannot send messages to deactivated users.'; @override - String get errorBannerCannotPostInChannelLabel => 'You do not have permission to post in this channel.'; + String get errorBannerCannotPostInChannelLabel => + 'You do not have permission to post in this channel.'; @override String get composeBoxAttachFilesTooltip => 'Attach files'; @@ -328,16 +346,19 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get messageListGroupYouWithYourself => 'Messages with yourself'; @override - String get contentValidationErrorTooLong => 'Message length shouldn\'t be greater than 10000 characters.'; + String get contentValidationErrorTooLong => + 'Message length shouldn\'t be greater than 10000 characters.'; @override String get contentValidationErrorEmpty => 'You have nothing to send!'; @override - String get contentValidationErrorQuoteAndReplyInProgress => 'Please wait for the quotation to complete.'; + String get contentValidationErrorQuoteAndReplyInProgress => + 'Please wait for the quotation to complete.'; @override - String get contentValidationErrorUploadInProgress => 'Please wait for the upload to complete.'; + String get contentValidationErrorUploadInProgress => + 'Please wait for the upload to complete.'; @override String get dialogCancel => 'Cancel'; @@ -411,13 +432,19 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get loginErrorMissingUsername => 'Please enter your username.'; @override - String get topicValidationErrorTooLong => 'Topic length shouldn\'t be greater than 60 characters.'; + String get topicValidationErrorTooLong => + 'Topic length shouldn\'t be greater than 60 characters.'; @override - String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.'; + String get topicValidationErrorMandatoryButEmpty => + 'Topics are required in this organization.'; @override - String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) { + 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.'; } @@ -457,10 +484,12 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get serverUrlValidationErrorInvalidUrl => 'Please enter a valid URL.'; @override - String get serverUrlValidationErrorNoUseEmail => 'Please enter the server URL, not your email.'; + String get serverUrlValidationErrorNoUseEmail => + 'Please enter the server URL, not your email.'; @override - String get serverUrlValidationErrorUnsupportedScheme => 'The server URL must start with http:// or https://.'; + String get serverUrlValidationErrorUnsupportedScheme => + 'The server URL must start with http:// or https://.'; @override String get spoilerDefaultHeaderText => 'Spoiler'; @@ -655,13 +684,15 @@ class ZulipLocalizationsAr extends ZulipLocalizations { String get experimentalFeatureSettingsPageTitle => 'Experimental features'; @override - String get experimentalFeatureSettingsWarning => 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; + String get experimentalFeatureSettingsWarning => + 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; @override String get errorNotificationOpenTitle => 'Failed to open notification'; @override - String get errorNotificationOpenAccountMissing => 'The account associated with this notification no longer exists.'; + String get errorNotificationOpenAccountMissing => + 'The account associated with this notification no longer exists.'; @override String get errorReactionAddingFailedTitle => 'Adding reaction failed'; diff --git a/lib/generated/l10n/zulip_localizations_en.dart b/lib/generated/l10n/zulip_localizations_en.dart index 289ba33af2..a74a2e1eaf 100644 --- a/lib/generated/l10n/zulip_localizations_en.dart +++ b/lib/generated/l10n/zulip_localizations_en.dart @@ -44,7 +44,8 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get logOutConfirmationDialogTitle => 'Log out?'; @override - String get logOutConfirmationDialogMessage => 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; + String get logOutConfirmationDialogMessage => + 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; @override String get logOutConfirmationDialogConfirmButton => 'Log out'; @@ -65,10 +66,12 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get permissionsNeededOpenSettings => 'Open settings'; @override - String get permissionsDeniedCameraAccess => 'To upload an image, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedCameraAccess => + 'To upload an image, please grant Zulip additional permissions in Settings.'; @override - String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedReadExternalStorage => + 'To upload files, please grant Zulip additional permissions in Settings.'; @override String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read'; @@ -95,7 +98,8 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved'; @override - String get errorUnresolveTopicFailedTitle => 'Failed to mark topic as unresolved'; + String get errorUnresolveTopicFailedTitle => + 'Failed to mark topic as unresolved'; @override String get actionSheetOptionCopyMessageText => 'Copy message text'; @@ -136,7 +140,8 @@ class ZulipLocalizationsEn extends ZulipLocalizations { } @override - String get errorCouldNotFetchMessageSource => 'Could not fetch message source'; + String get errorCouldNotFetchMessageSource => + 'Could not fetch message source'; @override String get errorCopyingFailed => 'Copying failed'; @@ -152,7 +157,11 @@ class ZulipLocalizationsEn extends ZulipLocalizations { } @override - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage) { + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ) { String _temp0 = intl.Intl.pluralLogic( num, locale: localeName, @@ -191,7 +200,8 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get errorCouldNotConnectTitle => 'Could not connect'; @override - String get errorMessageDoesNotSeemToExist => 'That message does not seem to exist.'; + String get errorMessageDoesNotSeemToExist => + 'That message does not seem to exist.'; @override String get errorQuotationFailed => 'Quotation failed'; @@ -202,7 +212,8 @@ class ZulipLocalizationsEn extends ZulipLocalizations { } @override - String get errorConnectingToServerShort => 'Error connecting to Zulip. Retrying…'; + String get errorConnectingToServerShort => + 'Error connecting to Zulip. Retrying…'; @override String errorConnectingToServerDetails(String serverUrl, String error) { @@ -210,10 +221,15 @@ class ZulipLocalizationsEn extends ZulipLocalizations { } @override - String get errorHandlingEventTitle => 'Error handling a Zulip event. Retrying connection…'; + String get errorHandlingEventTitle => + 'Error handling a Zulip event. Retrying connection…'; @override - String errorHandlingEventDetails(String serverUrl, String error, String event) { + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ) { return 'Error handling a Zulip event from $serverUrl; will retry.\n\nError: $error\n\nEvent: $event'; } @@ -256,10 +272,12 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get successMessageLinkCopied => 'Message link copied'; @override - String get errorBannerDeactivatedDmLabel => 'You cannot send messages to deactivated users.'; + String get errorBannerDeactivatedDmLabel => + 'You cannot send messages to deactivated users.'; @override - String get errorBannerCannotPostInChannelLabel => 'You do not have permission to post in this channel.'; + String get errorBannerCannotPostInChannelLabel => + 'You do not have permission to post in this channel.'; @override String get composeBoxAttachFilesTooltip => 'Attach files'; @@ -328,16 +346,19 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get messageListGroupYouWithYourself => 'Messages with yourself'; @override - String get contentValidationErrorTooLong => 'Message length shouldn\'t be greater than 10000 characters.'; + String get contentValidationErrorTooLong => + 'Message length shouldn\'t be greater than 10000 characters.'; @override String get contentValidationErrorEmpty => 'You have nothing to send!'; @override - String get contentValidationErrorQuoteAndReplyInProgress => 'Please wait for the quotation to complete.'; + String get contentValidationErrorQuoteAndReplyInProgress => + 'Please wait for the quotation to complete.'; @override - String get contentValidationErrorUploadInProgress => 'Please wait for the upload to complete.'; + String get contentValidationErrorUploadInProgress => + 'Please wait for the upload to complete.'; @override String get dialogCancel => 'Cancel'; @@ -411,13 +432,19 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get loginErrorMissingUsername => 'Please enter your username.'; @override - String get topicValidationErrorTooLong => 'Topic length shouldn\'t be greater than 60 characters.'; + String get topicValidationErrorTooLong => + 'Topic length shouldn\'t be greater than 60 characters.'; @override - String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.'; + String get topicValidationErrorMandatoryButEmpty => + 'Topics are required in this organization.'; @override - String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) { + 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.'; } @@ -457,10 +484,12 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get serverUrlValidationErrorInvalidUrl => 'Please enter a valid URL.'; @override - String get serverUrlValidationErrorNoUseEmail => 'Please enter the server URL, not your email.'; + String get serverUrlValidationErrorNoUseEmail => + 'Please enter the server URL, not your email.'; @override - String get serverUrlValidationErrorUnsupportedScheme => 'The server URL must start with http:// or https://.'; + String get serverUrlValidationErrorUnsupportedScheme => + 'The server URL must start with http:// or https://.'; @override String get spoilerDefaultHeaderText => 'Spoiler'; @@ -655,13 +684,15 @@ class ZulipLocalizationsEn extends ZulipLocalizations { String get experimentalFeatureSettingsPageTitle => 'Experimental features'; @override - String get experimentalFeatureSettingsWarning => 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; + String get experimentalFeatureSettingsWarning => + 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; @override String get errorNotificationOpenTitle => 'Failed to open notification'; @override - String get errorNotificationOpenAccountMissing => 'The account associated with this notification no longer exists.'; + String get errorNotificationOpenAccountMissing => + 'The account associated with this notification no longer exists.'; @override String get errorReactionAddingFailedTitle => 'Adding reaction failed'; diff --git a/lib/generated/l10n/zulip_localizations_ja.dart b/lib/generated/l10n/zulip_localizations_ja.dart index 00537f73a2..c11a3fae23 100644 --- a/lib/generated/l10n/zulip_localizations_ja.dart +++ b/lib/generated/l10n/zulip_localizations_ja.dart @@ -44,7 +44,8 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get logOutConfirmationDialogTitle => 'Log out?'; @override - String get logOutConfirmationDialogMessage => 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; + String get logOutConfirmationDialogMessage => + 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; @override String get logOutConfirmationDialogConfirmButton => 'Log out'; @@ -65,10 +66,12 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get permissionsNeededOpenSettings => 'Open settings'; @override - String get permissionsDeniedCameraAccess => 'To upload an image, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedCameraAccess => + 'To upload an image, please grant Zulip additional permissions in Settings.'; @override - String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedReadExternalStorage => + 'To upload files, please grant Zulip additional permissions in Settings.'; @override String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read'; @@ -95,7 +98,8 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved'; @override - String get errorUnresolveTopicFailedTitle => 'Failed to mark topic as unresolved'; + String get errorUnresolveTopicFailedTitle => + 'Failed to mark topic as unresolved'; @override String get actionSheetOptionCopyMessageText => 'Copy message text'; @@ -136,7 +140,8 @@ class ZulipLocalizationsJa extends ZulipLocalizations { } @override - String get errorCouldNotFetchMessageSource => 'Could not fetch message source'; + String get errorCouldNotFetchMessageSource => + 'Could not fetch message source'; @override String get errorCopyingFailed => 'Copying failed'; @@ -152,7 +157,11 @@ class ZulipLocalizationsJa extends ZulipLocalizations { } @override - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage) { + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ) { String _temp0 = intl.Intl.pluralLogic( num, locale: localeName, @@ -191,7 +200,8 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get errorCouldNotConnectTitle => 'Could not connect'; @override - String get errorMessageDoesNotSeemToExist => 'That message does not seem to exist.'; + String get errorMessageDoesNotSeemToExist => + 'That message does not seem to exist.'; @override String get errorQuotationFailed => 'Quotation failed'; @@ -202,7 +212,8 @@ class ZulipLocalizationsJa extends ZulipLocalizations { } @override - String get errorConnectingToServerShort => 'Error connecting to Zulip. Retrying…'; + String get errorConnectingToServerShort => + 'Error connecting to Zulip. Retrying…'; @override String errorConnectingToServerDetails(String serverUrl, String error) { @@ -210,10 +221,15 @@ class ZulipLocalizationsJa extends ZulipLocalizations { } @override - String get errorHandlingEventTitle => 'Error handling a Zulip event. Retrying connection…'; + String get errorHandlingEventTitle => + 'Error handling a Zulip event. Retrying connection…'; @override - String errorHandlingEventDetails(String serverUrl, String error, String event) { + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ) { return 'Error handling a Zulip event from $serverUrl; will retry.\n\nError: $error\n\nEvent: $event'; } @@ -256,10 +272,12 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get successMessageLinkCopied => 'Message link copied'; @override - String get errorBannerDeactivatedDmLabel => 'You cannot send messages to deactivated users.'; + String get errorBannerDeactivatedDmLabel => + 'You cannot send messages to deactivated users.'; @override - String get errorBannerCannotPostInChannelLabel => 'You do not have permission to post in this channel.'; + String get errorBannerCannotPostInChannelLabel => + 'You do not have permission to post in this channel.'; @override String get composeBoxAttachFilesTooltip => 'Attach files'; @@ -328,16 +346,19 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get messageListGroupYouWithYourself => 'Messages with yourself'; @override - String get contentValidationErrorTooLong => 'Message length shouldn\'t be greater than 10000 characters.'; + String get contentValidationErrorTooLong => + 'Message length shouldn\'t be greater than 10000 characters.'; @override String get contentValidationErrorEmpty => 'You have nothing to send!'; @override - String get contentValidationErrorQuoteAndReplyInProgress => 'Please wait for the quotation to complete.'; + String get contentValidationErrorQuoteAndReplyInProgress => + 'Please wait for the quotation to complete.'; @override - String get contentValidationErrorUploadInProgress => 'Please wait for the upload to complete.'; + String get contentValidationErrorUploadInProgress => + 'Please wait for the upload to complete.'; @override String get dialogCancel => 'Cancel'; @@ -411,13 +432,19 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get loginErrorMissingUsername => 'Please enter your username.'; @override - String get topicValidationErrorTooLong => 'Topic length shouldn\'t be greater than 60 characters.'; + String get topicValidationErrorTooLong => + 'Topic length shouldn\'t be greater than 60 characters.'; @override - String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.'; + String get topicValidationErrorMandatoryButEmpty => + 'Topics are required in this organization.'; @override - String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) { + 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.'; } @@ -457,10 +484,12 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get serverUrlValidationErrorInvalidUrl => 'Please enter a valid URL.'; @override - String get serverUrlValidationErrorNoUseEmail => 'Please enter the server URL, not your email.'; + String get serverUrlValidationErrorNoUseEmail => + 'Please enter the server URL, not your email.'; @override - String get serverUrlValidationErrorUnsupportedScheme => 'The server URL must start with http:// or https://.'; + String get serverUrlValidationErrorUnsupportedScheme => + 'The server URL must start with http:// or https://.'; @override String get spoilerDefaultHeaderText => 'Spoiler'; @@ -655,13 +684,15 @@ class ZulipLocalizationsJa extends ZulipLocalizations { String get experimentalFeatureSettingsPageTitle => 'Experimental features'; @override - String get experimentalFeatureSettingsWarning => 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; + String get experimentalFeatureSettingsWarning => + 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; @override String get errorNotificationOpenTitle => 'Failed to open notification'; @override - String get errorNotificationOpenAccountMissing => 'The account associated with this notification no longer exists.'; + String get errorNotificationOpenAccountMissing => + 'The account associated with this notification no longer exists.'; @override String get errorReactionAddingFailedTitle => 'Adding reaction failed'; diff --git a/lib/generated/l10n/zulip_localizations_nb.dart b/lib/generated/l10n/zulip_localizations_nb.dart index 3c063e91da..d23bd323fd 100644 --- a/lib/generated/l10n/zulip_localizations_nb.dart +++ b/lib/generated/l10n/zulip_localizations_nb.dart @@ -44,7 +44,8 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get logOutConfirmationDialogTitle => 'Log out?'; @override - String get logOutConfirmationDialogMessage => 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; + String get logOutConfirmationDialogMessage => + 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; @override String get logOutConfirmationDialogConfirmButton => 'Log out'; @@ -65,10 +66,12 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get permissionsNeededOpenSettings => 'Open settings'; @override - String get permissionsDeniedCameraAccess => 'To upload an image, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedCameraAccess => + 'To upload an image, please grant Zulip additional permissions in Settings.'; @override - String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedReadExternalStorage => + 'To upload files, please grant Zulip additional permissions in Settings.'; @override String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read'; @@ -95,7 +98,8 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved'; @override - String get errorUnresolveTopicFailedTitle => 'Failed to mark topic as unresolved'; + String get errorUnresolveTopicFailedTitle => + 'Failed to mark topic as unresolved'; @override String get actionSheetOptionCopyMessageText => 'Copy message text'; @@ -136,7 +140,8 @@ class ZulipLocalizationsNb extends ZulipLocalizations { } @override - String get errorCouldNotFetchMessageSource => 'Could not fetch message source'; + String get errorCouldNotFetchMessageSource => + 'Could not fetch message source'; @override String get errorCopyingFailed => 'Copying failed'; @@ -152,7 +157,11 @@ class ZulipLocalizationsNb extends ZulipLocalizations { } @override - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage) { + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ) { String _temp0 = intl.Intl.pluralLogic( num, locale: localeName, @@ -191,7 +200,8 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get errorCouldNotConnectTitle => 'Could not connect'; @override - String get errorMessageDoesNotSeemToExist => 'That message does not seem to exist.'; + String get errorMessageDoesNotSeemToExist => + 'That message does not seem to exist.'; @override String get errorQuotationFailed => 'Quotation failed'; @@ -202,7 +212,8 @@ class ZulipLocalizationsNb extends ZulipLocalizations { } @override - String get errorConnectingToServerShort => 'Error connecting to Zulip. Retrying…'; + String get errorConnectingToServerShort => + 'Error connecting to Zulip. Retrying…'; @override String errorConnectingToServerDetails(String serverUrl, String error) { @@ -210,10 +221,15 @@ class ZulipLocalizationsNb extends ZulipLocalizations { } @override - String get errorHandlingEventTitle => 'Error handling a Zulip event. Retrying connection…'; + String get errorHandlingEventTitle => + 'Error handling a Zulip event. Retrying connection…'; @override - String errorHandlingEventDetails(String serverUrl, String error, String event) { + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ) { return 'Error handling a Zulip event from $serverUrl; will retry.\n\nError: $error\n\nEvent: $event'; } @@ -256,10 +272,12 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get successMessageLinkCopied => 'Message link copied'; @override - String get errorBannerDeactivatedDmLabel => 'You cannot send messages to deactivated users.'; + String get errorBannerDeactivatedDmLabel => + 'You cannot send messages to deactivated users.'; @override - String get errorBannerCannotPostInChannelLabel => 'You do not have permission to post in this channel.'; + String get errorBannerCannotPostInChannelLabel => + 'You do not have permission to post in this channel.'; @override String get composeBoxAttachFilesTooltip => 'Attach files'; @@ -328,16 +346,19 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get messageListGroupYouWithYourself => 'Messages with yourself'; @override - String get contentValidationErrorTooLong => 'Message length shouldn\'t be greater than 10000 characters.'; + String get contentValidationErrorTooLong => + 'Message length shouldn\'t be greater than 10000 characters.'; @override String get contentValidationErrorEmpty => 'You have nothing to send!'; @override - String get contentValidationErrorQuoteAndReplyInProgress => 'Please wait for the quotation to complete.'; + String get contentValidationErrorQuoteAndReplyInProgress => + 'Please wait for the quotation to complete.'; @override - String get contentValidationErrorUploadInProgress => 'Please wait for the upload to complete.'; + String get contentValidationErrorUploadInProgress => + 'Please wait for the upload to complete.'; @override String get dialogCancel => 'Cancel'; @@ -411,13 +432,19 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get loginErrorMissingUsername => 'Please enter your username.'; @override - String get topicValidationErrorTooLong => 'Topic length shouldn\'t be greater than 60 characters.'; + String get topicValidationErrorTooLong => + 'Topic length shouldn\'t be greater than 60 characters.'; @override - String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.'; + String get topicValidationErrorMandatoryButEmpty => + 'Topics are required in this organization.'; @override - String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) { + 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.'; } @@ -457,10 +484,12 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get serverUrlValidationErrorInvalidUrl => 'Please enter a valid URL.'; @override - String get serverUrlValidationErrorNoUseEmail => 'Please enter the server URL, not your email.'; + String get serverUrlValidationErrorNoUseEmail => + 'Please enter the server URL, not your email.'; @override - String get serverUrlValidationErrorUnsupportedScheme => 'The server URL must start with http:// or https://.'; + String get serverUrlValidationErrorUnsupportedScheme => + 'The server URL must start with http:// or https://.'; @override String get spoilerDefaultHeaderText => 'Spoiler'; @@ -655,13 +684,15 @@ class ZulipLocalizationsNb extends ZulipLocalizations { String get experimentalFeatureSettingsPageTitle => 'Experimental features'; @override - String get experimentalFeatureSettingsWarning => 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; + String get experimentalFeatureSettingsWarning => + 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; @override String get errorNotificationOpenTitle => 'Failed to open notification'; @override - String get errorNotificationOpenAccountMissing => 'The account associated with this notification no longer exists.'; + String get errorNotificationOpenAccountMissing => + 'The account associated with this notification no longer exists.'; @override String get errorReactionAddingFailedTitle => 'Adding reaction failed'; diff --git a/lib/generated/l10n/zulip_localizations_pl.dart b/lib/generated/l10n/zulip_localizations_pl.dart index d4c3a033d9..e1a6bd45f4 100644 --- a/lib/generated/l10n/zulip_localizations_pl.dart +++ b/lib/generated/l10n/zulip_localizations_pl.dart @@ -44,7 +44,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get logOutConfirmationDialogTitle => 'Wylogować?'; @override - String get logOutConfirmationDialogMessage => 'Aby użyć tego konta należy wypełnić URL organizacji oraz dane konta.'; + String get logOutConfirmationDialogMessage => + 'Aby użyć tego konta należy wypełnić URL organizacji oraz dane konta.'; @override String get logOutConfirmationDialogConfirmButton => 'Wyloguj'; @@ -56,7 +57,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get profileButtonSendDirectMessage => 'Wyślij wiadomość bezpośrednią'; @override - String get errorCouldNotShowUserProfile => 'Nie udało się wyświetlić profilu.'; + String get errorCouldNotShowUserProfile => + 'Nie udało się wyświetlić profilu.'; @override String get permissionsNeededTitle => 'Wymagane uprawnienia'; @@ -65,13 +67,16 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get permissionsNeededOpenSettings => 'Otwórz ustawienia'; @override - String get permissionsDeniedCameraAccess => 'Aby odebrać obraz Zulip musi uzyskać dodatkowe uprawnienia w Ustawieniach.'; + String get permissionsDeniedCameraAccess => + 'Aby odebrać obraz Zulip musi uzyskać dodatkowe uprawnienia w Ustawieniach.'; @override - String get permissionsDeniedReadExternalStorage => 'Aby odebrać pliki Zulip musi uzyskać dodatkowe uprawnienia w Ustawieniach.'; + String get permissionsDeniedReadExternalStorage => + 'Aby odebrać pliki Zulip musi uzyskać dodatkowe uprawnienia w Ustawieniach.'; @override - String get actionSheetOptionMarkChannelAsRead => 'Oznacz kanał jako przeczytany'; + String get actionSheetOptionMarkChannelAsRead => + 'Oznacz kanał jako przeczytany'; @override String get actionSheetOptionMuteTopic => 'Wycisz wątek'; @@ -92,19 +97,23 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get actionSheetOptionUnresolveTopic => 'Oznacz brak rozwiązania'; @override - String get errorResolveTopicFailedTitle => 'Nie udało się oznaczyć jako rozwiązany'; + String get errorResolveTopicFailedTitle => + 'Nie udało się oznaczyć jako rozwiązany'; @override - String get errorUnresolveTopicFailedTitle => 'Nie udało się oznaczyć brak rozwiązania'; + String get errorUnresolveTopicFailedTitle => + 'Nie udało się oznaczyć brak rozwiązania'; @override String get actionSheetOptionCopyMessageText => 'Skopiuj tekst wiadomości'; @override - String get actionSheetOptionCopyMessageLink => 'Skopiuj odnośnik do wiadomości'; + String get actionSheetOptionCopyMessageLink => + 'Skopiuj odnośnik do wiadomości'; @override - String get actionSheetOptionMarkAsUnread => 'Odtąd oznacz jako nieprzeczytane'; + String get actionSheetOptionMarkAsUnread => + 'Odtąd oznacz jako nieprzeczytane'; @override String get actionSheetOptionShare => 'Udostępnij'; @@ -119,7 +128,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get actionSheetOptionUnstarMessage => 'Odbierz gwiazdkę'; @override - String get actionSheetOptionMarkTopicAsRead => 'Oznacz wątek jako przeczytany'; + String get actionSheetOptionMarkTopicAsRead => + 'Oznacz wątek jako przeczytany'; @override String get errorWebAuthOperationalErrorTitle => 'Coś poszło nie tak'; @@ -136,7 +146,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { } @override - String get errorCouldNotFetchMessageSource => 'Nie można uzyskać źródłowej wiadomości'; + String get errorCouldNotFetchMessageSource => + 'Nie można uzyskać źródłowej wiadomości'; @override String get errorCopyingFailed => 'Nie udało się skopiować'; @@ -152,7 +163,11 @@ class ZulipLocalizationsPl extends ZulipLocalizations { } @override - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage) { + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ) { String _temp0 = intl.Intl.pluralLogic( num, locale: localeName, @@ -191,7 +206,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get errorCouldNotConnectTitle => 'Brak połączenia'; @override - String get errorMessageDoesNotSeemToExist => 'Taka wiadomość raczej nie istnieje.'; + String get errorMessageDoesNotSeemToExist => + 'Taka wiadomość raczej nie istnieje.'; @override String get errorQuotationFailed => 'Cytowanie bez powodzenia'; @@ -202,7 +218,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { } @override - String get errorConnectingToServerShort => 'Błąd połączenia z Zulip. Ponawiam…'; + String get errorConnectingToServerShort => + 'Błąd połączenia z Zulip. Ponawiam…'; @override String errorConnectingToServerDetails(String serverUrl, String error) { @@ -210,10 +227,15 @@ class ZulipLocalizationsPl extends ZulipLocalizations { } @override - String get errorHandlingEventTitle => 'Błąd obsługi zdarzenia Zulip. Ponnawiam połączenie…'; + String get errorHandlingEventTitle => + 'Błąd obsługi zdarzenia Zulip. Ponnawiam połączenie…'; @override - String errorHandlingEventDetails(String serverUrl, String error, String event) { + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ) { return 'Błąd zdarzenia Zulip z $serverUrl; ponawiam.\n\nBłąd: $error\n\nZdarzenie: $event'; } @@ -244,7 +266,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get errorStarMessageFailedTitle => 'Dodanie gwiazdki bez powodzenia'; @override - String get errorUnstarMessageFailedTitle => 'Odebranie gwiazdki bez powodzenia'; + String get errorUnstarMessageFailedTitle => + 'Odebranie gwiazdki bez powodzenia'; @override String get successLinkCopied => 'Skopiowano odnośnik'; @@ -256,10 +279,12 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get successMessageLinkCopied => 'Skopiowano odnośnik wiadomości'; @override - String get errorBannerDeactivatedDmLabel => 'Nie można wysyłać wiadomości do dezaktywowanych użytkowników.'; + String get errorBannerDeactivatedDmLabel => + 'Nie można wysyłać wiadomości do dezaktywowanych użytkowników.'; @override - String get errorBannerCannotPostInChannelLabel => 'Nie masz uprawnień do dodawania wpisów w tym kanale.'; + String get errorBannerCannotPostInChannelLabel => + 'Nie masz uprawnień do dodawania wpisów w tym kanale.'; @override String get composeBoxAttachFilesTooltip => 'Dołącz pliki'; @@ -328,16 +353,19 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get messageListGroupYouWithYourself => 'Zapiski na własne konto'; @override - String get contentValidationErrorTooLong => 'Wiadomość nie może być dłuższa niż 10000 znaków.'; + String get contentValidationErrorTooLong => + 'Wiadomość nie może być dłuższa niż 10000 znaków.'; @override String get contentValidationErrorEmpty => 'Nie masz nic do wysłania!'; @override - String get contentValidationErrorQuoteAndReplyInProgress => 'Zaczekaj na zakończenie pobierania cytatu.'; + String get contentValidationErrorQuoteAndReplyInProgress => + 'Zaczekaj na zakończenie pobierania cytatu.'; @override - String get contentValidationErrorUploadInProgress => 'Zaczekaj na zakończenie przekazywania.'; + String get contentValidationErrorUploadInProgress => + 'Zaczekaj na zakończenie przekazywania.'; @override String get dialogCancel => 'Anuluj'; @@ -411,13 +439,19 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get loginErrorMissingUsername => 'Proszę podaj nazwę użytkownika.'; @override - String get topicValidationErrorTooLong => 'Tytuł nie może być dłuższy niż 60 znaków.'; + String get topicValidationErrorTooLong => + 'Tytuł nie może być dłuższy niż 60 znaków.'; @override - String get topicValidationErrorMandatoryButEmpty => 'Wątki są wymagane przez tę organizację.'; + String get topicValidationErrorMandatoryButEmpty => + 'Wątki są wymagane przez tę organizację.'; @override - String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) { + String errorServerVersionUnsupportedMessage( + String url, + String zulipVersion, + String minSupportedZulipVersion, + ) { return '$url uruchamia Zulip Server $zulipVersion, który nie jest obsługiwany. Minimalna obsługiwana wersja to Zulip Server $minSupportedZulipVersion.'; } @@ -457,10 +491,12 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get serverUrlValidationErrorInvalidUrl => 'Proszę podaj poprawny URL.'; @override - String get serverUrlValidationErrorNoUseEmail => 'Proszę podaj adres URL serwera a nie swój email.'; + String get serverUrlValidationErrorNoUseEmail => + 'Proszę podaj adres URL serwera a nie swój email.'; @override - String get serverUrlValidationErrorUnsupportedScheme => 'Adres URL serwera musi zaczynać się od http:// or https://.'; + String get serverUrlValidationErrorUnsupportedScheme => + 'Adres URL serwera musi zaczynać się od http:// or https://.'; @override String get spoilerDefaultHeaderText => 'Spoiler'; @@ -483,7 +519,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get markAsReadInProgress => 'Oznaczanie wiadomości jako przeczytane…'; @override - String get errorMarkAsReadFailedTitle => 'Oznaczanie jako przeczytane bez powodzenia'; + String get errorMarkAsReadFailedTitle => + 'Oznaczanie jako przeczytane bez powodzenia'; @override String markAsUnreadComplete(int num) { @@ -500,7 +537,8 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get markAsUnreadInProgress => 'Oznaczanie jako nieprzeczytane…'; @override - String get errorMarkAsUnreadFailedTitle => 'Oznaczanie jako nieprzeczytane bez powodzenia'; + String get errorMarkAsUnreadFailedTitle => + 'Oznaczanie jako nieprzeczytane bez powodzenia'; @override String get today => 'Dzisiaj'; @@ -655,19 +693,23 @@ class ZulipLocalizationsPl extends ZulipLocalizations { String get experimentalFeatureSettingsPageTitle => 'Funkcje eksperymentalne'; @override - String get experimentalFeatureSettingsWarning => 'W ten sposób aktywujesz funkcje, które są w fazie testów. Mogą one nie działać lub powodować problemy z tym co bez nich działa poprawnie.\n\nTo ustawienie przewidziane jest dla tych, którzy pracują nad ulepszeniem aplikacji Zulip.'; + String get experimentalFeatureSettingsWarning => + 'W ten sposób aktywujesz funkcje, które są w fazie testów. Mogą one nie działać lub powodować problemy z tym co bez nich działa poprawnie.\n\nTo ustawienie przewidziane jest dla tych, którzy pracują nad ulepszeniem aplikacji Zulip.'; @override - String get errorNotificationOpenTitle => 'Otwieranie powiadomienia bez powodzenia'; + String get errorNotificationOpenTitle => + 'Otwieranie powiadomienia bez powodzenia'; @override - String get errorNotificationOpenAccountMissing => 'Konto związane z tym powiadomieniem już nie istnieje.'; + String get errorNotificationOpenAccountMissing => + 'Konto związane z tym powiadomieniem już nie istnieje.'; @override String get errorReactionAddingFailedTitle => 'Dodanie reakcji bez powodzenia'; @override - String get errorReactionRemovingFailedTitle => 'Usuwanie reakcji bez powodzenia'; + String get errorReactionRemovingFailedTitle => + 'Usuwanie reakcji bez powodzenia'; @override String get emojiReactionsMore => 'więcej'; diff --git a/lib/generated/l10n/zulip_localizations_ru.dart b/lib/generated/l10n/zulip_localizations_ru.dart index cb09ca516e..78b68e812a 100644 --- a/lib/generated/l10n/zulip_localizations_ru.dart +++ b/lib/generated/l10n/zulip_localizations_ru.dart @@ -44,7 +44,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get logOutConfirmationDialogTitle => 'Выйти из системы?'; @override - String get logOutConfirmationDialogMessage => 'Чтобы использовать эту учетную запись в будущем, вам придется заново ввести URL-адрес вашей организации и информацию о вашей учетной записи.'; + String get logOutConfirmationDialogMessage => + 'Чтобы использовать эту учетную запись в будущем, вам придется заново ввести URL-адрес вашей организации и информацию о вашей учетной записи.'; @override String get logOutConfirmationDialogConfirmButton => 'Выйти'; @@ -56,7 +57,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get profileButtonSendDirectMessage => 'Отправить личное сообщение'; @override - String get errorCouldNotShowUserProfile => 'Не удалось показать профиль пользователя.'; + String get errorCouldNotShowUserProfile => + 'Не удалось показать профиль пользователя.'; @override String get permissionsNeededTitle => 'Требуются разрешения'; @@ -65,13 +67,16 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get permissionsNeededOpenSettings => 'Открыть настройки'; @override - String get permissionsDeniedCameraAccess => 'Для загрузки изображения, пожалуйста, предоставьте Zulip дополнительные разрешения в настройках.'; + String get permissionsDeniedCameraAccess => + 'Для загрузки изображения, пожалуйста, предоставьте Zulip дополнительные разрешения в настройках.'; @override - String get permissionsDeniedReadExternalStorage => 'Для загрузки файлов, пожалуйста, предоставьте Zulip дополнительные разрешения в настройках.'; + String get permissionsDeniedReadExternalStorage => + 'Для загрузки файлов, пожалуйста, предоставьте Zulip дополнительные разрешения в настройках.'; @override - String get actionSheetOptionMarkChannelAsRead => 'Отметить канал как прочитанный'; + String get actionSheetOptionMarkChannelAsRead => + 'Отметить канал как прочитанный'; @override String get actionSheetOptionMuteTopic => 'Отключить тему'; @@ -92,19 +97,23 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get actionSheetOptionUnresolveTopic => 'Снять отметку \"решено\"'; @override - String get errorResolveTopicFailedTitle => 'Не удалось отметить тему как решенную'; + String get errorResolveTopicFailedTitle => + 'Не удалось отметить тему как решенную'; @override - String get errorUnresolveTopicFailedTitle => 'Не удалось отметить тему как нерешенную'; + String get errorUnresolveTopicFailedTitle => + 'Не удалось отметить тему как нерешенную'; @override String get actionSheetOptionCopyMessageText => 'Скопировать текст сообщения'; @override - String get actionSheetOptionCopyMessageLink => 'Скопировать ссылку на сообщение'; + String get actionSheetOptionCopyMessageLink => + 'Скопировать ссылку на сообщение'; @override - String get actionSheetOptionMarkAsUnread => 'Отметить как непрочитанные начиная отсюда'; + String get actionSheetOptionMarkAsUnread => + 'Отметить как непрочитанные начиная отсюда'; @override String get actionSheetOptionShare => 'Поделиться'; @@ -119,7 +128,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get actionSheetOptionUnstarMessage => 'Снять отметку с сообщения'; @override - String get actionSheetOptionMarkTopicAsRead => 'Отметить тему как прочитанную'; + String get actionSheetOptionMarkTopicAsRead => + 'Отметить тему как прочитанную'; @override String get errorWebAuthOperationalErrorTitle => 'Что-то пошло не так'; @@ -136,7 +146,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { } @override - String get errorCouldNotFetchMessageSource => 'Не удалось извлечь источник сообщения'; + String get errorCouldNotFetchMessageSource => + 'Не удалось извлечь источник сообщения'; @override String get errorCopyingFailed => 'Сбой копирования'; @@ -152,7 +163,11 @@ class ZulipLocalizationsRu extends ZulipLocalizations { } @override - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage) { + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ) { String _temp0 = intl.Intl.pluralLogic( num, locale: localeName, @@ -191,7 +206,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get errorCouldNotConnectTitle => 'Нет связи с сервером'; @override - String get errorMessageDoesNotSeemToExist => 'Это сообщение, похоже, отсутствует.'; + String get errorMessageDoesNotSeemToExist => + 'Это сообщение, похоже, отсутствует.'; @override String get errorQuotationFailed => 'Цитирование не удалось'; @@ -202,7 +218,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { } @override - String get errorConnectingToServerShort => 'Ошибка подключения к Zulip. Повторяем попытку…'; + String get errorConnectingToServerShort => + 'Ошибка подключения к Zulip. Повторяем попытку…'; @override String errorConnectingToServerDetails(String serverUrl, String error) { @@ -210,10 +227,15 @@ class ZulipLocalizationsRu extends ZulipLocalizations { } @override - String get errorHandlingEventTitle => 'Ошибка обработки события Zulip. Повторная попытка соединения…'; + String get errorHandlingEventTitle => + 'Ошибка обработки события Zulip. Повторная попытка соединения…'; @override - String errorHandlingEventDetails(String serverUrl, String error, String event) { + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ) { return 'Ошибка обработки события Zulip от $serverUrl; повторим попытку.\n\nОшибка: $error\n\nСобытие: $event'; } @@ -235,7 +257,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get errorFollowTopicFailed => 'Не удалось начать отслеживать тему'; @override - String get errorUnfollowTopicFailed => 'Не удалось прекратить отслеживать тему'; + String get errorUnfollowTopicFailed => + 'Не удалось прекратить отслеживать тему'; @override String get errorSharingFailed => 'Не удалось поделиться'; @@ -244,7 +267,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get errorStarMessageFailedTitle => 'Не удалось отметить сообщение'; @override - String get errorUnstarMessageFailedTitle => 'Не удалось снять отметку с сообщения'; + String get errorUnstarMessageFailedTitle => + 'Не удалось снять отметку с сообщения'; @override String get successLinkCopied => 'Ссылка скопирована'; @@ -256,10 +280,12 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get successMessageLinkCopied => 'Ссылка на сообщение скопирована'; @override - String get errorBannerDeactivatedDmLabel => 'Нельзя отправить сообщение отключенным пользователям.'; + String get errorBannerDeactivatedDmLabel => + 'Нельзя отправить сообщение отключенным пользователям.'; @override - String get errorBannerCannotPostInChannelLabel => 'У вас нет права писать в этом канале.'; + String get errorBannerCannotPostInChannelLabel => + 'У вас нет права писать в этом канале.'; @override String get composeBoxAttachFilesTooltip => 'Прикрепить файлы'; @@ -328,16 +354,19 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get messageListGroupYouWithYourself => 'Сообщения с собой'; @override - String get contentValidationErrorTooLong => 'Длина сообщения не должна превышать 10000 символов.'; + String get contentValidationErrorTooLong => + 'Длина сообщения не должна превышать 10000 символов.'; @override String get contentValidationErrorEmpty => 'Нечего отправлять!'; @override - String get contentValidationErrorQuoteAndReplyInProgress => 'Пожалуйста, дождитесь завершения цитирования.'; + String get contentValidationErrorQuoteAndReplyInProgress => + 'Пожалуйста, дождитесь завершения цитирования.'; @override - String get contentValidationErrorUploadInProgress => 'Пожалуйста, дождитесь завершения загрузки.'; + String get contentValidationErrorUploadInProgress => + 'Пожалуйста, дождитесь завершения загрузки.'; @override String get dialogCancel => 'Отмена'; @@ -396,7 +425,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get loginEmailLabel => 'Адрес почты'; @override - String get loginErrorMissingEmail => 'Пожалуйста, введите ваш адрес электронной почты.'; + String get loginErrorMissingEmail => + 'Пожалуйста, введите ваш адрес электронной почты.'; @override String get loginPasswordLabel => 'Пароль'; @@ -408,16 +438,23 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get loginUsernameLabel => 'Имя пользователя'; @override - String get loginErrorMissingUsername => 'Пожалуйста, введите ваше имя пользователя.'; + String get loginErrorMissingUsername => + 'Пожалуйста, введите ваше имя пользователя.'; @override - String get topicValidationErrorTooLong => 'Длина темы не должна превышать 60 символов.'; + String get topicValidationErrorTooLong => + 'Длина темы не должна превышать 60 символов.'; @override - String get topicValidationErrorMandatoryButEmpty => 'Темы обязательны в этой организации.'; + String get topicValidationErrorMandatoryButEmpty => + 'Темы обязательны в этой организации.'; @override - String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) { + String errorServerVersionUnsupportedMessage( + String url, + String zulipVersion, + String minSupportedZulipVersion, + ) { return '$url использует Zulip Server $zulipVersion, который не поддерживается. Минимальная поддерживаемая версия — Zulip Server $minSupportedZulipVersion.'; } @@ -454,13 +491,16 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get serverUrlValidationErrorEmpty => 'Пожалуйста, введите URL-адрес.'; @override - String get serverUrlValidationErrorInvalidUrl => 'Пожалуйста, введите корректный URL-адрес.'; + String get serverUrlValidationErrorInvalidUrl => + 'Пожалуйста, введите корректный URL-адрес.'; @override - String get serverUrlValidationErrorNoUseEmail => 'Пожалуйста, введите URL-адрес сервера, а не свой email.'; + String get serverUrlValidationErrorNoUseEmail => + 'Пожалуйста, введите URL-адрес сервера, а не свой email.'; @override - String get serverUrlValidationErrorUnsupportedScheme => 'URL-адрес сервера должен начинаться с http:// или https://.'; + String get serverUrlValidationErrorUnsupportedScheme => + 'URL-адрес сервера должен начинаться с http:// или https://.'; @override String get spoilerDefaultHeaderText => 'Спойлер'; @@ -483,7 +523,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get markAsReadInProgress => 'Помечаем сообщения как прочитанные…'; @override - String get errorMarkAsReadFailedTitle => 'Не удалось установить отметку прочтения'; + String get errorMarkAsReadFailedTitle => + 'Не удалось установить отметку прочтения'; @override String markAsUnreadComplete(int num) { @@ -500,7 +541,8 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get markAsUnreadInProgress => 'Помечаем сообщения как непрочитанные…'; @override - String get errorMarkAsUnreadFailedTitle => 'Не удалось снять отметку прочтения'; + String get errorMarkAsUnreadFailedTitle => + 'Не удалось снять отметку прочтения'; @override String get today => 'Сегодня'; @@ -652,16 +694,19 @@ class ZulipLocalizationsRu extends ZulipLocalizations { String get pollWidgetOptionsMissing => 'В опросе пока нет вариантов ответа.'; @override - String get experimentalFeatureSettingsPageTitle => 'Экспериментальные функции'; + String get experimentalFeatureSettingsPageTitle => + 'Экспериментальные функции'; @override - String get experimentalFeatureSettingsWarning => 'Эти параметры включают функции, которые все еще находятся в стадии разработки и не готовы. Они могут не работать и вызывать проблемы в других местах приложения.\n\nЦель этих настроек — экспериментирование людьми, работающими над разработкой Zulip.'; + String get experimentalFeatureSettingsWarning => + 'Эти параметры включают функции, которые все еще находятся в стадии разработки и не готовы. Они могут не работать и вызывать проблемы в других местах приложения.\n\nЦель этих настроек — экспериментирование людьми, работающими над разработкой Zulip.'; @override String get errorNotificationOpenTitle => 'Не удалось открыть оповещения'; @override - String get errorNotificationOpenAccountMissing => 'Учетной записи, связанной с этим оповещением, больше нет.'; + String get errorNotificationOpenAccountMissing => + 'Учетной записи, связанной с этим оповещением, больше нет.'; @override String get errorReactionAddingFailedTitle => 'Не удалось добавить реакцию'; diff --git a/lib/generated/l10n/zulip_localizations_sk.dart b/lib/generated/l10n/zulip_localizations_sk.dart index 0cb42c3a37..193ac26d8e 100644 --- a/lib/generated/l10n/zulip_localizations_sk.dart +++ b/lib/generated/l10n/zulip_localizations_sk.dart @@ -44,7 +44,8 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get logOutConfirmationDialogTitle => 'Chcete sa odhlásiť?'; @override - String get logOutConfirmationDialogMessage => 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; + String get logOutConfirmationDialogMessage => + 'To use this account in the future, you will have to re-enter the URL for your organization and your account information.'; @override String get logOutConfirmationDialogConfirmButton => 'Odhlásiť sa'; @@ -65,10 +66,12 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get permissionsNeededOpenSettings => 'Otvoriť nastavenia'; @override - String get permissionsDeniedCameraAccess => 'To upload an image, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedCameraAccess => + 'To upload an image, please grant Zulip additional permissions in Settings.'; @override - String get permissionsDeniedReadExternalStorage => 'To upload files, please grant Zulip additional permissions in Settings.'; + String get permissionsDeniedReadExternalStorage => + 'To upload files, please grant Zulip additional permissions in Settings.'; @override String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read'; @@ -95,7 +98,8 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved'; @override - String get errorUnresolveTopicFailedTitle => 'Failed to mark topic as unresolved'; + String get errorUnresolveTopicFailedTitle => + 'Failed to mark topic as unresolved'; @override String get actionSheetOptionCopyMessageText => 'Skopírovať text správy'; @@ -104,7 +108,8 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get actionSheetOptionCopyMessageLink => 'Skopírovať odkaz do správy'; @override - String get actionSheetOptionMarkAsUnread => 'Označiť ako neprečítané od tejto správy'; + String get actionSheetOptionMarkAsUnread => + 'Označiť ako neprečítané od tejto správy'; @override String get actionSheetOptionShare => 'Zdielať'; @@ -136,7 +141,8 @@ class ZulipLocalizationsSk extends ZulipLocalizations { } @override - String get errorCouldNotFetchMessageSource => 'Nepodarilo sa nahrať zdroj správy'; + String get errorCouldNotFetchMessageSource => + 'Nepodarilo sa nahrať zdroj správy'; @override String get errorCopyingFailed => 'Kopírovanie zlyhalo'; @@ -152,7 +158,11 @@ class ZulipLocalizationsSk extends ZulipLocalizations { } @override - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage) { + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ) { String _temp0 = intl.Intl.pluralLogic( num, locale: localeName, @@ -202,7 +212,8 @@ class ZulipLocalizationsSk extends ZulipLocalizations { } @override - String get errorConnectingToServerShort => 'Chyba pri pripájaní na Zulip. Skúšam znovu…'; + String get errorConnectingToServerShort => + 'Chyba pri pripájaní na Zulip. Skúšam znovu…'; @override String errorConnectingToServerDetails(String serverUrl, String error) { @@ -210,10 +221,15 @@ class ZulipLocalizationsSk extends ZulipLocalizations { } @override - String get errorHandlingEventTitle => 'Chyba pri obsluhe Zulip udalosti. Pokúšam sa znovu…'; + String get errorHandlingEventTitle => + 'Chyba pri obsluhe Zulip udalosti. Pokúšam sa znovu…'; @override - String errorHandlingEventDetails(String serverUrl, String error, String event) { + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ) { return 'Chyba obsluhy Zulip udalosti na serveri $serverUrl; skúsim znovu.\n\nChyba: $error\n\nUdalosť: $event'; } @@ -256,10 +272,12 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get successMessageLinkCopied => 'Message link copied'; @override - String get errorBannerDeactivatedDmLabel => 'You cannot send messages to deactivated users.'; + String get errorBannerDeactivatedDmLabel => + 'You cannot send messages to deactivated users.'; @override - String get errorBannerCannotPostInChannelLabel => 'You do not have permission to post in this channel.'; + String get errorBannerCannotPostInChannelLabel => + 'You do not have permission to post in this channel.'; @override String get composeBoxAttachFilesTooltip => 'Attach files'; @@ -328,16 +346,19 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get messageListGroupYouWithYourself => 'Messages with yourself'; @override - String get contentValidationErrorTooLong => 'Message length shouldn\'t be greater than 10000 characters.'; + String get contentValidationErrorTooLong => + 'Message length shouldn\'t be greater than 10000 characters.'; @override String get contentValidationErrorEmpty => 'You have nothing to send!'; @override - String get contentValidationErrorQuoteAndReplyInProgress => 'Please wait for the quotation to complete.'; + String get contentValidationErrorQuoteAndReplyInProgress => + 'Please wait for the quotation to complete.'; @override - String get contentValidationErrorUploadInProgress => 'Please wait for the upload to complete.'; + String get contentValidationErrorUploadInProgress => + 'Please wait for the upload to complete.'; @override String get dialogCancel => 'Cancel'; @@ -411,13 +432,19 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get loginErrorMissingUsername => 'Prosím zadajte prihlasovacie meno.'; @override - String get topicValidationErrorTooLong => 'Topic length shouldn\'t be greater than 60 characters.'; + String get topicValidationErrorTooLong => + 'Topic length shouldn\'t be greater than 60 characters.'; @override - String get topicValidationErrorMandatoryButEmpty => 'Topics are required in this organization.'; + String get topicValidationErrorMandatoryButEmpty => + 'Topics are required in this organization.'; @override - String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) { + 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.'; } @@ -457,10 +484,12 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get serverUrlValidationErrorInvalidUrl => 'Vložte správnu adresu.'; @override - String get serverUrlValidationErrorNoUseEmail => 'Vložte adresu servera, nie email.'; + String get serverUrlValidationErrorNoUseEmail => + 'Vložte adresu servera, nie email.'; @override - String get serverUrlValidationErrorUnsupportedScheme => 'Adresa servera musí začínať s http:// or https://.'; + String get serverUrlValidationErrorUnsupportedScheme => + 'Adresa servera musí začínať s http:// or https://.'; @override String get spoilerDefaultHeaderText => 'Vyzradenie'; @@ -483,7 +512,8 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get markAsReadInProgress => 'Označiť správy ako prečítané…'; @override - String get errorMarkAsReadFailedTitle => 'Neodarilo sa označiť správy ako prečítané'; + String get errorMarkAsReadFailedTitle => + 'Neodarilo sa označiť správy ako prečítané'; @override String markAsUnreadComplete(int num) { @@ -500,7 +530,8 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get markAsUnreadInProgress => 'Označiť správy ako neprečítané…'; @override - String get errorMarkAsUnreadFailedTitle => 'Zlyhalo označenie správ za prečítané'; + String get errorMarkAsUnreadFailedTitle => + 'Zlyhalo označenie správ za prečítané'; @override String get today => 'Dnes'; @@ -655,13 +686,15 @@ class ZulipLocalizationsSk extends ZulipLocalizations { String get experimentalFeatureSettingsPageTitle => 'Experimental features'; @override - String get experimentalFeatureSettingsWarning => 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; + String get experimentalFeatureSettingsWarning => + 'These options enable features which are still under development and not ready. They may not work, and may cause issues in other areas of the app.\n\nThe purpose of these settings is for experimentation by people working on developing Zulip.'; @override String get errorNotificationOpenTitle => 'Nepodarilo sa otvoriť oznámenie'; @override - String get errorNotificationOpenAccountMissing => 'The account associated with this notification no longer exists.'; + String get errorNotificationOpenAccountMissing => + 'The account associated with this notification no longer exists.'; @override String get errorReactionAddingFailedTitle => 'Nepodarilo sa pridať reakciu'; diff --git a/lib/generated/l10n/zulip_localizations_uk.dart b/lib/generated/l10n/zulip_localizations_uk.dart index b7e6d792f2..c1898631fd 100644 --- a/lib/generated/l10n/zulip_localizations_uk.dart +++ b/lib/generated/l10n/zulip_localizations_uk.dart @@ -44,7 +44,8 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get logOutConfirmationDialogTitle => 'Вийти?'; @override - String get logOutConfirmationDialogMessage => 'Щоб використовувати цей обліковий запис у майбутньому, вам доведеться повторно ввести його дані та URL-адресу вашої організації.'; + String get logOutConfirmationDialogMessage => + 'Щоб використовувати цей обліковий запис у майбутньому, вам доведеться повторно ввести його дані та URL-адресу вашої організації.'; @override String get logOutConfirmationDialogConfirmButton => 'Вийти'; @@ -53,10 +54,12 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get chooseAccountButtonAddAnAccount => 'Додати обліковий запис'; @override - String get profileButtonSendDirectMessage => 'Надіслати особисте повідомлення'; + String get profileButtonSendDirectMessage => + 'Надіслати особисте повідомлення'; @override - String get errorCouldNotShowUserProfile => 'Не вдалося показати профіль користувача.'; + String get errorCouldNotShowUserProfile => + 'Не вдалося показати профіль користувача.'; @override String get permissionsNeededTitle => 'Потрібні дозволи'; @@ -65,13 +68,16 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get permissionsNeededOpenSettings => 'Відкрити налаштування'; @override - String get permissionsDeniedCameraAccess => 'Щоб завантажити зображення, надайте Zulip додаткові дозволи в налаштуваннях.'; + String get permissionsDeniedCameraAccess => + 'Щоб завантажити зображення, надайте Zulip додаткові дозволи в налаштуваннях.'; @override - String get permissionsDeniedReadExternalStorage => 'Щоб завантажувати файли, надайте Zulip додаткові дозволи в налаштуваннях.'; + String get permissionsDeniedReadExternalStorage => + 'Щоб завантажувати файли, надайте Zulip додаткові дозволи в налаштуваннях.'; @override - String get actionSheetOptionMarkChannelAsRead => 'Позначити канал як прочитаний'; + String get actionSheetOptionMarkChannelAsRead => + 'Позначити канал як прочитаний'; @override String get actionSheetOptionMuteTopic => 'Заглушити тему'; @@ -92,16 +98,19 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get actionSheetOptionUnresolveTopic => 'Позначити як невирішене'; @override - String get errorResolveTopicFailedTitle => 'Не вдалося позначити тему як вирішену'; + String get errorResolveTopicFailedTitle => + 'Не вдалося позначити тему як вирішену'; @override - String get errorUnresolveTopicFailedTitle => 'Не вдалося позначити тему як невирішену'; + String get errorUnresolveTopicFailedTitle => + 'Не вдалося позначити тему як невирішену'; @override String get actionSheetOptionCopyMessageText => 'Копіювати текст повідомлення'; @override - String get actionSheetOptionCopyMessageLink => 'Копіювати посилання на повідомлення'; + String get actionSheetOptionCopyMessageLink => + 'Копіювати посилання на повідомлення'; @override String get actionSheetOptionMarkAsUnread => 'Позначити як непрочитане звідси'; @@ -116,7 +125,8 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get actionSheetOptionStarMessage => 'Позначити повідомлення зірочкою'; @override - String get actionSheetOptionUnstarMessage => 'Зняти позначку зірочки з повідомлення'; + String get actionSheetOptionUnstarMessage => + 'Зняти позначку зірочки з повідомлення'; @override String get actionSheetOptionMarkTopicAsRead => 'Позначити тему як прочитану'; @@ -136,7 +146,8 @@ class ZulipLocalizationsUk extends ZulipLocalizations { } @override - String get errorCouldNotFetchMessageSource => 'Не вдалося отримати джерело повідомлення'; + String get errorCouldNotFetchMessageSource => + 'Не вдалося отримати джерело повідомлення'; @override String get errorCopyingFailed => 'Помилка копіювання'; @@ -152,7 +163,11 @@ class ZulipLocalizationsUk extends ZulipLocalizations { } @override - String errorFilesTooLarge(int num, int maxFileUploadSizeMib, String listMessage) { + String errorFilesTooLarge( + int num, + int maxFileUploadSizeMib, + String listMessage, + ) { String _temp0 = intl.Intl.pluralLogic( num, locale: localeName, @@ -191,7 +206,8 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get errorCouldNotConnectTitle => 'Не вдалося підключитися'; @override - String get errorMessageDoesNotSeemToExist => 'Здається, цього повідомлення не існує.'; + String get errorMessageDoesNotSeemToExist => + 'Здається, цього повідомлення не існує.'; @override String get errorQuotationFailed => 'Помилка цитування'; @@ -202,7 +218,8 @@ class ZulipLocalizationsUk extends ZulipLocalizations { } @override - String get errorConnectingToServerShort => 'Помилка підключення до Zulip. Повторна спроба…'; + String get errorConnectingToServerShort => + 'Помилка підключення до Zulip. Повторна спроба…'; @override String errorConnectingToServerDetails(String serverUrl, String error) { @@ -210,10 +227,15 @@ class ZulipLocalizationsUk extends ZulipLocalizations { } @override - String get errorHandlingEventTitle => 'Помилка обробки події Zulip. Повторна спроба підключення…'; + String get errorHandlingEventTitle => + 'Помилка обробки події Zulip. Повторна спроба підключення…'; @override - String errorHandlingEventDetails(String serverUrl, String error, String event) { + String errorHandlingEventDetails( + String serverUrl, + String error, + String event, + ) { return 'Помилка обробки події Zulip із $serverUrl; буде повторювати спробу.\n\nПомилка: $error\n\nПодія: $event'; } @@ -241,10 +263,12 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get errorSharingFailed => 'Поширення не вдалося'; @override - String get errorStarMessageFailedTitle => 'Не вдалося позначити повідомлення зірочкою'; + String get errorStarMessageFailedTitle => + 'Не вдалося позначити повідомлення зірочкою'; @override - String get errorUnstarMessageFailedTitle => 'Не вдалося зняти позначку зірочки з повідомлення'; + String get errorUnstarMessageFailedTitle => + 'Не вдалося зняти позначку зірочки з повідомлення'; @override String get successLinkCopied => 'Посилання скопійовано'; @@ -253,13 +277,16 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get successMessageTextCopied => 'Текст повідомлення скопійовано'; @override - String get successMessageLinkCopied => 'Посилання на повідомлення скопійовано'; + String get successMessageLinkCopied => + 'Посилання на повідомлення скопійовано'; @override - String get errorBannerDeactivatedDmLabel => 'Ви не можете надсилати повідомлення деактивованим користувачам.'; + String get errorBannerDeactivatedDmLabel => + 'Ви не можете надсилати повідомлення деактивованим користувачам.'; @override - String get errorBannerCannotPostInChannelLabel => 'Ви не маєте дозволу на публікацію в цьому каналі.'; + String get errorBannerCannotPostInChannelLabel => + 'Ви не маєте дозволу на публікацію в цьому каналі.'; @override String get composeBoxAttachFilesTooltip => 'Прикріпити файли'; @@ -328,16 +355,19 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get messageListGroupYouWithYourself => 'Повідомлення з собою'; @override - String get contentValidationErrorTooLong => 'Довжина повідомлення не повинна перевищувати 10000 символів.'; + String get contentValidationErrorTooLong => + 'Довжина повідомлення не повинна перевищувати 10000 символів.'; @override String get contentValidationErrorEmpty => 'Вам нема чого надсилати!'; @override - String get contentValidationErrorQuoteAndReplyInProgress => 'Будь ласка, дочекайтеся завершення цитування.'; + String get contentValidationErrorQuoteAndReplyInProgress => + 'Будь ласка, дочекайтеся завершення цитування.'; @override - String get contentValidationErrorUploadInProgress => 'Дочекайтеся завершення завантаження.'; + String get contentValidationErrorUploadInProgress => + 'Дочекайтеся завершення завантаження.'; @override String get dialogCancel => 'Відміна'; @@ -396,7 +426,8 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get loginEmailLabel => 'Адреса електронної пошти'; @override - String get loginErrorMissingEmail => 'Будь ласка, введіть свою електронну адресу.'; + String get loginErrorMissingEmail => + 'Будь ласка, введіть свою електронну адресу.'; @override String get loginPasswordLabel => 'Пароль'; @@ -411,13 +442,19 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get loginErrorMissingUsername => 'Введіть своє ім\'я користувача.'; @override - String get topicValidationErrorTooLong => 'Довжина теми не повинна перевищувати 60 символів.'; + String get topicValidationErrorTooLong => + 'Довжина теми не повинна перевищувати 60 символів.'; @override - String get topicValidationErrorMandatoryButEmpty => 'Теми обовʼязкові в цій організації.'; + String get topicValidationErrorMandatoryButEmpty => + 'Теми обовʼязкові в цій організації.'; @override - String errorServerVersionUnsupportedMessage(String url, String zulipVersion, String minSupportedZulipVersion) { + String errorServerVersionUnsupportedMessage( + String url, + String zulipVersion, + String minSupportedZulipVersion, + ) { return '$url використовує Zulip Server $zulipVersion, який не підтримується. Мінімальною підтримуваною версією є Zulip Server $minSupportedZulipVersion.'; } @@ -457,10 +494,12 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get serverUrlValidationErrorInvalidUrl => 'Введіть дійсну URL-адресу.'; @override - String get serverUrlValidationErrorNoUseEmail => 'Введіть URL-адресу сервера, а не свою електронну адресу.'; + String get serverUrlValidationErrorNoUseEmail => + 'Введіть URL-адресу сервера, а не свою електронну адресу.'; @override - String get serverUrlValidationErrorUnsupportedScheme => 'URL-адреса сервера має починатися з http:// або https://.'; + String get serverUrlValidationErrorUnsupportedScheme => + 'URL-адреса сервера має починатися з http:// або https://.'; @override String get spoilerDefaultHeaderText => 'Спойлер'; @@ -497,10 +536,12 @@ class ZulipLocalizationsUk extends ZulipLocalizations { } @override - String get markAsUnreadInProgress => 'Позначення повідомлень як непрочитаних…'; + String get markAsUnreadInProgress => + 'Позначення повідомлень як непрочитаних…'; @override - String get errorMarkAsUnreadFailedTitle => 'Не вдалося позначити як непрочитане'; + String get errorMarkAsUnreadFailedTitle => + 'Не вдалося позначити як непрочитане'; @override String get today => 'Сьогодні'; @@ -643,25 +684,29 @@ class ZulipLocalizationsUk extends ZulipLocalizations { String get themeSettingSystem => 'Системна'; @override - String get openLinksWithInAppBrowser => 'Відкривати посилання за допомогою браузера додатку'; + String get openLinksWithInAppBrowser => + 'Відкривати посилання за допомогою браузера додатку'; @override String get pollWidgetQuestionMissing => 'Немає питання.'; @override - String get pollWidgetOptionsMissing => 'У цьому опитуванні ще немає варіантів.'; + String get pollWidgetOptionsMissing => + 'У цьому опитуванні ще немає варіантів.'; @override String get experimentalFeatureSettingsPageTitle => 'Експериментальні функції'; @override - String get experimentalFeatureSettingsWarning => 'Ці опції вмикають функції, які ще розробляються та не готові. Вони можуть не працювати та викликати проблеми в інших місцях додатку.\n\nМетою цих налаштувань є експериментування людьми, що працюють над розробкою Zulip.'; + String get experimentalFeatureSettingsWarning => + 'Ці опції вмикають функції, які ще розробляються та не готові. Вони можуть не працювати та викликати проблеми в інших місцях додатку.\n\nМетою цих налаштувань є експериментування людьми, що працюють над розробкою Zulip.'; @override String get errorNotificationOpenTitle => 'Не вдалося відкрити сповіщення'; @override - String get errorNotificationOpenAccountMissing => 'Обліковий запис, пов’язаний із цим сповіщенням, більше не існує.'; + String get errorNotificationOpenAccountMissing => + 'Обліковий запис, пов’язаний із цим сповіщенням, більше не існує.'; @override String get errorReactionAddingFailedTitle => 'Не вдалося додати реакцію'; diff --git a/lib/widgets/message_list.dart b/lib/widgets/message_list.dart index 03ae763bdc..9d8e27757a 100644 --- a/lib/widgets/message_list.dart +++ b/lib/widgets/message_list.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_color_models/flutter_color_models.dart'; @@ -465,8 +463,8 @@ class MessageList extends StatefulWidget { class _MessageListState extends State with PerAccountStoreAwareStateMixin { MessageListView? model; - final ScrollController scrollController = MessageListScrollController(); - final ValueNotifier _scrollToBottomVisibleValue = ValueNotifier(false); + final MessageListScrollController scrollController = MessageListScrollController(); + final ValueNotifier _scrollToBottomVisible = ValueNotifier(false); @override void initState() { @@ -484,7 +482,7 @@ class _MessageListState extends State with PerAccountStoreAwareStat void dispose() { model?.dispose(); scrollController.dispose(); - _scrollToBottomVisibleValue.dispose(); + _scrollToBottomVisible.dispose(); super.dispose(); } @@ -511,9 +509,9 @@ class _MessageListState extends State with PerAccountStoreAwareStat void _handleScrollMetrics(ScrollMetrics scrollMetrics) { if (scrollMetrics.extentAfter == 0) { - _scrollToBottomVisibleValue.value = false; + _scrollToBottomVisible.value = false; } else { - _scrollToBottomVisibleValue.value = true; + _scrollToBottomVisible.value = true; } if (scrollMetrics.extentBefore < kFetchMessagesBufferPixels) { @@ -577,7 +575,7 @@ class _MessageListState extends State with PerAccountStoreAwareStat child: SafeArea( child: ScrollToBottomButton( scrollController: scrollController, - visibleValue: _scrollToBottomVisibleValue))), + visible: _scrollToBottomVisible))), ]))))); } @@ -690,26 +688,20 @@ class _MessageListState extends State with PerAccountStoreAwareStat } class ScrollToBottomButton extends StatelessWidget { - const ScrollToBottomButton({super.key, required this.scrollController, required this.visibleValue}); - - final ValueNotifier visibleValue; - final ScrollController scrollController; - - Future _navigateToBottom() { - final distance = scrollController.position.pixels; - final durationMsAtSpeedLimit = (1000 * distance / 8000).ceil(); - final durationMs = max(300, durationMsAtSpeedLimit); - return scrollController.animateTo( - 0, - duration: Duration(milliseconds: durationMs), - curve: Curves.ease); + const ScrollToBottomButton({super.key, required this.scrollController, required this.visible}); + + final ValueNotifier visible; + final MessageListScrollController scrollController; + + void _scrollToBottom() { + scrollController.position.scrollToEnd(); } @override Widget build(BuildContext context) { final zulipLocalizations = ZulipLocalizations.of(context); return ValueListenableBuilder( - valueListenable: visibleValue, + valueListenable: visible, builder: (BuildContext context, bool value, Widget? child) { return (value && child != null) ? child : const SizedBox.shrink(); }, @@ -720,7 +712,7 @@ class ScrollToBottomButton extends StatelessWidget { iconSize: 40, // Web has the same color in light and dark mode. color: const HSLColor.fromAHSL(0.5, 240, 0.96, 0.68).toColor(), - onPressed: _navigateToBottom)); + onPressed: _scrollToBottom)); } } diff --git a/lib/widgets/scrolling.dart b/lib/widgets/scrolling.dart index 69f46082b3..5bccc680a5 100644 --- a/lib/widgets/scrolling.dart +++ b/lib/widgets/scrolling.dart @@ -43,6 +43,124 @@ class _SingleChildScrollViewWithScrollbarState } } +/// A simulation of motion at a constant velocity. +/// +/// Models a particle that follows Newton's law of inertia, +/// with no forces acting on the particle, and no end to the motion. +/// +/// See also [GravitySimulation], which adds a constant acceleration +/// and a stopping point. +class InertialSimulation extends Simulation { // TODO(upstream) + InertialSimulation(double initialPosition, double velocity) + : _x0 = initialPosition, _v = velocity; + + final double _x0; + final double _v; + + @override + double x(double time) => _x0 + _v * time; + + @override + double dx(double time) => _v; + + @override + bool isDone(double time) => false; + + @override + String toString() => '${objectRuntimeType(this, 'InertialSimulation')}(' + 'x₀: ${_x0.toStringAsFixed(1)}, dx₀: ${_v.toStringAsFixed(1)})'; +} + +/// A simulation of the user impatiently scrolling to the end of a list. +/// +/// The position [x] is in logical pixels, and time is in seconds. +/// +/// The motion is meant to resemble the user scrolling the list down +/// (by dragging up and flinging), and if the list is long then +/// fling-scrolling again and again to keep it moving quickly. +/// +/// In that scenario taken literally, the motion would repeatedly slow down, +/// then speed up again with a fresh drag and fling. But doing that in +/// response to a simulated drag, as opposed to when the user is actually +/// dragging with their own finger, would feel jerky and not a good UX. +/// Instead this takes a smoothed-out approximation of such a trajectory. +class ScrollToEndSimulation extends InertialSimulation { + factory ScrollToEndSimulation(ScrollPosition position) { + final tolerance = position.physics.toleranceFor(position); + final startPosition = position.pixels; + final estimatedEndPosition = position.maxScrollExtent; + final velocityForMinDuration = (estimatedEndPosition - startPosition) + / (minDuration.inMilliseconds / 1000.0); + final velocity = clampDouble(velocityForMinDuration, + // If the starting position is beyond the estimated end + // (i.e. `velocityForMinDuration < 0`), or very close to it, + // then move forward at a small positive velocity. + // Let the overscroll handling bring the position to exactly the end. + 2 * tolerance.velocity, + topSpeed); + return ScrollToEndSimulation._(startPosition, velocity); + } + + ScrollToEndSimulation._(super.initialPosition, super.velocity); + + /// The top speed to move at, in logical pixels per second. + /// + /// This will be the speed whenever the estimated distance to be traveled + /// is long enough to take at least [minDuration] at this speed. + /// + /// This is chosen to equal the top speed that can be produced + /// by a fling gesture in a Flutter [ScrollView], + /// which in turn was chosen to equal the top speed of + /// an (initial) fling gesture in a native Android scroll view. + static const double topSpeed = 8000; + + /// The desired duration of the animation when traveling short distances. + /// + /// The speed will be chosen so that traveling the estimated distance + /// will take this long, whenever that distance is short enough + /// that that means a speed of at most [topSpeed]. + static const minDuration = Duration(milliseconds: 300); +} + +/// An activity that animates a scroll view smoothly to its end. +/// +/// In particular this drives the "scroll to bottom" button +/// in the Zulip message list. +class ScrollToEndActivity extends DrivenScrollActivity { + /// Create an activity that animates a scroll view smoothly to its end. + /// + /// The [delegate] is required to also implement [ScrollPosition]. + ScrollToEndActivity(ScrollActivityDelegate delegate) + : super.simulation(delegate, + vsync: (delegate as ScrollPosition).context.vsync, + ScrollToEndSimulation(delegate as ScrollPosition)); + + ScrollPosition get _position => delegate as ScrollPosition; + + @override + bool applyMoveTo(double value) { + bool done = false; + if (value > _position.maxScrollExtent) { + // The activity has reached the end. + // Stop at exactly the end, rather than causing overscroll. + // Possibly some overscroll would actually be desirable, but: + // TODO(upstream) stretch-overscroll seems busted, inverted: + // Is this formula (from [_StretchController.absorbImpact] really right? + // _stretchSizeTween.end = + // math.min(_stretchIntensity + (_flingFriction / velocity), 1.0); + // Seems to take low velocity to the largest stretch, and high velocity + // to the smallest stretch. + // Specifically, a very slow fling produces a very large stretch, + // while other flings produce small stretches that vary little + // between modest speed (~300 px/s) and top speed (8000 px/s). + value = _position.maxScrollExtent; + done = true; + } + if (!super.applyMoveTo(value)) return false; + return !done; + } +} + /// A version of [ScrollPosition] adapted for the Zulip message list, /// used by [MessageListScrollController]. class MessageListScrollPosition extends ScrollPositionWithSingleContext { @@ -167,6 +285,36 @@ class MessageListScrollPosition extends ScrollPositionWithSingleContext { return !changed; } + + /// Scroll the position smoothly to the end of the scrollable content. + /// + /// This is similar to calling [animateTo] with a target of [maxScrollExtent], + /// except that if [maxScrollExtent] changes over the course of the animation + /// (for example due to more content being added at the end, + /// or due to the estimated length of the content changing as + /// different items scroll into the viewport), + /// this animation will carry on until it reaches the updated value + /// of [maxScrollExtent], not the value it had at the start of the animation. + /// + /// The animation is typically handled by a [ScrollToEndActivity]. + void scrollToEnd() { + final tolerance = physics.toleranceFor(this); + if (nearEqual(pixels, maxScrollExtent, tolerance.distance)) { + // Skip the animation; jump right to the target, which is already close. + jumpTo(maxScrollExtent); + return; + } + + if (pixels > maxScrollExtent) { + // The position is already scrolled past the end. Let overscroll handle it. + // (This situation shouldn't even arise; the UI only offers this option + // when `pixels < maxScrollExtent`.) + goBallistic(0.0); + return; + } + + beginActivity(ScrollToEndActivity(this)); + } } /// A version of [ScrollController] adapted for the Zulip message list. @@ -180,7 +328,10 @@ class MessageListScrollController extends ScrollController { }); @override - ScrollPosition createScrollPosition(ScrollPhysics physics, + MessageListScrollPosition get position => super.position as MessageListScrollPosition; + + @override + MessageListScrollPosition createScrollPosition(ScrollPhysics physics, ScrollContext context, ScrollPosition? oldPosition) { return MessageListScrollPosition( physics: physics, diff --git a/pubspec.lock b/pubspec.lock index f9401bbaf3..a1a7177bc2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1355,5 +1355,5 @@ packages: source: path version: "0.0.1" sdks: - dart: ">=3.9.0-55.0.dev <4.0.0" - flutter: ">=3.32.0-1.0.pre.257" + dart: ">=3.9.0-63.0.dev <4.0.0" + flutter: ">=3.32.0-1.0.pre.332" diff --git a/pubspec.yaml b/pubspec.yaml index 95d05d41c8..a1c9f6dd2d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,8 +14,8 @@ environment: # We use a recent version of Flutter from its main channel, and # the corresponding recent version of the Dart SDK. # Feel free to update these regularly; see README.md for instructions. - sdk: '>=3.9.0-55.0.dev <4.0.0' - flutter: '>=3.32.0-1.0.pre.257' # b90818ec53ac6f774cdeebd2acd9ab8e71b5c7b5 + sdk: '>=3.9.0-63.0.dev <4.0.0' + flutter: '>=3.32.0-1.0.pre.332' # adae8bbdbaed53ef305726fcfe811b2351d73a1a # To update dependencies, see instructions in README.md. dependencies: diff --git a/test/flutter_checks.dart b/test/flutter_checks.dart index 49e402d158..328bfdd843 100644 --- a/test/flutter_checks.dart +++ b/test/flutter_checks.dart @@ -7,15 +7,20 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -extension PaintChecks on Subject { - Subject get shader => has((x) => x.shader, 'shader'); -} +//////////////////////////////////////////////////////////////// +// From the Flutter engine, i.e. from dart:ui. +// extension OffsetChecks on Subject { Subject get dx => has((x) => x.dx, 'dx'); Subject get dy => has((x) => x.dy, 'dy'); } +extension SizeChecks on Subject { + Subject get width => has((x) => x.width, 'width'); + Subject get height => has((x) => x.height, 'height'); +} + extension RectChecks on Subject { Subject get left => has((d) => d.left, 'left'); Subject get top => has((d) => d.top, 'top'); @@ -26,52 +31,106 @@ extension RectChecks on Subject { // TODO others } +extension PaintChecks on Subject { + Subject get shader => has((x) => x.shader, 'shader'); +} + +extension FontVariationChecks on Subject { + Subject get axis => has((x) => x.axis, 'axis'); + Subject get value => has((x) => x.value, 'value'); +} + +//////////////////////////////////////////////////////////////// +// From 'package:flutter/foundation.dart'. +// + +extension ValueListenableChecks on Subject> { + Subject get value => has((c) => c.value, 'value'); +} + +//////////////////////////////////////////////////////////////// +// From 'package:flutter/services.dart'. +// + +extension ClipboardDataChecks on Subject { + Subject get text => has((d) => d.text, 'text'); +} + +extension TextEditingValueChecks on Subject { + Subject get text => has((x) => x.text, 'text'); + Subject get selection => has((x) => x.selection, 'selection'); + Subject get composing => has((x) => x.composing, 'composing'); +} + +//////////////////////////////////////////////////////////////// +// From 'package:flutter/animation.dart'. +// + extension AnimationChecks on Subject> { Subject get status => has((d) => d.status, 'status'); Subject get value => has((d) => d.value, 'value'); } -extension ClipboardDataChecks on Subject { - Subject get text => has((d) => d.text, 'text'); +//////////////////////////////////////////////////////////////// +// From 'package:flutter/painting.dart'. +// + +extension BoxDecorationChecks on Subject { + Subject get color => has((x) => x.color, 'color'); } -extension ColoredBoxChecks on Subject { - Subject get color => has((d) => d.color, 'color'); +extension TextStyleChecks on Subject { + Subject get inherit => has((t) => t.inherit, 'inherit'); + Subject get color => has((t) => t.color, 'color'); + Subject get fontSize => has((t) => t.fontSize, 'fontSize'); + Subject get fontWeight => has((t) => t.fontWeight, 'fontWeight'); + Subject get letterSpacing => has((t) => t.letterSpacing, 'letterSpacing'); + Subject?> get fontVariations => has((t) => t.fontVariations, 'fontVariations'); + Subject get fontFamily => has((t) => t.fontFamily, 'fontFamily'); + Subject?> get fontFamilyFallback => has((t) => t.fontFamilyFallback, 'fontFamilyFallback'); + + // TODO others } -extension GlobalKeyChecks> on Subject> { - Subject get currentContext => has((k) => k.currentContext, 'currentContext'); - Subject get currentWidget => has((k) => k.currentWidget, 'currentWidget'); - Subject get currentState => has((k) => k.currentState, 'currentState'); +extension InlineSpanChecks on Subject { + Subject get style => has((x) => x.style, 'style'); } +//////////////////////////////////////////////////////////////// +// From 'package:flutter/rendering.dart'. +// + extension RenderBoxChecks on Subject { Subject get size => has((x) => x.size, 'size'); } -extension IconChecks on Subject { - Subject get icon => has((i) => i.icon, 'icon'); - Subject get color => has((i) => i.color, 'color'); - - // TODO others +extension RenderParagraphChecks on Subject { + Subject get text => has((x) => x.text, 'text'); + Subject get didExceedMaxLines => has((x) => x.didExceedMaxLines, 'didExceedMaxLines'); } -extension RouteChecks on Subject> { - Subject get isFirst => has((r) => r.isFirst, 'isFirst'); - Subject get settings => has((r) => r.settings, 'settings'); +//////////////////////////////////////////////////////////////// +// From 'package:flutter/widgets.dart'. +// + +extension GlobalKeyChecks> on Subject> { + Subject get currentContext => has((k) => k.currentContext, 'currentContext'); + Subject get currentWidget => has((k) => k.currentWidget, 'currentWidget'); + Subject get currentState => has((k) => k.currentState, 'currentState'); } -extension PageRouteChecks on Subject> { - Subject get fullscreenDialog => has((x) => x.fullscreenDialog, 'fullscreenDialog'); +extension ElementChecks on Subject { + Subject get size => has((t) => t.size, 'size'); + // TODO more } -extension RouteSettingsChecks on Subject { - Subject get name => has((s) => s.name, 'name'); - Subject get arguments => has((s) => s.arguments, 'arguments'); +extension MediaQueryDataChecks on Subject { + Subject get textScaler => has((x) => x.textScaler, 'textScaler'); + // TODO more } -extension ValueListenableChecks on Subject> { - Subject get value => has((c) => c.value, 'value'); +extension ColoredBoxChecks on Subject { + Subject get color => has((d) => d.color, 'color'); } extension TextChecks on Subject { @@ -79,38 +138,50 @@ extension TextChecks on Subject { Subject get style => has((t) => t.style, 'style'); } -extension TextEditingValueChecks on Subject { - Subject get text => has((x) => x.text, 'text'); - Subject get selection => has((x) => x.selection, 'selection'); - Subject get composing => has((x) => x.composing, 'composing'); -} - extension TextEditingControllerChecks on Subject { Subject get text => has((t) => t.text, 'text'); } -extension TextFieldChecks on Subject { - Subject get textCapitalization => has((t) => t.textCapitalization, 'textCapitalization'); - Subject get decoration => has((t) => t.decoration, 'decoration'); - Subject get controller => has((t) => t.controller, 'controller'); +extension ScrollActivityChecks on Subject { + Subject get velocity => has((x) => x.velocity, 'velocity'); } -extension TextStyleChecks on Subject { - Subject get inherit => has((t) => t.inherit, 'inherit'); - Subject get color => has((t) => t.color, 'color'); - Subject get fontSize => has((t) => t.fontSize, 'fontSize'); - Subject get fontWeight => has((t) => t.fontWeight, 'fontWeight'); - Subject get letterSpacing => has((t) => t.letterSpacing, 'letterSpacing'); - Subject?> get fontVariations => has((t) => t.fontVariations, 'fontVariations'); - Subject get fontFamily => has((t) => t.fontFamily, 'fontFamily'); - Subject?> get fontFamilyFallback => has((t) => t.fontFamilyFallback, 'fontFamilyFallback'); +extension IconChecks on Subject { + Subject get icon => has((i) => i.icon, 'icon'); + Subject get color => has((i) => i.color, 'color'); // TODO others } -extension FontVariationChecks on Subject { - Subject get axis => has((x) => x.axis, 'axis'); - Subject get value => has((x) => x.value, 'value'); +extension TableRowChecks on Subject { + Subject get decoration => has((x) => x.decoration, 'decoration'); +} + +extension TableChecks on Subject { + Subject> get children => has((x) => x.children, 'children'); +} + +extension RouteChecks on Subject> { + Subject get isFirst => has((r) => r.isFirst, 'isFirst'); + Subject get settings => has((r) => r.settings, 'settings'); +} + +extension RouteSettingsChecks on Subject { + Subject get name => has((s) => s.name, 'name'); + Subject get arguments => has((s) => s.arguments, 'arguments'); +} + +extension PageRouteChecks on Subject> { + Subject get fullscreenDialog => has((x) => x.fullscreenDialog, 'fullscreenDialog'); +} + +//////////////////////////////////////////////////////////////// +// From 'package:flutter/material.dart'. +// + +extension MaterialChecks on Subject { + Subject get color => has((x) => x.color, 'color'); + // TODO more } extension TextThemeChecks on Subject { @@ -139,63 +210,28 @@ extension TypographyChecks on Subject { Subject get tall => has((t) => t.tall, 'tall'); } -extension InlineSpanChecks on Subject { - Subject get style => has((x) => x.style, 'style'); -} - -extension RenderParagraphChecks on Subject { - Subject get text => has((x) => x.text, 'text'); - Subject get didExceedMaxLines => has((x) => x.didExceedMaxLines, 'didExceedMaxLines'); -} - -extension SizeChecks on Subject { - Subject get width => has((x) => x.width, 'width'); - Subject get height => has((x) => x.height, 'height'); -} - -extension ElementChecks on Subject { - Subject get size => has((t) => t.size, 'size'); - // TODO more -} - -extension MediaQueryDataChecks on Subject { - Subject get textScaler => has((x) => x.textScaler, 'textScaler'); - // TODO more -} - -extension MaterialChecks on Subject { - Subject get color => has((x) => x.color, 'color'); - // TODO more +extension ThemeDataChecks on Subject { + Subject get brightness => has((x) => x.brightness, 'brightness'); } extension InputDecorationChecks on Subject { Subject get hintText => has((x) => x.hintText, 'hintText'); } -extension RadioListTileChecks on Subject> { - Subject get checked => has((x) => x.checked, 'checked'); -} - -extension SwitchListTileChecks on Subject { - Subject get value => has((x) => x.value, 'value'); -} - -extension ThemeDataChecks on Subject { - Subject get brightness => has((x) => x.brightness, 'brightness'); -} - -extension BoxDecorationChecks on Subject { - Subject get color => has((x) => x.color, 'color'); +extension TextFieldChecks on Subject { + Subject get textCapitalization => has((t) => t.textCapitalization, 'textCapitalization'); + Subject get decoration => has((t) => t.decoration, 'decoration'); + Subject get controller => has((t) => t.controller, 'controller'); } -extension TableRowChecks on Subject { - Subject get decoration => has((x) => x.decoration, 'decoration'); +extension IconButtonChecks on Subject { + Subject get isSelected => has((x) => x.isSelected, 'isSelected'); } -extension TableChecks on Subject
{ - Subject> get children => has((x) => x.children, 'children'); +extension SwitchListTileChecks on Subject { + Subject get value => has((x) => x.value, 'value'); } -extension IconButtonChecks on Subject { - Subject get isSelected => has((x) => x.isSelected, 'isSelected'); +extension RadioListTileChecks on Subject> { + Subject get checked => has((x) => x.checked, 'checked'); } diff --git a/test/widgets/message_list_test.dart b/test/widgets/message_list_test.dart index 0262df378e..44f9a3203d 100644 --- a/test/widgets/message_list_test.dart +++ b/test/widgets/message_list_test.dart @@ -462,10 +462,7 @@ void main() { testWidgets('scrolling changes visibility', (tester) async { await setupMessageListPage(tester, messageCount: 10); - final scrollController = findMessageListScrollController(tester)!; - - // Initial state should be not visible, as the message list renders with latest message in view check(isButtonVisible(tester)).equals(false); scrollController.jumpTo(-600); @@ -480,41 +477,73 @@ void main() { testWidgets('dimension updates changes visibility', (tester) async { await setupMessageListPage(tester, messageCount: 100); + // Scroll up, to hide the button. final scrollController = findMessageListScrollController(tester)!; - - // Initial state should be not visible, as the message list renders with latest message in view - check(isButtonVisible(tester)).equals(false); - scrollController.jumpTo(-600); await tester.pump(); check(isButtonVisible(tester)).equals(true); + // Make the view taller, so that the bottom of the list is back in view. addTearDown(tester.view.resetPhysicalSize); tester.view.physicalSize = const Size(2000, 40000); await tester.pump(); - // Dimension changes use NotificationListener + // which has a one-frame lag. If that ever gets resolved, + // this extra pump would ideally be removed.) await tester.pump(); + // Check the button duly disappears again. check(isButtonVisible(tester)).equals(false); }); - testWidgets('button functionality', (tester) async { + testWidgets('button works', (tester) async { await setupMessageListPage(tester, messageCount: 10); - final scrollController = findMessageListScrollController(tester)!; - - // Initial state should be not visible, as the message list renders with latest message in view - check(isButtonVisible(tester)).equals(false); - scrollController.jumpTo(-600); await tester.pump(); - check(isButtonVisible(tester)).equals(true); + check(scrollController.position.pixels).equals(-600); + // Tap button. await tester.tap(find.byType(ScrollToBottomButton)); + // The list scrolls to the end… await tester.pumpAndSettle(); - check(isButtonVisible(tester)).equals(false); check(scrollController.position.pixels).equals(0); + // … and for good measure confirm the button disappeared. + check(isButtonVisible(tester)).equals(false); + }); + + testWidgets('scrolls at reasonable, constant speed', (tester) async { + const maxSpeed = 8000.0; + const distance = 40000.0; + await setupMessageListPage(tester, messageCount: 1000); + final controller = findMessageListScrollController(tester)!; + + // Scroll a long distance up, many screenfuls. + controller.jumpTo(-distance); + await tester.pump(); + check(controller.position.pixels).equals(-distance); + + // Tap button. + await tester.tap(find.byType(ScrollToBottomButton)); + await tester.pump(); + + // Measure speed. + final log = []; + double pos = controller.position.pixels; + while (pos < 0) { + check(log.length).isLessThan(30); + await tester.pump(const Duration(seconds: 1)); + final lastPos = pos; + pos = controller.position.pixels; + log.add(pos - lastPos); + } + // Check the main question: the speed was as expected throughout. + check(log.slice(0, log.length-1)).every((it) => it.equals(maxSpeed)); + check(log).last..isGreaterThan(0)..isLessOrEqual(maxSpeed); + + // Also check the test's assumptions: the scroll reached the end… + check(pos).equals(0); + // … and scrolled far enough to effectively test the max speed. + check(log.sum).isGreaterThan(2 * maxSpeed); }); }); diff --git a/test/widgets/scrolling_test.dart b/test/widgets/scrolling_test.dart index 8f1820e6ff..8e0afafef4 100644 --- a/test/widgets/scrolling_test.dart +++ b/test/widgets/scrolling_test.dart @@ -1,4 +1,5 @@ import 'package:checks/checks.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:zulip/widgets/scrolling.dart'; @@ -8,12 +9,12 @@ import '../flutter_checks.dart'; void main() { group('MessageListScrollView', () { Widget buildList({ - MessageListScrollController? controller, + required MessageListScrollController controller, required double topHeight, required double bottomHeight, }) { return MessageListScrollView( - controller: controller ?? MessageListScrollController(), + controller: controller, center: const ValueKey('center'), slivers: [ SliverToBoxAdapter( @@ -23,15 +24,22 @@ void main() { ]); } + late MessageListScrollController controller; + late MessageListScrollPosition position; + Future prepare(WidgetTester tester, { - MessageListScrollController? controller, + bool reuseController = false, required double topHeight, required double bottomHeight, }) async { + if (!reuseController) { + controller = MessageListScrollController(); + } await tester.pumpWidget(Directionality(textDirection: TextDirection.ltr, child: buildList(controller: controller, topHeight: topHeight, bottomHeight: bottomHeight))); await tester.pump(); + position = controller.position; } // The `skipOffstage: false` produces more informative output @@ -123,20 +131,18 @@ void main() { }); testWidgets('stick to end of list when it grows', (tester) async { - final controller = MessageListScrollController(); - await prepare(tester, controller: controller, + await prepare(tester, topHeight: 400, bottomHeight: 400); check(tester.getRect(findBottom))..top.equals(200)..bottom.equals(600); // Bottom sliver grows; remain scrolled to (new) bottom. - await prepare(tester, controller: controller, + await prepare(tester, reuseController: true, topHeight: 400, bottomHeight: 500); check(tester.getRect(findBottom))..top.equals(100)..bottom.equals(600); }); testWidgets('when not at end, let it grow without following', (tester) async { - final controller = MessageListScrollController(); - await prepare(tester, controller: controller, + await prepare(tester, topHeight: 400, bottomHeight: 400); check(tester.getRect(findBottom))..top.equals(200)..bottom.equals(600); @@ -146,7 +152,7 @@ void main() { check(tester.getRect(findBottom))..top.equals(300)..bottom.equals(700); // Bottom sliver grows; remain at existing position, now farther from end. - await prepare(tester, controller: controller, + await prepare(tester, reuseController: true, topHeight: 400, bottomHeight: 500); check(tester.getRect(findBottom))..top.equals(300)..bottom.equals(800); }); @@ -186,5 +192,201 @@ void main() { // … and check the scroll position is preserved, not reset to initial. check(tester.getRect(findTop)).bottom.equals(400); }); + + group('scrollToEnd', () { + testWidgets('short -> slow', (tester) async { + await prepare(tester, topHeight: 300, bottomHeight: 600); + await tester.drag(findBottom, Offset(0, 300)); + await tester.pump(); + check(position.extentAfter).equals(300); + + // Start scrolling to end, from just a short distance up. + position.scrollToEnd(); + await tester.pump(); + check(position.extentAfter).equals(300); + check(position.activity).isA(); + + // The scrolling moves at a stately pace; … + await tester.pump(Duration(milliseconds: 100)); + check(position.extentAfter).equals(200); + + await tester.pump(Duration(milliseconds: 100)); + check(position.extentAfter).equals(100); + + // … then upon reaching the end, … + await tester.pump(Duration(milliseconds: 100)); + check(position.extentAfter).equals(0); + + // … goes idle on the next frame, … + await tester.pump(Duration(milliseconds: 1)); + check(position.activity).isA(); + // … without moving any farther. + check(position.extentAfter).equals(0); + }); + + testWidgets('long -> bounded speed', (tester) async { + const referenceSpeed = 8000.0; + const seconds = 10; + const distance = seconds * referenceSpeed; + await prepare(tester, topHeight: distance + 1000, bottomHeight: 300); + await tester.drag(findBottom, Offset(0, distance)); + await tester.pump(); + check(position.extentAfter).equals(distance); + + // Start scrolling to end. + position.scrollToEnd(); + await tester.pump(); + check(position.activity).isA(); + + // Let it scroll, plotting the trajectory. + final log = []; + for (int i = 0; i < seconds; i++) { + log.add(position.extentAfter); + await tester.pump(const Duration(seconds: 1)); + } + log.add(position.extentAfter); + check(log).deepEquals(List.generate(seconds + 1, + (i) => distance - referenceSpeed * i)); + + // Having reached the end, … + check(position.extentAfter).equals(0); + // … it goes idle on the next frame, … + await tester.pump(Duration(milliseconds: 1)); + check(position.activity).isA(); + // … without moving any farther. + check(position.extentAfter).equals(0); + }); + + testWidgets('starting from overscroll, just drift', (tester) async { + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + await prepare(tester, topHeight: 400, bottomHeight: 400); + + // Drag into overscroll. + await tester.drag(findBottom, Offset(0, -100)); + await tester.pump(); + final offset1 = position.pixels - position.maxScrollExtent; + check(offset1).isGreaterThan(100 / 2); + check(position.activity).isA(); + + // Start drifting back into range. + await tester.pump(Duration(milliseconds: 10)); + final offset2 = position.pixels - position.maxScrollExtent; + check(offset2)..isGreaterThan(0.0)..isLessThan(offset1); + check(position.activity).isA() + .velocity.isLessThan(0); + + // Invoke `scrollToEnd`. The motion should stop… + position.scrollToEnd(); + await tester.pump(); + check(position.pixels - position.maxScrollExtent).equals(offset2); + check(position.activity).isA() + .velocity.equals(0); + + // … and resume drifting from there… + await tester.pump(Duration(milliseconds: 10)); + final offset3 = position.pixels - position.maxScrollExtent; + check(offset3)..isGreaterThan(0.0)..isLessThan(offset2); + check(position.activity).isA() + .velocity.isLessThan(0); + + // … to eventually return to being in range. + await tester.pump(Duration(seconds: 1)); + check(position.pixels - position.maxScrollExtent).equals(0); + check(position.activity).isA(); + + debugDefaultTargetPlatformOverride = null; + }); + + testWidgets('starting very near end, apply min speed', (tester) async { + await prepare(tester, topHeight: 400, bottomHeight: 400); + // Verify the assumption used for constructing the example numbers below. + check(position.physics.toleranceFor(position).velocity) + .isCloseTo(20/3, .01); + + position.jumpTo(398); + await tester.pump(); + check(position.extentAfter).equals(2); + + position.scrollToEnd(); + await tester.pump(); + check(position.extentAfter).equals(2); + + // Reach the end in just 150ms, not 300ms. + await tester.pump(Duration(milliseconds: 75)); + check(position.extentAfter).equals(1); + await tester.pump(Duration(milliseconds: 75)); + check(position.extentAfter).equals(0); + }); + + testWidgets('on overscroll, stop', (tester) async { + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + await prepare(tester, topHeight: 400, bottomHeight: 1000); + + // Scroll up… + position.jumpTo(400); + await tester.pump(); + check(position.extentAfter).equals(600); + + // … then invoke `scrollToEnd`… + position.scrollToEnd(); + await tester.pump(); + + // … but have the bottom sliver turn out to be shorter than it was. + await prepare(tester, topHeight: 400, bottomHeight: 600, + reuseController: true); + check(position.extentAfter).equals(200); + + // Let the scrolling animation proceed until it hits the end. + int steps = 0; + while (position.extentAfter > 0) { + check(++steps).isLessThan(100); + await tester.pump(Duration(milliseconds: 11)); + } + + // This is the very first frame where the position reached the end. + // It's at exactly the end, no farther… + check(position.pixels - position.maxScrollExtent).equals(0); + + // … and the animation is done. Nothing further happens. + check(position.activity).isA(); + await tester.pump(Duration(milliseconds: 11)); + check(position.pixels - position.maxScrollExtent).equals(0); + check(position.activity).isA(); + + debugDefaultTargetPlatformOverride = null; + }); + + testWidgets('keep going even if content turns out longer', (tester) async { + await prepare(tester, topHeight: 1000, bottomHeight: 3000); + + // Scroll up… + position.jumpTo(0); + await tester.pump(); + check(position.extentAfter).equals(3000); + + // … then invoke `scrollToEnd`… + position.scrollToEnd(); + await tester.pump(); + + // … but have the bottom sliver turn out to be longer than it was. + await prepare(tester, topHeight: 1000, bottomHeight: 6000, + reuseController: true); + check(position.extentAfter).equals(6000); + + // Let the scrolling animation go until it stops. + int steps = 0; + double prevRemaining; + double remaining = position.extentAfter; + do { + prevRemaining = remaining; + check(++steps).isLessThan(100); + await tester.pump(Duration(milliseconds: 10)); + remaining = position.extentAfter; + } while (remaining < prevRemaining); + + // The scroll position should be all the way at the end. + check(remaining).equals(0); + }); + }); }); }