From 135a8af84d1e2d7b201e28521070dcb500ed2cd8 Mon Sep 17 00:00:00 2001 From: poppingmoon <63451158+poppingmoon@users.noreply.github.com> Date: Wed, 30 Oct 2024 01:03:20 +0900 Subject: [PATCH] feat: spell check for post form --- lib/i18n/aria/aria.i18n.yaml | 1 + lib/i18n/strings.g.dart | 2 +- lib/i18n/strings_en_US.g.dart | 1 + lib/model/general_settings.dart | 1 + lib/model/general_settings.freezed.dart | 24 ++++++++++++++++++- lib/model/general_settings.g.dart | 2 ++ .../general_settings_notifier_provider.dart | 5 ++++ .../general_settings_notifier_provider.g.dart | 2 +- lib/view/page/settings/behavior_page.dart | 9 +++++++ lib/view/widget/post_form.dart | 9 +++++++ 10 files changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/i18n/aria/aria.i18n.yaml b/lib/i18n/aria/aria.i18n.yaml index 08334743..18fb51cd 100644 --- a/lib/i18n/aria/aria.i18n.yaml +++ b/lib/i18n/aria/aria.i18n.yaml @@ -41,6 +41,7 @@ emojiPickerUseDialog: "Display emoji picker as dialog" enableEmojiFadeIn: "Enable fade-in animations for custom emojis" enableFederation: "Enable federation" enablePredictiveBack: "Enable predictive back animations" +enableSpellCheck: "Enable spell check" endpoint: "Endpoint" expandNote: "Expand note" extraMentionsWarning: "This note includes mentions that are not included in the target note of reply" diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index 967a1fef..8f0e90a1 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,7 +4,7 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 31 -/// Strings: 54621 (1761 per locale) +/// Strings: 54622 (1762 per locale) // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/lib/i18n/strings_en_US.g.dart b/lib/i18n/strings_en_US.g.dart index 6922ff95..ee5f9b3d 100644 --- a/lib/i18n/strings_en_US.g.dart +++ b/lib/i18n/strings_en_US.g.dart @@ -95,6 +95,7 @@ class TranslationsAriaEnUs { String get enableEmojiFadeIn => 'Enable fade-in animations for custom emojis'; String get enableFederation => 'Enable federation'; String get enablePredictiveBack => 'Enable predictive back animations'; + String get enableSpellCheck => 'Enable spell check'; String get endpoint => 'Endpoint'; String get expandNote => 'Expand note'; String get extraMentionsWarning => 'This note includes mentions that are not included in the target note of reply'; diff --git a/lib/model/general_settings.dart b/lib/model/general_settings.dart index 98fe347e..c4f06a2e 100644 --- a/lib/model/general_settings.dart +++ b/lib/model/general_settings.dart @@ -129,6 +129,7 @@ class GeneralSettings with _$GeneralSettings { @Default(true) bool confirmBeforeFollow, @Default(false) bool confirmWhenRevealingSensitiveMedia, @Default(LaunchMode.externalApplication) LaunchMode launchMode, + @Default(false) bool enableSpellCheck, @Default(false) bool enablePredictiveBack, // Theme diff --git a/lib/model/general_settings.freezed.dart b/lib/model/general_settings.freezed.dart index 0c97ddbf..317297a1 100644 --- a/lib/model/general_settings.freezed.dart +++ b/lib/model/general_settings.freezed.dart @@ -114,6 +114,7 @@ mixin _$GeneralSettings { bool get confirmWhenRevealingSensitiveMedia => throw _privateConstructorUsedError; LaunchMode get launchMode => throw _privateConstructorUsedError; + bool get enableSpellCheck => throw _privateConstructorUsedError; bool get enablePredictiveBack => throw _privateConstructorUsedError; // Theme ThemeMode get themeMode => throw _privateConstructorUsedError; String get lightThemeId => throw _privateConstructorUsedError; @@ -216,6 +217,7 @@ abstract class $GeneralSettingsCopyWith<$Res> { bool confirmBeforeFollow, bool confirmWhenRevealingSensitiveMedia, LaunchMode launchMode, + bool enableSpellCheck, bool enablePredictiveBack, ThemeMode themeMode, String lightThemeId, @@ -316,6 +318,7 @@ class _$GeneralSettingsCopyWithImpl<$Res, $Val extends GeneralSettings> Object? confirmBeforeFollow = null, Object? confirmWhenRevealingSensitiveMedia = null, Object? launchMode = null, + Object? enableSpellCheck = null, Object? enablePredictiveBack = null, Object? themeMode = null, Object? lightThemeId = null, @@ -640,6 +643,10 @@ class _$GeneralSettingsCopyWithImpl<$Res, $Val extends GeneralSettings> ? _value.launchMode : launchMode // ignore: cast_nullable_to_non_nullable as LaunchMode, + enableSpellCheck: null == enableSpellCheck + ? _value.enableSpellCheck + : enableSpellCheck // ignore: cast_nullable_to_non_nullable + as bool, enablePredictiveBack: null == enablePredictiveBack ? _value.enablePredictiveBack : enablePredictiveBack // ignore: cast_nullable_to_non_nullable @@ -749,6 +756,7 @@ abstract class _$$GeneralSettingsImplCopyWith<$Res> bool confirmBeforeFollow, bool confirmWhenRevealingSensitiveMedia, LaunchMode launchMode, + bool enableSpellCheck, bool enablePredictiveBack, ThemeMode themeMode, String lightThemeId, @@ -847,6 +855,7 @@ class __$$GeneralSettingsImplCopyWithImpl<$Res> Object? confirmBeforeFollow = null, Object? confirmWhenRevealingSensitiveMedia = null, Object? launchMode = null, + Object? enableSpellCheck = null, Object? enablePredictiveBack = null, Object? themeMode = null, Object? lightThemeId = null, @@ -1171,6 +1180,10 @@ class __$$GeneralSettingsImplCopyWithImpl<$Res> ? _value.launchMode : launchMode // ignore: cast_nullable_to_non_nullable as LaunchMode, + enableSpellCheck: null == enableSpellCheck + ? _value.enableSpellCheck + : enableSpellCheck // ignore: cast_nullable_to_non_nullable + as bool, enablePredictiveBack: null == enablePredictiveBack ? _value.enablePredictiveBack : enablePredictiveBack // ignore: cast_nullable_to_non_nullable @@ -1276,6 +1289,7 @@ class _$GeneralSettingsImpl implements _GeneralSettings { this.confirmBeforeFollow = true, this.confirmWhenRevealingSensitiveMedia = false, this.launchMode = LaunchMode.externalApplication, + this.enableSpellCheck = false, this.enablePredictiveBack = false, this.themeMode = ThemeMode.system, this.lightThemeId = 'a58a0abb-ff8c-476a-8dec-0ad7837e7e96', @@ -1535,6 +1549,9 @@ class _$GeneralSettingsImpl implements _GeneralSettings { final LaunchMode launchMode; @override @JsonKey() + final bool enableSpellCheck; + @override + @JsonKey() final bool enablePredictiveBack; // Theme @override @@ -1549,7 +1566,7 @@ class _$GeneralSettingsImpl implements _GeneralSettings { @override String toString() { - return 'GeneralSettings(locale: $locale, collapseRenotes: $collapseRenotes, sensitive: $sensitive, highlightSensitiveMedia: $highlightSensitiveMedia, animatedMfm: $animatedMfm, advancedMfm: $advancedMfm, showReactionsCount: $showReactionsCount, loadRawImages: $loadRawImages, instanceTicker: $instanceTicker, showNoteCreatedAt: $showNoteCreatedAt, showAvatarsInNote: $showAvatarsInNote, showAvatarsInSubNote: $showAvatarsInSubNote, squareAvatars: $squareAvatars, showAvatarDecorations: $showAvatarDecorations, showQuoteButtonInNoteFooter: $showQuoteButtonInNoteFooter, showLikeButtonInNoteFooter: $showLikeButtonInNoteFooter, showClipButtonInNoteFooter: $showClipButtonInNoteFooter, showTranslateButtonInNoteFooter: $showTranslateButtonInNoteFooter, showNoteReactionsViewer: $showNoteReactionsViewer, showSubNoteReactionsViewer: $showSubNoteReactionsViewer, showNoteFooter: $showNoteFooter, showSubNoteFooter: $showSubNoteFooter, alwaysExpandCw: $alwaysExpandCw, alwaysExpandLongNote: $alwaysExpandLongNote, alwaysExpandMediaInSubNote: $alwaysExpandMediaInSubNote, mergeReactionsByName: $mergeReactionsByName, alwaysShowAllReactions: $alwaysShowAllReactions, mediaListWithOneImageAppearance: $mediaListWithOneImageAppearance, thumbnailBoxFit: $thumbnailBoxFit, emojiStyle: $emojiStyle, fontFamily: $fontFamily, fontSize: $fontSize, lineHeight: $lineHeight, avatarScale: $avatarScale, reactionsDisplayScale: $reactionsDisplayScale, limitWidthOfReaction: $limitWidthOfReaction, noteFooterScale: $noteFooterScale, noteVerticalPadding: $noteVerticalPadding, noteHorizontalPadding: $noteHorizontalPadding, publicNoteBackgroundColor: $publicNoteBackgroundColor, homeNoteBackgroundColor: $homeNoteBackgroundColor, followersNoteBackgroundColor: $followersNoteBackgroundColor, specifiedNoteBackgroundColor: $specifiedNoteBackgroundColor, emojiPickerUseDialog: $emojiPickerUseDialog, emojiPickerScale: $emojiPickerScale, emojiPickerAutofocus: $emojiPickerAutofocus, emojiPickerKeepOpen: $emojiPickerKeepOpen, dataSaverMedia: $dataSaverMedia, dataSaverAvatar: $dataSaverAvatar, dataSaverUrlPreview: $dataSaverUrlPreview, disableDataSaverWhenOnWifi: $disableDataSaverWhenOnWifi, reduceAnimation: $reduceAnimation, disableShowingAnimatedImages: $disableShowingAnimatedImages, enableEmojiFadeIn: $enableEmojiFadeIn, forceShowAds: $forceShowAds, useGroupedNotifications: $useGroupedNotifications, showTimelineTabBarAtBottom: $showTimelineTabBarAtBottom, showMenuButtonInTabBar: $showMenuButtonInTabBar, timelinesPageButtonTypes: $timelinesPageButtonTypes, showSmallTimelinesPageButtons: $showSmallTimelinesPageButtons, showSquaredTimelinesPageButtons: $showSquaredTimelinesPageButtons, showTabHeaderInOneLine: $showTabHeaderInOneLine, alwaysShowTabHeader: $alwaysShowTabHeader, showTimelineLastViewedAt: $showTimelineLastViewedAt, showPopupOnNewNote: $showPopupOnNewNote, vibrateNote: $vibrateNote, vibrateNotification: $vibrateNotification, enableInfiniteScroll: $enableInfiniteScroll, keepScreenOn: $keepScreenOn, enableHorizontalSwipe: $enableHorizontalSwipe, openSensitiveMediaOnDoubleTap: $openSensitiveMediaOnDoubleTap, noteTapAction: $noteTapAction, noteDoubleTapAction: $noteDoubleTapAction, noteLongPressAction: $noteLongPressAction, confirmBeforePost: $confirmBeforePost, confirmBeforeReact: $confirmBeforeReact, confirmBeforeFollow: $confirmBeforeFollow, confirmWhenRevealingSensitiveMedia: $confirmWhenRevealingSensitiveMedia, launchMode: $launchMode, enablePredictiveBack: $enablePredictiveBack, themeMode: $themeMode, lightThemeId: $lightThemeId, darkThemeId: $darkThemeId)'; + return 'GeneralSettings(locale: $locale, collapseRenotes: $collapseRenotes, sensitive: $sensitive, highlightSensitiveMedia: $highlightSensitiveMedia, animatedMfm: $animatedMfm, advancedMfm: $advancedMfm, showReactionsCount: $showReactionsCount, loadRawImages: $loadRawImages, instanceTicker: $instanceTicker, showNoteCreatedAt: $showNoteCreatedAt, showAvatarsInNote: $showAvatarsInNote, showAvatarsInSubNote: $showAvatarsInSubNote, squareAvatars: $squareAvatars, showAvatarDecorations: $showAvatarDecorations, showQuoteButtonInNoteFooter: $showQuoteButtonInNoteFooter, showLikeButtonInNoteFooter: $showLikeButtonInNoteFooter, showClipButtonInNoteFooter: $showClipButtonInNoteFooter, showTranslateButtonInNoteFooter: $showTranslateButtonInNoteFooter, showNoteReactionsViewer: $showNoteReactionsViewer, showSubNoteReactionsViewer: $showSubNoteReactionsViewer, showNoteFooter: $showNoteFooter, showSubNoteFooter: $showSubNoteFooter, alwaysExpandCw: $alwaysExpandCw, alwaysExpandLongNote: $alwaysExpandLongNote, alwaysExpandMediaInSubNote: $alwaysExpandMediaInSubNote, mergeReactionsByName: $mergeReactionsByName, alwaysShowAllReactions: $alwaysShowAllReactions, mediaListWithOneImageAppearance: $mediaListWithOneImageAppearance, thumbnailBoxFit: $thumbnailBoxFit, emojiStyle: $emojiStyle, fontFamily: $fontFamily, fontSize: $fontSize, lineHeight: $lineHeight, avatarScale: $avatarScale, reactionsDisplayScale: $reactionsDisplayScale, limitWidthOfReaction: $limitWidthOfReaction, noteFooterScale: $noteFooterScale, noteVerticalPadding: $noteVerticalPadding, noteHorizontalPadding: $noteHorizontalPadding, publicNoteBackgroundColor: $publicNoteBackgroundColor, homeNoteBackgroundColor: $homeNoteBackgroundColor, followersNoteBackgroundColor: $followersNoteBackgroundColor, specifiedNoteBackgroundColor: $specifiedNoteBackgroundColor, emojiPickerUseDialog: $emojiPickerUseDialog, emojiPickerScale: $emojiPickerScale, emojiPickerAutofocus: $emojiPickerAutofocus, emojiPickerKeepOpen: $emojiPickerKeepOpen, dataSaverMedia: $dataSaverMedia, dataSaverAvatar: $dataSaverAvatar, dataSaverUrlPreview: $dataSaverUrlPreview, disableDataSaverWhenOnWifi: $disableDataSaverWhenOnWifi, reduceAnimation: $reduceAnimation, disableShowingAnimatedImages: $disableShowingAnimatedImages, enableEmojiFadeIn: $enableEmojiFadeIn, forceShowAds: $forceShowAds, useGroupedNotifications: $useGroupedNotifications, showTimelineTabBarAtBottom: $showTimelineTabBarAtBottom, showMenuButtonInTabBar: $showMenuButtonInTabBar, timelinesPageButtonTypes: $timelinesPageButtonTypes, showSmallTimelinesPageButtons: $showSmallTimelinesPageButtons, showSquaredTimelinesPageButtons: $showSquaredTimelinesPageButtons, showTabHeaderInOneLine: $showTabHeaderInOneLine, alwaysShowTabHeader: $alwaysShowTabHeader, showTimelineLastViewedAt: $showTimelineLastViewedAt, showPopupOnNewNote: $showPopupOnNewNote, vibrateNote: $vibrateNote, vibrateNotification: $vibrateNotification, enableInfiniteScroll: $enableInfiniteScroll, keepScreenOn: $keepScreenOn, enableHorizontalSwipe: $enableHorizontalSwipe, openSensitiveMediaOnDoubleTap: $openSensitiveMediaOnDoubleTap, noteTapAction: $noteTapAction, noteDoubleTapAction: $noteDoubleTapAction, noteLongPressAction: $noteLongPressAction, confirmBeforePost: $confirmBeforePost, confirmBeforeReact: $confirmBeforeReact, confirmBeforeFollow: $confirmBeforeFollow, confirmWhenRevealingSensitiveMedia: $confirmWhenRevealingSensitiveMedia, launchMode: $launchMode, enableSpellCheck: $enableSpellCheck, enablePredictiveBack: $enablePredictiveBack, themeMode: $themeMode, lightThemeId: $lightThemeId, darkThemeId: $darkThemeId)'; } @override @@ -1666,6 +1683,7 @@ class _$GeneralSettingsImpl implements _GeneralSettings { (identical(other.confirmBeforeFollow, confirmBeforeFollow) || other.confirmBeforeFollow == confirmBeforeFollow) && (identical(other.confirmWhenRevealingSensitiveMedia, confirmWhenRevealingSensitiveMedia) || other.confirmWhenRevealingSensitiveMedia == confirmWhenRevealingSensitiveMedia) && (identical(other.launchMode, launchMode) || other.launchMode == launchMode) && + (identical(other.enableSpellCheck, enableSpellCheck) || other.enableSpellCheck == enableSpellCheck) && (identical(other.enablePredictiveBack, enablePredictiveBack) || other.enablePredictiveBack == enablePredictiveBack) && (identical(other.themeMode, themeMode) || other.themeMode == themeMode) && (identical(other.lightThemeId, lightThemeId) || other.lightThemeId == lightThemeId) && @@ -1755,6 +1773,7 @@ class _$GeneralSettingsImpl implements _GeneralSettings { confirmBeforeFollow, confirmWhenRevealingSensitiveMedia, launchMode, + enableSpellCheck, enablePredictiveBack, themeMode, lightThemeId, @@ -1860,6 +1879,7 @@ abstract class _GeneralSettings implements GeneralSettings { final bool confirmBeforeFollow, final bool confirmWhenRevealingSensitiveMedia, final LaunchMode launchMode, + final bool enableSpellCheck, final bool enablePredictiveBack, final ThemeMode themeMode, final String lightThemeId, @@ -2034,6 +2054,8 @@ abstract class _GeneralSettings implements GeneralSettings { @override LaunchMode get launchMode; @override + bool get enableSpellCheck; + @override bool get enablePredictiveBack; // Theme @override ThemeMode get themeMode; diff --git a/lib/model/general_settings.g.dart b/lib/model/general_settings.g.dart index 7f661d15..7909455b 100644 --- a/lib/model/general_settings.g.dart +++ b/lib/model/general_settings.g.dart @@ -139,6 +139,7 @@ _$GeneralSettingsImpl _$$GeneralSettingsImplFromJson( launchMode: $enumDecodeNullable(_$LaunchModeEnumMap, json['launchMode']) ?? LaunchMode.externalApplication, + enableSpellCheck: json['enableSpellCheck'] as bool? ?? false, enablePredictiveBack: json['enablePredictiveBack'] as bool? ?? false, themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ?? ThemeMode.system, @@ -259,6 +260,7 @@ Map _$$GeneralSettingsImplToJson( val['confirmWhenRevealingSensitiveMedia'] = instance.confirmWhenRevealingSensitiveMedia; val['launchMode'] = _$LaunchModeEnumMap[instance.launchMode]!; + val['enableSpellCheck'] = instance.enableSpellCheck; val['enablePredictiveBack'] = instance.enablePredictiveBack; val['themeMode'] = _$ThemeModeEnumMap[instance.themeMode]!; val['lightThemeId'] = instance.lightThemeId; diff --git a/lib/provider/general_settings_notifier_provider.dart b/lib/provider/general_settings_notifier_provider.dart index 196a28f9..1fffb5d0 100644 --- a/lib/provider/general_settings_notifier_provider.dart +++ b/lib/provider/general_settings_notifier_provider.dart @@ -505,6 +505,11 @@ class GeneralSettingsNotifier extends _$GeneralSettingsNotifier { await _save(); } + Future setEnableSpellCheck(bool enableSpellCheck) async { + state = state.copyWith(enableSpellCheck: enableSpellCheck); + await _save(); + } + Future setEnablePredictiveBack(bool enablePredictiveBack) async { state = state.copyWith(enablePredictiveBack: enablePredictiveBack); await _save(); diff --git a/lib/provider/general_settings_notifier_provider.g.dart b/lib/provider/general_settings_notifier_provider.g.dart index 7aab6755..534a6fcb 100644 --- a/lib/provider/general_settings_notifier_provider.g.dart +++ b/lib/provider/general_settings_notifier_provider.g.dart @@ -7,7 +7,7 @@ part of 'general_settings_notifier_provider.dart'; // ************************************************************************** String _$generalSettingsNotifierHash() => - r'c1b2a89a855faad56f65d9fc3c89c60fb23420dc'; + r'a1d4732d1a4e3f12264e37a9bcdb0fd1bd320387'; /// See also [GeneralSettingsNotifier]. @ProviderFor(GeneralSettingsNotifier) diff --git a/lib/view/page/settings/behavior_page.dart b/lib/view/page/settings/behavior_page.dart index 39d15a69..0a8eff9e 100644 --- a/lib/view/page/settings/behavior_page.dart +++ b/lib/view/page/settings/behavior_page.dart @@ -214,6 +214,15 @@ class BehaviorPage extends ConsumerWidget { } }, ), + if (defaultTargetPlatform + case TargetPlatform.android || TargetPlatform.iOS) + SwitchListTile( + title: Text(t.aria.enableSpellCheck), + value: settings.enableSpellCheck, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setEnableSpellCheck(value), + ), if (defaultTargetPlatform == TargetPlatform.android) SwitchListTile( title: Text(t.aria.enablePredictiveBack), diff --git a/lib/view/widget/post_form.dart b/lib/view/widget/post_form.dart index c32488f5..5dd83408 100644 --- a/lib/view/widget/post_form.dart +++ b/lib/view/widget/post_form.dart @@ -257,6 +257,10 @@ class PostForm extends HookConsumerWidget { _ when request.renoteId != null => (t.misskey.quote, Icons.send), _ => (t.misskey.note, Icons.send), }; + final enableSpellCheck = ref.watch( + generalSettingsNotifierProvider + .select((settings) => settings.enableSpellCheck), + ); final useCw = useState(useMemoized(() => request.cw?.isNotEmpty ?? false, [])); final cwController = this.cwController ?? @@ -840,6 +844,9 @@ class PostForm extends HookConsumerWidget { textInputAction: TextInputAction.next, maxLength: (request.cw?.length ?? 0) > 80 ? 100 : null, maxLengthEnforcement: MaxLengthEnforcement.none, + spellCheckConfiguration: enableSpellCheck + ? const SpellCheckConfiguration() + : null, ), ), ), @@ -907,6 +914,8 @@ class PostForm extends HookConsumerWidget { onLiveTextInput: null, anchors: editableTextState.contextMenuAnchors, ), + spellCheckConfiguration: + enableSpellCheck ? const SpellCheckConfiguration() : null, ), ), Padding(