diff --git a/lib/i18n/aria/aria.i18n.yaml b/lib/i18n/aria/aria.i18n.yaml index 2f7174dee..f148bcc12 100644 --- a/lib/i18n/aria/aria.i18n.yaml +++ b/lib/i18n/aria/aria.i18n.yaml @@ -48,6 +48,7 @@ newNotificationReceived: "There are new notifications" noAccounts: "No accounts" noTabs: "No tabs" noteDoubleTapAction: "Note double tap action" +noteFooterSize: "Note action buttons size" noteLongPressAction: "Note long press action" noteTapAction: "Note tap action" notesAfterRenotes: "Notes after renotes" @@ -74,8 +75,9 @@ serverUrl: "Server URL" settingsFileForAria: "Settings file for Aria" settingsForUser(rich): "Settings for {user}" showAvatarsInNote: "Show avatars in notes" +showAvatarsInSubNote: "Show avatars in sub notes" showNoteFooter: "Show action buttons in notes" -showNoteReactionsViewer: "Show reactions viewer in notes" +showNoteReactionsViewer: "Show reactions viewers in notes" showSelfRenotes: "Show self-renotes" showStackTrace: "Show stack trace" showSubNoteFooter: "Show action buttons in subnotes" diff --git a/lib/i18n/aria/aria_ja-JP.i18n.yaml b/lib/i18n/aria/aria_ja-JP.i18n.yaml index 0d16deeb6..1a8371b81 100644 --- a/lib/i18n/aria/aria_ja-JP.i18n.yaml +++ b/lib/i18n/aria/aria_ja-JP.i18n.yaml @@ -44,6 +44,7 @@ newNotificationReceived: "新しい通知があります" noAccounts: "アカウントがありません" noTabs: "タブがありません" noteDoubleTapAction: "ノートをダブルタップしたときの動作" +noteFooterSize: "アクションボタンのサイズ" noteLongPressAction: "ノートを長押ししたときの動作" noteTapAction: "ノートをタップしたときの動作" notesAfterRenotes: "リノート直後のノート" @@ -70,6 +71,7 @@ serverUrl: "サーバーのURL" settingsFileForAria: "Ariaの設定ファイル" settingsForUser(rich): "{user}の設定" showAvatarsInNote: "ノートにユーザーのアイコンを表示する" +showAvatarsInSubNote: "サブノートにユーザーのアイコンを表示する" showNoteFooter: "ノートにアクションボタンを表示する" showNoteReactionsViewer: "ノートにリアクションを表示する" showSelfRenotes: "セルフリノートを表示する" diff --git a/lib/i18n/aria/aria_ja-KS.i18n.yaml b/lib/i18n/aria/aria_ja-KS.i18n.yaml index 23c3df930..637ff93ec 100644 --- a/lib/i18n/aria/aria_ja-KS.i18n.yaml +++ b/lib/i18n/aria/aria_ja-KS.i18n.yaml @@ -44,6 +44,7 @@ newNotificationReceived: "新しい通知があるで" noAccounts: "アカウントはあらへん" noTabs: "タブはあらへん" noteDoubleTapAction: "ノートを二度押ししたときの動作" +noteFooterSize: "アクションボタンのでかさ" noteLongPressAction: "ノートを長押ししたときの動作" noteTapAction: "ノートをいらったときの動作" notesAfterRenotes: "リノート直後のノート" @@ -70,6 +71,7 @@ serverUrl: "サーバーのURL" settingsFileForAria: "Ariaの設定ファイル" settingsForUser(rich): "{user}の設定" showAvatarsInNote: "ノートにユーザーのアイコンを表示するで" +showAvatarsInSubNote: "サブノートにユーザーのアイコンを表示するで" showNoteFooter: "ノートにアクションボタンを表示するで" showNoteReactionsViewer: "ノートにツッコミを表示するで" showSelfRenotes: "セルフリノートを表示するで" diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index 0eb8dd936..16cbd4cd9 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: 50668 (1634 per locale) +/// Strings: 50674 (1634 per locale) // coverage:ignore-file // ignore_for_file: type=lint diff --git a/lib/i18n/strings_en_US.g.dart b/lib/i18n/strings_en_US.g.dart index d8cda555f..0e8f0b991 100644 --- a/lib/i18n/strings_en_US.g.dart +++ b/lib/i18n/strings_en_US.g.dart @@ -108,6 +108,7 @@ class _StringsAriaEnUs { String get noAccounts => 'No accounts'; String get noTabs => 'No tabs'; String get noteDoubleTapAction => 'Note double tap action'; + String get noteFooterSize => 'Note action buttons size'; String get noteLongPressAction => 'Note long press action'; String get noteTapAction => 'Note tap action'; String get notesAfterRenotes => 'Notes after renotes'; @@ -150,8 +151,9 @@ class _StringsAriaEnUs { user, ]); String get showAvatarsInNote => 'Show avatars in notes'; + String get showAvatarsInSubNote => 'Show avatars in sub notes'; String get showNoteFooter => 'Show action buttons in notes'; - String get showNoteReactionsViewer => 'Show reactions viewer in notes'; + String get showNoteReactionsViewer => 'Show reactions viewers in notes'; String get showSelfRenotes => 'Show self-renotes'; String get showStackTrace => 'Show stack trace'; String get showSubNoteFooter => 'Show action buttons in subnotes'; diff --git a/lib/i18n/strings_ja_JP.g.dart b/lib/i18n/strings_ja_JP.g.dart index ad5336dfb..b17448d1b 100644 --- a/lib/i18n/strings_ja_JP.g.dart +++ b/lib/i18n/strings_ja_JP.g.dart @@ -97,6 +97,7 @@ class _StringsAriaJaJp extends _StringsAriaEnUs { @override String get noAccounts => 'アカウントがありません'; @override String get noTabs => 'タブがありません'; @override String get noteDoubleTapAction => 'ノートをダブルタップしたときの動作'; + @override String get noteFooterSize => 'アクションボタンのサイズ'; @override String get noteLongPressAction => 'ノートを長押ししたときの動作'; @override String get noteTapAction => 'ノートをタップしたときの動作'; @override String get notesAfterRenotes => 'リノート直後のノート'; @@ -139,6 +140,7 @@ class _StringsAriaJaJp extends _StringsAriaEnUs { const TextSpan(text: 'の設定'), ]); @override String get showAvatarsInNote => 'ノートにユーザーのアイコンを表示する'; + @override String get showAvatarsInSubNote => 'サブノートにユーザーのアイコンを表示する'; @override String get showNoteFooter => 'ノートにアクションボタンを表示する'; @override String get showNoteReactionsViewer => 'ノートにリアクションを表示する'; @override String get showSelfRenotes => 'セルフリノートを表示する'; diff --git a/lib/i18n/strings_ja_KS.g.dart b/lib/i18n/strings_ja_KS.g.dart index 8e46654c4..740af1a30 100644 --- a/lib/i18n/strings_ja_KS.g.dart +++ b/lib/i18n/strings_ja_KS.g.dart @@ -97,6 +97,7 @@ class _StringsAriaJaKs extends _StringsAriaEnUs { @override String get noAccounts => 'アカウントはあらへん'; @override String get noTabs => 'タブはあらへん'; @override String get noteDoubleTapAction => 'ノートを二度押ししたときの動作'; + @override String get noteFooterSize => 'アクションボタンのでかさ'; @override String get noteLongPressAction => 'ノートを長押ししたときの動作'; @override String get noteTapAction => 'ノートをいらったときの動作'; @override String get notesAfterRenotes => 'リノート直後のノート'; @@ -139,6 +140,7 @@ class _StringsAriaJaKs extends _StringsAriaEnUs { const TextSpan(text: 'の設定'), ]); @override String get showAvatarsInNote => 'ノートにユーザーのアイコンを表示するで'; + @override String get showAvatarsInSubNote => 'サブノートにユーザーのアイコンを表示するで'; @override String get showNoteFooter => 'ノートにアクションボタンを表示するで'; @override String get showNoteReactionsViewer => 'ノートにツッコミを表示するで'; @override String get showSelfRenotes => 'セルフリノートを表示するで'; diff --git a/lib/i18n/strings_map.g.dart b/lib/i18n/strings_map.g.dart index 9e237518d..a13bb7435 100644 --- a/lib/i18n/strings_map.g.dart +++ b/lib/i18n/strings_map.g.dart @@ -72,6 +72,7 @@ extension on Translations { case 'aria.noAccounts': return 'No accounts'; case 'aria.noTabs': return 'No tabs'; case 'aria.noteDoubleTapAction': return 'Note double tap action'; + case 'aria.noteFooterSize': return 'Note action buttons size'; case 'aria.noteLongPressAction': return 'Note long press action'; case 'aria.noteTapAction': return 'Note tap action'; case 'aria.notesAfterRenotes': return 'Notes after renotes'; @@ -114,8 +115,9 @@ extension on Translations { user, ]); case 'aria.showAvatarsInNote': return 'Show avatars in notes'; + case 'aria.showAvatarsInSubNote': return 'Show avatars in sub notes'; case 'aria.showNoteFooter': return 'Show action buttons in notes'; - case 'aria.showNoteReactionsViewer': return 'Show reactions viewer in notes'; + case 'aria.showNoteReactionsViewer': return 'Show reactions viewers in notes'; case 'aria.showSelfRenotes': return 'Show self-renotes'; case 'aria.showStackTrace': return 'Show stack trace'; case 'aria.showSubNoteFooter': return 'Show action buttons in subnotes'; @@ -20954,6 +20956,7 @@ extension on _StringsJaJp { case 'aria.noAccounts': return 'アカウントがありません'; case 'aria.noTabs': return 'タブがありません'; case 'aria.noteDoubleTapAction': return 'ノートをダブルタップしたときの動作'; + case 'aria.noteFooterSize': return 'アクションボタンのサイズ'; case 'aria.noteLongPressAction': return 'ノートを長押ししたときの動作'; case 'aria.noteTapAction': return 'ノートをタップしたときの動作'; case 'aria.notesAfterRenotes': return 'リノート直後のノート'; @@ -20996,6 +20999,7 @@ extension on _StringsJaJp { const TextSpan(text: 'の設定'), ]); case 'aria.showAvatarsInNote': return 'ノートにユーザーのアイコンを表示する'; + case 'aria.showAvatarsInSubNote': return 'サブノートにユーザーのアイコンを表示する'; case 'aria.showNoteFooter': return 'ノートにアクションボタンを表示する'; case 'aria.showNoteReactionsViewer': return 'ノートにリアクションを表示する'; case 'aria.showSelfRenotes': return 'セルフリノートを表示する'; @@ -23436,6 +23440,7 @@ extension on _StringsJaKs { case 'aria.noAccounts': return 'アカウントはあらへん'; case 'aria.noTabs': return 'タブはあらへん'; case 'aria.noteDoubleTapAction': return 'ノートを二度押ししたときの動作'; + case 'aria.noteFooterSize': return 'アクションボタンのでかさ'; case 'aria.noteLongPressAction': return 'ノートを長押ししたときの動作'; case 'aria.noteTapAction': return 'ノートをいらったときの動作'; case 'aria.notesAfterRenotes': return 'リノート直後のノート'; @@ -23478,6 +23483,7 @@ extension on _StringsJaKs { const TextSpan(text: 'の設定'), ]); case 'aria.showAvatarsInNote': return 'ノートにユーザーのアイコンを表示するで'; + case 'aria.showAvatarsInSubNote': return 'サブノートにユーザーのアイコンを表示するで'; case 'aria.showNoteFooter': return 'ノートにアクションボタンを表示するで'; case 'aria.showNoteReactionsViewer': return 'ノートにツッコミを表示するで'; case 'aria.showSelfRenotes': return 'セルフリノートを表示するで'; diff --git a/lib/model/general_settings.dart b/lib/model/general_settings.dart index b36d5764a..63e339e00 100644 --- a/lib/model/general_settings.dart +++ b/lib/model/general_settings.dart @@ -11,6 +11,8 @@ const defaultFontSize = 14.0; const maxFontSize = 24.0; const minReactionsDisplayScale = 0.1; const maxReactionsDisplayScale = 3.0; +const minNoteFooterScale = 0.5; +const maxNoteFooterScale = 2.0; const minEmojiPickerScale = 0.1; const maxEmojiPickerScale = 3.0; @@ -26,7 +28,7 @@ class GeneralSettings with _$GeneralSettings { @Default(true) bool collapseRenotes, @Default(SensitiveMediaDisplay.respect) SensitiveMediaDisplay sensitive, @Default(false) bool highlightSensitiveMedia, - @Default(false) bool animatedMfm, + @Default(true) bool animatedMfm, @Default(true) bool advancedMfm, @Default(false) bool showReactionsCount, @Default(false) bool loadRawImages, @@ -46,14 +48,15 @@ class GeneralSettings with _$GeneralSettings { @Default(false) bool showTranslateButtonInNoteFooter, @Default(defaultFontSize) double fontSize, String? fontFamily, - @Default(true) bool showNoteFooter, + @Default(true) bool showAvatarsInNote, + @Default(true) bool showAvatarsInSubNote, @Default(true) bool showNoteReactionsViewer, - @Default(false) bool showSubNoteFooter, + @Default(true) bool showNoteFooter, @Default(false) bool showSubNoteReactionsViewer, + @Default(false) bool showSubNoteFooter, @Default(false) bool vibrateNote, @Default(false) bool vibrateNotification, @Default(false) bool showTimelineTabBarOnBottom, - @Default(true) bool showAvatarsInNote, @Default(1.0) double noteFooterScale, // Behavior diff --git a/lib/model/general_settings.freezed.dart b/lib/model/general_settings.freezed.dart index fb94c5d50..b0a3023f9 100644 --- a/lib/model/general_settings.freezed.dart +++ b/lib/model/general_settings.freezed.dart @@ -48,14 +48,15 @@ mixin _$GeneralSettings { throw _privateConstructorUsedError; double get fontSize => throw _privateConstructorUsedError; String? get fontFamily => throw _privateConstructorUsedError; - bool get showNoteFooter => throw _privateConstructorUsedError; + bool get showAvatarsInNote => throw _privateConstructorUsedError; + bool get showAvatarsInSubNote => throw _privateConstructorUsedError; bool get showNoteReactionsViewer => throw _privateConstructorUsedError; - bool get showSubNoteFooter => throw _privateConstructorUsedError; + bool get showNoteFooter => throw _privateConstructorUsedError; bool get showSubNoteReactionsViewer => throw _privateConstructorUsedError; + bool get showSubNoteFooter => throw _privateConstructorUsedError; bool get vibrateNote => throw _privateConstructorUsedError; bool get vibrateNotification => throw _privateConstructorUsedError; bool get showTimelineTabBarOnBottom => throw _privateConstructorUsedError; - bool get showAvatarsInNote => throw _privateConstructorUsedError; double get noteFooterScale => throw _privateConstructorUsedError; // Behavior bool get enableInfiniteScroll => throw _privateConstructorUsedError; bool get keepScreenOn => throw _privateConstructorUsedError; @@ -109,14 +110,15 @@ abstract class $GeneralSettingsCopyWith<$Res> { bool showTranslateButtonInNoteFooter, double fontSize, String? fontFamily, - bool showNoteFooter, + bool showAvatarsInNote, + bool showAvatarsInSubNote, bool showNoteReactionsViewer, - bool showSubNoteFooter, + bool showNoteFooter, bool showSubNoteReactionsViewer, + bool showSubNoteFooter, bool vibrateNote, bool vibrateNotification, bool showTimelineTabBarOnBottom, - bool showAvatarsInNote, double noteFooterScale, bool enableInfiniteScroll, bool keepScreenOn, @@ -170,14 +172,15 @@ class _$GeneralSettingsCopyWithImpl<$Res, $Val extends GeneralSettings> Object? showTranslateButtonInNoteFooter = null, Object? fontSize = null, Object? fontFamily = freezed, - Object? showNoteFooter = null, + Object? showAvatarsInNote = null, + Object? showAvatarsInSubNote = null, Object? showNoteReactionsViewer = null, - Object? showSubNoteFooter = null, + Object? showNoteFooter = null, Object? showSubNoteReactionsViewer = null, + Object? showSubNoteFooter = null, Object? vibrateNote = null, Object? vibrateNotification = null, Object? showTimelineTabBarOnBottom = null, - Object? showAvatarsInNote = null, Object? noteFooterScale = null, Object? enableInfiniteScroll = null, Object? keepScreenOn = null, @@ -290,22 +293,30 @@ class _$GeneralSettingsCopyWithImpl<$Res, $Val extends GeneralSettings> ? _value.fontFamily : fontFamily // ignore: cast_nullable_to_non_nullable as String?, - showNoteFooter: null == showNoteFooter - ? _value.showNoteFooter - : showNoteFooter // ignore: cast_nullable_to_non_nullable + showAvatarsInNote: null == showAvatarsInNote + ? _value.showAvatarsInNote + : showAvatarsInNote // ignore: cast_nullable_to_non_nullable + as bool, + showAvatarsInSubNote: null == showAvatarsInSubNote + ? _value.showAvatarsInSubNote + : showAvatarsInSubNote // ignore: cast_nullable_to_non_nullable as bool, showNoteReactionsViewer: null == showNoteReactionsViewer ? _value.showNoteReactionsViewer : showNoteReactionsViewer // ignore: cast_nullable_to_non_nullable as bool, - showSubNoteFooter: null == showSubNoteFooter - ? _value.showSubNoteFooter - : showSubNoteFooter // ignore: cast_nullable_to_non_nullable + showNoteFooter: null == showNoteFooter + ? _value.showNoteFooter + : showNoteFooter // ignore: cast_nullable_to_non_nullable as bool, showSubNoteReactionsViewer: null == showSubNoteReactionsViewer ? _value.showSubNoteReactionsViewer : showSubNoteReactionsViewer // ignore: cast_nullable_to_non_nullable as bool, + showSubNoteFooter: null == showSubNoteFooter + ? _value.showSubNoteFooter + : showSubNoteFooter // ignore: cast_nullable_to_non_nullable + as bool, vibrateNote: null == vibrateNote ? _value.vibrateNote : vibrateNote // ignore: cast_nullable_to_non_nullable @@ -318,10 +329,6 @@ class _$GeneralSettingsCopyWithImpl<$Res, $Val extends GeneralSettings> ? _value.showTimelineTabBarOnBottom : showTimelineTabBarOnBottom // ignore: cast_nullable_to_non_nullable as bool, - showAvatarsInNote: null == showAvatarsInNote - ? _value.showAvatarsInNote - : showAvatarsInNote // ignore: cast_nullable_to_non_nullable - as bool, noteFooterScale: null == noteFooterScale ? _value.noteFooterScale : noteFooterScale // ignore: cast_nullable_to_non_nullable @@ -416,14 +423,15 @@ abstract class _$$GeneralSettingsImplCopyWith<$Res> bool showTranslateButtonInNoteFooter, double fontSize, String? fontFamily, - bool showNoteFooter, + bool showAvatarsInNote, + bool showAvatarsInSubNote, bool showNoteReactionsViewer, - bool showSubNoteFooter, + bool showNoteFooter, bool showSubNoteReactionsViewer, + bool showSubNoteFooter, bool vibrateNote, bool vibrateNotification, bool showTimelineTabBarOnBottom, - bool showAvatarsInNote, double noteFooterScale, bool enableInfiniteScroll, bool keepScreenOn, @@ -475,14 +483,15 @@ class __$$GeneralSettingsImplCopyWithImpl<$Res> Object? showTranslateButtonInNoteFooter = null, Object? fontSize = null, Object? fontFamily = freezed, - Object? showNoteFooter = null, + Object? showAvatarsInNote = null, + Object? showAvatarsInSubNote = null, Object? showNoteReactionsViewer = null, - Object? showSubNoteFooter = null, + Object? showNoteFooter = null, Object? showSubNoteReactionsViewer = null, + Object? showSubNoteFooter = null, Object? vibrateNote = null, Object? vibrateNotification = null, Object? showTimelineTabBarOnBottom = null, - Object? showAvatarsInNote = null, Object? noteFooterScale = null, Object? enableInfiniteScroll = null, Object? keepScreenOn = null, @@ -595,22 +604,30 @@ class __$$GeneralSettingsImplCopyWithImpl<$Res> ? _value.fontFamily : fontFamily // ignore: cast_nullable_to_non_nullable as String?, - showNoteFooter: null == showNoteFooter - ? _value.showNoteFooter - : showNoteFooter // ignore: cast_nullable_to_non_nullable + showAvatarsInNote: null == showAvatarsInNote + ? _value.showAvatarsInNote + : showAvatarsInNote // ignore: cast_nullable_to_non_nullable + as bool, + showAvatarsInSubNote: null == showAvatarsInSubNote + ? _value.showAvatarsInSubNote + : showAvatarsInSubNote // ignore: cast_nullable_to_non_nullable as bool, showNoteReactionsViewer: null == showNoteReactionsViewer ? _value.showNoteReactionsViewer : showNoteReactionsViewer // ignore: cast_nullable_to_non_nullable as bool, - showSubNoteFooter: null == showSubNoteFooter - ? _value.showSubNoteFooter - : showSubNoteFooter // ignore: cast_nullable_to_non_nullable + showNoteFooter: null == showNoteFooter + ? _value.showNoteFooter + : showNoteFooter // ignore: cast_nullable_to_non_nullable as bool, showSubNoteReactionsViewer: null == showSubNoteReactionsViewer ? _value.showSubNoteReactionsViewer : showSubNoteReactionsViewer // ignore: cast_nullable_to_non_nullable as bool, + showSubNoteFooter: null == showSubNoteFooter + ? _value.showSubNoteFooter + : showSubNoteFooter // ignore: cast_nullable_to_non_nullable + as bool, vibrateNote: null == vibrateNote ? _value.vibrateNote : vibrateNote // ignore: cast_nullable_to_non_nullable @@ -623,10 +640,6 @@ class __$$GeneralSettingsImplCopyWithImpl<$Res> ? _value.showTimelineTabBarOnBottom : showTimelineTabBarOnBottom // ignore: cast_nullable_to_non_nullable as bool, - showAvatarsInNote: null == showAvatarsInNote - ? _value.showAvatarsInNote - : showAvatarsInNote // ignore: cast_nullable_to_non_nullable - as bool, noteFooterScale: null == noteFooterScale ? _value.noteFooterScale : noteFooterScale // ignore: cast_nullable_to_non_nullable @@ -696,7 +709,7 @@ class _$GeneralSettingsImpl implements _GeneralSettings { this.collapseRenotes = true, this.sensitive = SensitiveMediaDisplay.respect, this.highlightSensitiveMedia = false, - this.animatedMfm = false, + this.animatedMfm = true, this.advancedMfm = true, this.showReactionsCount = false, this.loadRawImages = false, @@ -716,14 +729,15 @@ class _$GeneralSettingsImpl implements _GeneralSettings { this.showTranslateButtonInNoteFooter = false, this.fontSize = defaultFontSize, this.fontFamily, - this.showNoteFooter = true, + this.showAvatarsInNote = true, + this.showAvatarsInSubNote = true, this.showNoteReactionsViewer = true, - this.showSubNoteFooter = false, + this.showNoteFooter = true, this.showSubNoteReactionsViewer = false, + this.showSubNoteFooter = false, this.vibrateNote = false, this.vibrateNotification = false, this.showTimelineTabBarOnBottom = false, - this.showAvatarsInNote = true, this.noteFooterScale = 1.0, this.enableInfiniteScroll = true, this.keepScreenOn = false, @@ -818,18 +832,24 @@ class _$GeneralSettingsImpl implements _GeneralSettings { final String? fontFamily; @override @JsonKey() - final bool showNoteFooter; + final bool showAvatarsInNote; + @override + @JsonKey() + final bool showAvatarsInSubNote; @override @JsonKey() final bool showNoteReactionsViewer; @override @JsonKey() - final bool showSubNoteFooter; + final bool showNoteFooter; @override @JsonKey() final bool showSubNoteReactionsViewer; @override @JsonKey() + final bool showSubNoteFooter; + @override + @JsonKey() final bool vibrateNote; @override @JsonKey() @@ -839,9 +859,6 @@ class _$GeneralSettingsImpl implements _GeneralSettings { final bool showTimelineTabBarOnBottom; @override @JsonKey() - final bool showAvatarsInNote; - @override - @JsonKey() final double noteFooterScale; // Behavior @override @@ -887,7 +904,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, emojiStyle: $emojiStyle, emojiPickerUseDialog: $emojiPickerUseDialog, emojiPickerScale: $emojiPickerScale, emojiPickerAutofocus: $emojiPickerAutofocus, squareAvatars: $squareAvatars, showAvatarDecorations: $showAvatarDecorations, showClipButtonInNoteFooter: $showClipButtonInNoteFooter, reactionsDisplayScale: $reactionsDisplayScale, limitWidthOfReaction: $limitWidthOfReaction, forceShowAds: $forceShowAds, useGroupedNotifications: $useGroupedNotifications, dataSaverMedia: $dataSaverMedia, dataSaverUrlPreview: $dataSaverUrlPreview, showTranslateButtonInNoteFooter: $showTranslateButtonInNoteFooter, fontSize: $fontSize, fontFamily: $fontFamily, showNoteFooter: $showNoteFooter, showNoteReactionsViewer: $showNoteReactionsViewer, showSubNoteFooter: $showSubNoteFooter, showSubNoteReactionsViewer: $showSubNoteReactionsViewer, vibrateNote: $vibrateNote, vibrateNotification: $vibrateNotification, showTimelineTabBarOnBottom: $showTimelineTabBarOnBottom, showAvatarsInNote: $showAvatarsInNote, noteFooterScale: $noteFooterScale, enableInfiniteScroll: $enableInfiniteScroll, keepScreenOn: $keepScreenOn, enableHorizontalSwipe: $enableHorizontalSwipe, openSensitiveMediaOnDoubleTap: $openSensitiveMediaOnDoubleTap, noteTapAction: $noteTapAction, noteDoubleTapAction: $noteDoubleTapAction, noteLongPressAction: $noteLongPressAction, confirmBeforePost: $confirmBeforePost, confirmBeforeReact: $confirmBeforeReact, confirmBeforeFollow: $confirmBeforeFollow, themeMode: $themeMode, lightThemeId: $lightThemeId, darkThemeId: $darkThemeId)'; + return 'GeneralSettings(locale: $locale, collapseRenotes: $collapseRenotes, sensitive: $sensitive, highlightSensitiveMedia: $highlightSensitiveMedia, animatedMfm: $animatedMfm, advancedMfm: $advancedMfm, showReactionsCount: $showReactionsCount, loadRawImages: $loadRawImages, emojiStyle: $emojiStyle, emojiPickerUseDialog: $emojiPickerUseDialog, emojiPickerScale: $emojiPickerScale, emojiPickerAutofocus: $emojiPickerAutofocus, squareAvatars: $squareAvatars, showAvatarDecorations: $showAvatarDecorations, showClipButtonInNoteFooter: $showClipButtonInNoteFooter, reactionsDisplayScale: $reactionsDisplayScale, limitWidthOfReaction: $limitWidthOfReaction, forceShowAds: $forceShowAds, useGroupedNotifications: $useGroupedNotifications, dataSaverMedia: $dataSaverMedia, dataSaverUrlPreview: $dataSaverUrlPreview, showTranslateButtonInNoteFooter: $showTranslateButtonInNoteFooter, fontSize: $fontSize, fontFamily: $fontFamily, showAvatarsInNote: $showAvatarsInNote, showAvatarsInSubNote: $showAvatarsInSubNote, showNoteReactionsViewer: $showNoteReactionsViewer, showNoteFooter: $showNoteFooter, showSubNoteReactionsViewer: $showSubNoteReactionsViewer, showSubNoteFooter: $showSubNoteFooter, vibrateNote: $vibrateNote, vibrateNotification: $vibrateNotification, showTimelineTabBarOnBottom: $showTimelineTabBarOnBottom, noteFooterScale: $noteFooterScale, enableInfiniteScroll: $enableInfiniteScroll, keepScreenOn: $keepScreenOn, enableHorizontalSwipe: $enableHorizontalSwipe, openSensitiveMediaOnDoubleTap: $openSensitiveMediaOnDoubleTap, noteTapAction: $noteTapAction, noteDoubleTapAction: $noteDoubleTapAction, noteLongPressAction: $noteLongPressAction, confirmBeforePost: $confirmBeforePost, confirmBeforeReact: $confirmBeforeReact, confirmBeforeFollow: $confirmBeforeFollow, themeMode: $themeMode, lightThemeId: $lightThemeId, darkThemeId: $darkThemeId)'; } @override @@ -944,19 +961,20 @@ class _$GeneralSettingsImpl implements _GeneralSettings { other.fontSize == fontSize) && (identical(other.fontFamily, fontFamily) || other.fontFamily == fontFamily) && - (identical(other.showNoteFooter, showNoteFooter) || - other.showNoteFooter == showNoteFooter) && + (identical(other.showAvatarsInNote, showAvatarsInNote) || + other.showAvatarsInNote == showAvatarsInNote) && + (identical(other.showAvatarsInSubNote, showAvatarsInSubNote) || + other.showAvatarsInSubNote == showAvatarsInSubNote) && (identical(other.showNoteReactionsViewer, showNoteReactionsViewer) || other.showNoteReactionsViewer == showNoteReactionsViewer) && - (identical(other.showSubNoteFooter, showSubNoteFooter) || - other.showSubNoteFooter == showSubNoteFooter) && + (identical(other.showNoteFooter, showNoteFooter) || + other.showNoteFooter == showNoteFooter) && (identical(other.showSubNoteReactionsViewer, showSubNoteReactionsViewer) || - other.showSubNoteReactionsViewer == - showSubNoteReactionsViewer) && + other.showSubNoteReactionsViewer == showSubNoteReactionsViewer) && + (identical(other.showSubNoteFooter, showSubNoteFooter) || other.showSubNoteFooter == showSubNoteFooter) && (identical(other.vibrateNote, vibrateNote) || other.vibrateNote == vibrateNote) && (identical(other.vibrateNotification, vibrateNotification) || other.vibrateNotification == vibrateNotification) && (identical(other.showTimelineTabBarOnBottom, showTimelineTabBarOnBottom) || other.showTimelineTabBarOnBottom == showTimelineTabBarOnBottom) && - (identical(other.showAvatarsInNote, showAvatarsInNote) || other.showAvatarsInNote == showAvatarsInNote) && (identical(other.noteFooterScale, noteFooterScale) || other.noteFooterScale == noteFooterScale) && (identical(other.enableInfiniteScroll, enableInfiniteScroll) || other.enableInfiniteScroll == enableInfiniteScroll) && (identical(other.keepScreenOn, keepScreenOn) || other.keepScreenOn == keepScreenOn) && @@ -1001,14 +1019,15 @@ class _$GeneralSettingsImpl implements _GeneralSettings { showTranslateButtonInNoteFooter, fontSize, fontFamily, - showNoteFooter, + showAvatarsInNote, + showAvatarsInSubNote, showNoteReactionsViewer, - showSubNoteFooter, + showNoteFooter, showSubNoteReactionsViewer, + showSubNoteFooter, vibrateNote, vibrateNotification, showTimelineTabBarOnBottom, - showAvatarsInNote, noteFooterScale, enableInfiniteScroll, keepScreenOn, @@ -1067,14 +1086,15 @@ abstract class _GeneralSettings implements GeneralSettings { final bool showTranslateButtonInNoteFooter, final double fontSize, final String? fontFamily, - final bool showNoteFooter, + final bool showAvatarsInNote, + final bool showAvatarsInSubNote, final bool showNoteReactionsViewer, - final bool showSubNoteFooter, + final bool showNoteFooter, final bool showSubNoteReactionsViewer, + final bool showSubNoteFooter, final bool vibrateNote, final bool vibrateNotification, final bool showTimelineTabBarOnBottom, - final bool showAvatarsInNote, final double noteFooterScale, final bool enableInfiniteScroll, final bool keepScreenOn, @@ -1144,22 +1164,24 @@ abstract class _GeneralSettings implements GeneralSettings { @override String? get fontFamily; @override - bool get showNoteFooter; + bool get showAvatarsInNote; + @override + bool get showAvatarsInSubNote; @override bool get showNoteReactionsViewer; @override - bool get showSubNoteFooter; + bool get showNoteFooter; @override bool get showSubNoteReactionsViewer; @override + bool get showSubNoteFooter; + @override bool get vibrateNote; @override bool get vibrateNotification; @override bool get showTimelineTabBarOnBottom; @override - bool get showAvatarsInNote; - @override double get noteFooterScale; @override // Behavior bool get enableInfiniteScroll; diff --git a/lib/model/general_settings.g.dart b/lib/model/general_settings.g.dart index d11727dfd..1bebe9e43 100644 --- a/lib/model/general_settings.g.dart +++ b/lib/model/general_settings.g.dart @@ -17,7 +17,7 @@ _$GeneralSettingsImpl _$$GeneralSettingsImplFromJson( SensitiveMediaDisplay.respect, highlightSensitiveMedia: json['highlightSensitiveMedia'] as bool? ?? false, - animatedMfm: json['animatedMfm'] as bool? ?? false, + animatedMfm: json['animatedMfm'] as bool? ?? true, advancedMfm: json['advancedMfm'] as bool? ?? true, showReactionsCount: json['showReactionsCount'] as bool? ?? false, loadRawImages: json['loadRawImages'] as bool? ?? false, @@ -43,16 +43,17 @@ _$GeneralSettingsImpl _$$GeneralSettingsImplFromJson( json['showTranslateButtonInNoteFooter'] as bool? ?? false, fontSize: (json['fontSize'] as num?)?.toDouble() ?? defaultFontSize, fontFamily: json['fontFamily'] as String?, - showNoteFooter: json['showNoteFooter'] as bool? ?? true, + showAvatarsInNote: json['showAvatarsInNote'] as bool? ?? true, + showAvatarsInSubNote: json['showAvatarsInSubNote'] as bool? ?? true, showNoteReactionsViewer: json['showNoteReactionsViewer'] as bool? ?? true, - showSubNoteFooter: json['showSubNoteFooter'] as bool? ?? false, + showNoteFooter: json['showNoteFooter'] as bool? ?? true, showSubNoteReactionsViewer: json['showSubNoteReactionsViewer'] as bool? ?? false, + showSubNoteFooter: json['showSubNoteFooter'] as bool? ?? false, vibrateNote: json['vibrateNote'] as bool? ?? false, vibrateNotification: json['vibrateNotification'] as bool? ?? false, showTimelineTabBarOnBottom: json['showTimelineTabBarOnBottom'] as bool? ?? false, - showAvatarsInNote: json['showAvatarsInNote'] as bool? ?? true, noteFooterScale: (json['noteFooterScale'] as num?)?.toDouble() ?? 1.0, enableInfiniteScroll: json['enableInfiniteScroll'] as bool? ?? true, keepScreenOn: json['keepScreenOn'] as bool? ?? false, @@ -114,14 +115,15 @@ Map _$$GeneralSettingsImplToJson( instance.showTranslateButtonInNoteFooter; val['fontSize'] = instance.fontSize; writeNotNull('fontFamily', instance.fontFamily); - val['showNoteFooter'] = instance.showNoteFooter; + val['showAvatarsInNote'] = instance.showAvatarsInNote; + val['showAvatarsInSubNote'] = instance.showAvatarsInSubNote; val['showNoteReactionsViewer'] = instance.showNoteReactionsViewer; - val['showSubNoteFooter'] = instance.showSubNoteFooter; + val['showNoteFooter'] = instance.showNoteFooter; val['showSubNoteReactionsViewer'] = instance.showSubNoteReactionsViewer; + val['showSubNoteFooter'] = instance.showSubNoteFooter; val['vibrateNote'] = instance.vibrateNote; val['vibrateNotification'] = instance.vibrateNotification; val['showTimelineTabBarOnBottom'] = instance.showTimelineTabBarOnBottom; - val['showAvatarsInNote'] = instance.showAvatarsInNote; val['noteFooterScale'] = instance.noteFooterScale; val['enableInfiniteScroll'] = instance.enableInfiniteScroll; val['keepScreenOn'] = instance.keepScreenOn; diff --git a/lib/provider/general_settings_notifier_provider.dart b/lib/provider/general_settings_notifier_provider.dart index 3a1eacad0..964d06a6a 100644 --- a/lib/provider/general_settings_notifier_provider.dart +++ b/lib/provider/general_settings_notifier_provider.dart @@ -101,6 +101,11 @@ class GeneralSettingsNotifier extends _$GeneralSettingsNotifier { await _save(); } + Future setShowAvatarsInSubNote(bool showAvatarsInSubNote) async { + state = state.copyWith(showAvatarsInSubNote: showAvatarsInSubNote); + await _save(); + } + Future setSquareAvatars(bool squareAvatars) async { state = state.copyWith(squareAvatars: squareAvatars); await _save(); diff --git a/lib/provider/general_settings_notifier_provider.g.dart b/lib/provider/general_settings_notifier_provider.g.dart index d1a546b7d..036318933 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'173d9d4df1574cc5bec45addaeaec6802e68ba57'; + r'4f9f601fc09d4e4e7e3af0bb1fe605ce5450e80b'; /// See also [GeneralSettingsNotifier]. @ProviderFor(GeneralSettingsNotifier) diff --git a/lib/router/router.dart b/lib/router/router.dart index 0fa0f1ebe..f30cfe04c 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -54,6 +54,7 @@ import '../view/page/settings/import_export_page.dart'; import '../view/page/settings/languages_page.dart'; import '../view/page/settings/mute_block_page.dart'; import '../view/page/settings/muted_users_page.dart'; +import '../view/page/settings/note_display_page.dart'; import '../view/page/settings/privacy_page.dart'; import '../view/page/settings/profile_page.dart'; import '../view/page/settings/renote_muted_users_page.dart'; @@ -218,6 +219,10 @@ GoRouter router(RouterRef ref) { path: 'language', builder: (_, __) => const LanguagesPage(), ), + GoRoute( + path: 'note-display', + builder: (_, __) => const NoteDisplayPage(), + ), GoRoute( path: 'tab', builder: (_, __) => const TabsPage(), diff --git a/lib/router/router.g.dart b/lib/router/router.g.dart index e83b462a3..9d4d75b5d 100644 --- a/lib/router/router.g.dart +++ b/lib/router/router.g.dart @@ -6,7 +6,7 @@ part of 'router.dart'; // RiverpodGenerator // ************************************************************************** -String _$routerHash() => r'dda3bfab936632ea8eba82896c128d90ac9c20c2'; +String _$routerHash() => r'5861214ca249d2fe8e59c9a6742deeff7fde8b21'; /// See also [router]. @ProviderFor(router) diff --git a/lib/util/get_note_action.dart b/lib/util/get_note_action.dart index d84e91727..26fe8d48d 100644 --- a/lib/util/get_note_action.dart +++ b/lib/util/get_note_action.dart @@ -19,6 +19,9 @@ void Function()? getNoteAction( required Note note, required Note appearNote, }) { + if (note.id.isEmpty) { + return null; + } return switch (type) { NoteActionType.none => null, NoteActionType.expand => () => diff --git a/lib/view/dialog/post_confirmation_dialog.dart b/lib/view/dialog/post_confirmation_dialog.dart index 87da3b669..4f1e39397 100644 --- a/lib/view/dialog/post_confirmation_dialog.dart +++ b/lib/view/dialog/post_confirmation_dialog.dart @@ -5,7 +5,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../../extension/notes_create_request_extension.dart'; import '../../i18n/strings.g.dart'; import '../../model/account.dart'; -import '../../model/general_settings.dart'; import '../../model/post_file.dart'; import '../../provider/api/attaches_notifier_provider.dart'; import '../../provider/api/i_notifier_provider.dart'; @@ -63,9 +62,6 @@ class PostConfirmationDialog extends ConsumerWidget { noteId: '', note: note.copyWith(files: files), showFooter: false, - tapAction: NoteActionType.none, - doubleTapAction: NoteActionType.none, - longPressAction: NoteActionType.none, ), Align( alignment: Alignment.centerRight, diff --git a/lib/view/page/post_page.dart b/lib/view/page/post_page.dart index cdd9418f9..92f7e6cff 100644 --- a/lib/view/page/post_page.dart +++ b/lib/view/page/post_page.dart @@ -17,7 +17,6 @@ import '../../extension/text_editing_controller_extension.dart'; import '../../extension/user_extension.dart'; import '../../i18n/strings.g.dart'; import '../../model/account.dart'; -import '../../model/general_settings.dart'; import '../../model/post_file.dart'; import '../../provider/account_settings_notifier_provider.dart'; import '../../provider/accounts_notifier_provider.dart'; @@ -905,9 +904,6 @@ class PostPage extends HookConsumerWidget { noteId: '', note: note, showFooter: false, - tapAction: NoteActionType.none, - doubleTapAction: NoteActionType.none, - longPressAction: NoteActionType.none, ), ], ), diff --git a/lib/view/page/settings/appearance_page.dart b/lib/view/page/settings/appearance_page.dart index fc25beaef..56f4d1743 100644 --- a/lib/view/page/settings/appearance_page.dart +++ b/lib/view/page/settings/appearance_page.dart @@ -1,18 +1,13 @@ import 'dart:ui'; -import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../../../constant/default_pinned_emojis.dart'; -import '../../../gen/fonts.gen.dart'; import '../../../i18n/strings.g.dart'; -import '../../../model/account.dart'; import '../../../model/general_settings.dart'; import '../../../provider/general_settings_notifier_provider.dart'; -import '../../dialog/radio_dialog.dart'; -import '../../widget/reaction_button.dart'; import '../../widget/unicode_emoji.dart'; class AppearancePage extends HookConsumerWidget { @@ -21,20 +16,6 @@ class AppearancePage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final settings = ref.watch(generalSettingsNotifierProvider); - final fontSize = useState( - clampDouble( - settings.fontSize, - minFontSize, - maxFontSize, - ), - ); - final reactionsDisplayScale = useState( - clampDouble( - settings.reactionsDisplayScale, - minReactionsDisplayScale, - maxReactionsDisplayScale, - ), - ); final emojiPickerScale = useState( clampDouble( settings.emojiPickerScale, @@ -47,291 +28,6 @@ class AppearancePage extends HookConsumerWidget { appBar: AppBar(title: Text(t.misskey.appearance)), body: ListView( children: [ - Padding( - padding: const EdgeInsets.only(left: 16.0), - child: Text( - t.misskey.displayOfNote, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.8), - ), - ), - ), - SwitchListTile( - title: Text(t.misskey.collapseRenotes), - value: settings.collapseRenotes, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setCollapseRenotes(value), - ), - ListTile( - title: Text(t.misskey.displayOfSensitiveMedia), - subtitle: Text( - switch (settings.sensitive) { - SensitiveMediaDisplay.respect => - t.misskey.displayOfSensitiveMedia_.respect, - SensitiveMediaDisplay.ignore => - t.misskey.displayOfSensitiveMedia_.ignore, - SensitiveMediaDisplay.force => - t.misskey.displayOfSensitiveMedia_.force, - }, - ), - trailing: const Icon(Icons.navigate_next), - onTap: () async { - final result = await showRadioDialog( - context, - title: Text(t.misskey.displayOfSensitiveMedia), - values: SensitiveMediaDisplay.values, - initialValue: settings.sensitive, - itemBuilder: (context, value) => Text( - switch (value) { - SensitiveMediaDisplay.respect => - t.misskey.displayOfSensitiveMedia_.respect, - SensitiveMediaDisplay.ignore => - t.misskey.displayOfSensitiveMedia_.ignore, - SensitiveMediaDisplay.force => - t.misskey.displayOfSensitiveMedia_.force, - }, - ), - ); - if (result != null) { - await ref - .read(generalSettingsNotifierProvider.notifier) - .setSensitive(result); - } - }, - ), - SwitchListTile( - title: Text(t.misskey.highlightSensitiveMedia), - value: settings.highlightSensitiveMedia, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setHighlightSensitiveMedia(value), - ), - SwitchListTile( - title: Text(t.misskey.enableAnimatedMfm), - value: settings.animatedMfm, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setAnimatedMfm(value), - ), - SwitchListTile( - title: Text(t.misskey.enableAdvancedMfm), - value: settings.advancedMfm, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setAdvancedMfm(value), - ), - // TODO: Update localization - // SwitchListTile( - // title: Text(t.misskey.showReactionsCount), - // value: settings.showReactionsCount, - // onChanged: (value) => ref - // .read(generalSettingsNotifierProvider.notifier) - // .setShowReactionsCount(value), - // ), - SwitchListTile( - title: Text(t.misskey.loadRawImages), - value: settings.loadRawImages, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setLoadRawImages(value), - ), - ListTile( - title: Text(t.misskey.emojiStyle), - subtitle: Text( - switch (settings.emojiStyle) { - EmojiStyle.native => t.misskey.native, - EmojiStyle.twemoji => 'Twemoji', - }, - ), - trailing: const Icon(Icons.navigate_next), - onTap: () async { - final result = await showRadioDialog( - context, - title: Text(t.misskey.emojiStyle), - values: EmojiStyle.values, - initialValue: settings.emojiStyle, - itemBuilder: (context, value) => Text( - switch (value) { - EmojiStyle.native => t.misskey.native, - EmojiStyle.twemoji => 'Twemoji', - }, - ), - ); - if (result != null) { - await ref - .read(generalSettingsNotifierProvider.notifier) - .setEmojiStyle(result); - } - }, - ), - SwitchListTile( - title: Text(t.aria.showAvatarsInNote), - value: settings.showAvatarsInNote, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setShowAvatarsInNote(value), - ), - SwitchListTile( - title: Text(t.misskey.squareAvatars), - value: settings.squareAvatars, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setSquareAvatars(value), - ), - SwitchListTile( - title: Text(t.misskey.showAvatarDecorations), - value: settings.showAvatarDecorations, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setShowAvatarDecorations(value), - ), - SwitchListTile( - title: Text(t.misskey.showClipButtonInNoteFooter), - value: settings.showClipButtonInNoteFooter, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setShowClipButtonInNoteFooter(value), - ), - SwitchListTile( - title: Text(t.aria.showTranslateButtonInNoteFooter), - value: settings.showTranslateButtonInNoteFooter, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setShowTranslateButtonInNoteFooter(value), - ), - SwitchListTile( - title: Text(t.aria.showNoteFooter), - value: settings.showNoteFooter, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setShowNoteFooter(value), - ), - SwitchListTile( - title: Text(t.aria.showNoteReactionsViewer), - value: settings.showNoteReactionsViewer, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setShowNoteReactionsViewer(value), - ), - SwitchListTile( - title: Text(t.aria.showSubNoteFooter), - value: settings.showSubNoteFooter, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setShowSubNoteFooter(value), - ), - SwitchListTile( - title: Text(t.aria.showSubNoteReactionsViewer), - value: settings.showSubNoteReactionsViewer, - onChanged: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setShowSubNoteReactionsViewer(value), - ), - ListTile( - title: Text(t.aria.font), - subtitle: Text(settings.fontFamily ?? t.misskey.system), - trailing: const Icon(Icons.navigate_next), - onTap: () async { - final result = await showRadioDialog( - context, - title: Text(t.aria.font), - values: [ - (null,), - (FontFamily.bIZUDGothic,), - (FontFamily.bIZUDMincho,), - (FontFamily.mPlus1,), - (FontFamily.mPlus2,), - (FontFamily.notoSansJP,), - (FontFamily.notoSansKR,), - (FontFamily.notoSansSC,), - (FontFamily.notoSansTC,), - (FontFamily.notoSerifJP,), - (FontFamily.nunito,), - (FontFamily.pretendard,), - ], - initialValue: (settings.fontFamily,), - itemBuilder: (context, value) => Text( - value.$1 ?? t.misskey.system, - style: TextStyle(fontFamily: value.$1), - ), - ); - if (result != null) { - await ref - .read(generalSettingsNotifierProvider.notifier) - .setFontFamily(result.$1); - } - }, - ), - ListTile( - title: Text(t.misskey.fontSize), - subtitle: Slider( - value: fontSize.value, - min: minFontSize, - max: maxFontSize, - label: fontSize.value.toStringAsFixed(1), - onChanged: (value) => fontSize.value = value, - onChangeEnd: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setFontSize(value), - ), - trailing: IconButton( - onPressed: () { - fontSize.value = defaultFontSize; - ref - .read(generalSettingsNotifierProvider.notifier) - .setFontSize(defaultFontSize); - }, - icon: const Icon(Icons.refresh), - ), - ), - ListTile( - title: Text(t.misskey.reactionsDisplaySize), - subtitle: Slider( - value: reactionsDisplayScale.value, - min: minReactionsDisplayScale, - max: maxReactionsDisplayScale, - label: reactionsDisplayScale.value.toStringAsFixed(3), - onChanged: (value) => reactionsDisplayScale.value = value, - onChangeEnd: (value) => ref - .read(generalSettingsNotifierProvider.notifier) - .setReactionsDisplayScale(value), - ), - trailing: IconButton( - onPressed: () { - reactionsDisplayScale.value = 1.0; - ref - .read(generalSettingsNotifierProvider.notifier) - .setReactionsDisplayScale(1.0); - }, - icon: const Icon(Icons.refresh), - ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Wrap( - spacing: 4.0, - runSpacing: 4.0, - children: defaultPinnedEmojis - .mapIndexed( - (index, emoji) => ReactionButton( - account: Account.dummy(), - emoji: emoji, - count: index + 1, - scale: reactionsDisplayScale.value, - ), - ) - .toList(), - ), - ), - // SwitchListTile( - // title: Text(t.misskey.limitWidthOfReaction), - // value: settings.limitWidthOfReaction, - // onChanged: (value) => ref - // .read(generalSettingsNotifierProvider.notifier) - // .setLimitWidthOfReaction(value), - // ), - const Divider(), Padding( padding: const EdgeInsets.only(left: 16.0), child: Text( diff --git a/lib/view/page/settings/note_display_page.dart b/lib/view/page/settings/note_display_page.dart new file mode 100644 index 000000000..65d296aae --- /dev/null +++ b/lib/view/page/settings/note_display_page.dart @@ -0,0 +1,457 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:misskey_dart/misskey_dart.dart'; +import 'package:multi_split_view/multi_split_view.dart'; +import 'package:twemoji_v2/twemoji_v2.dart'; + +import '../../../constant/default_pinned_emojis.dart'; +import '../../../gen/fonts.gen.dart'; +import '../../../i18n/strings.g.dart'; +import '../../../model/account.dart'; +import '../../../model/general_settings.dart'; +import '../../../provider/general_settings_notifier_provider.dart'; +import '../../dialog/radio_dialog.dart'; +import '../../widget/note_widget.dart'; + +class NoteDisplayPage extends HookConsumerWidget { + const NoteDisplayPage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final settings = ref.watch(generalSettingsNotifierProvider); + final fontSize = useState( + clampDouble( + settings.fontSize, + minFontSize, + maxFontSize, + ), + ); + final reactionsDisplayScale = useState( + clampDouble( + settings.reactionsDisplayScale, + minReactionsDisplayScale, + maxReactionsDisplayScale, + ), + ); + final noteFooterScale = useState( + clampDouble( + settings.noteFooterScale, + minNoteFooterScale, + maxNoteFooterScale, + ), + ); + + return Scaffold( + appBar: AppBar(title: Text(t.misskey.displayOfNote)), + body: MultiSplitViewTheme( + data: MultiSplitViewThemeData( + dividerPainter: DividerPainters.grooved1( + size: 40.0, + highlightedSize: 60.0, + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.3), + highlightedColor: + Theme.of(context).colorScheme.onSurface.withOpacity(0.9), + thickness: 4.0, + highlightedThickness: 6.0, + ), + ), + child: MultiSplitView( + axis: Axis.vertical, + children: [ + ListView( + children: [ + SwitchListTile( + title: Text(t.misskey.collapseRenotes), + value: settings.collapseRenotes, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setCollapseRenotes(value), + ), + ListTile( + title: Text(t.misskey.displayOfSensitiveMedia), + subtitle: Text( + switch (settings.sensitive) { + SensitiveMediaDisplay.respect => + t.misskey.displayOfSensitiveMedia_.respect, + SensitiveMediaDisplay.ignore => + t.misskey.displayOfSensitiveMedia_.ignore, + SensitiveMediaDisplay.force => + t.misskey.displayOfSensitiveMedia_.force, + }, + ), + trailing: const Icon(Icons.navigate_next), + onTap: () async { + final result = await showRadioDialog( + context, + title: Text(t.misskey.displayOfSensitiveMedia), + values: SensitiveMediaDisplay.values, + initialValue: settings.sensitive, + itemBuilder: (context, value) => Text( + switch (value) { + SensitiveMediaDisplay.respect => + t.misskey.displayOfSensitiveMedia_.respect, + SensitiveMediaDisplay.ignore => + t.misskey.displayOfSensitiveMedia_.ignore, + SensitiveMediaDisplay.force => + t.misskey.displayOfSensitiveMedia_.force, + }, + ), + ); + if (result != null) { + await ref + .read(generalSettingsNotifierProvider.notifier) + .setSensitive(result); + } + }, + ), + SwitchListTile( + title: Text(t.misskey.highlightSensitiveMedia), + value: settings.highlightSensitiveMedia, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setHighlightSensitiveMedia(value), + ), + SwitchListTile( + title: Text(t.misskey.enableAnimatedMfm), + value: settings.animatedMfm, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setAnimatedMfm(value), + ), + SwitchListTile( + title: Text(t.misskey.enableAdvancedMfm), + value: settings.advancedMfm, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setAdvancedMfm(value), + ), + // TODO: Update localization + SwitchListTile( + // title: Text(t.misskey.showReactionsCount), + value: settings.showReactionsCount, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowReactionsCount(value), + ), + SwitchListTile( + title: Text(t.misskey.loadRawImages), + value: settings.loadRawImages, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setLoadRawImages(value), + ), + ListTile( + title: Text(t.misskey.emojiStyle), + subtitle: Text( + switch (settings.emojiStyle) { + EmojiStyle.native => t.misskey.native, + EmojiStyle.twemoji => 'Twemoji', + }, + ), + trailing: const Icon(Icons.navigate_next), + onTap: () async { + final result = await showRadioDialog( + context, + title: Text(t.misskey.emojiStyle), + values: EmojiStyle.values, + initialValue: settings.emojiStyle, + itemBuilder: (context, value) => Text( + switch (value) { + EmojiStyle.native => t.misskey.native, + EmojiStyle.twemoji => 'Twemoji', + }, + ), + ); + if (result != null) { + await ref + .read(generalSettingsNotifierProvider.notifier) + .setEmojiStyle(result); + } + }, + ), + SwitchListTile( + title: Text(t.aria.showAvatarsInNote), + value: settings.showAvatarsInNote, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowAvatarsInNote(value), + ), + SwitchListTile( + title: Text(t.aria.showAvatarsInSubNote), + value: settings.showAvatarsInSubNote, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowAvatarsInSubNote(value), + ), + SwitchListTile( + title: Text(t.misskey.squareAvatars), + value: settings.squareAvatars, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setSquareAvatars(value), + ), + SwitchListTile( + title: Text(t.misskey.showAvatarDecorations), + value: settings.showAvatarDecorations, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowAvatarDecorations(value), + ), + SwitchListTile( + title: Text(t.misskey.showClipButtonInNoteFooter), + value: settings.showClipButtonInNoteFooter, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowClipButtonInNoteFooter(value), + ), + SwitchListTile( + title: Text(t.aria.showTranslateButtonInNoteFooter), + value: settings.showTranslateButtonInNoteFooter, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowTranslateButtonInNoteFooter(value), + ), + SwitchListTile( + title: Text(t.aria.showNoteReactionsViewer), + value: settings.showNoteReactionsViewer, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowNoteReactionsViewer(value), + ), + SwitchListTile( + title: Text(t.aria.showNoteFooter), + value: settings.showNoteFooter, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowNoteFooter(value), + ), + SwitchListTile( + title: Text(t.aria.showSubNoteReactionsViewer), + value: settings.showSubNoteReactionsViewer, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowSubNoteReactionsViewer(value), + ), + SwitchListTile( + title: Text(t.aria.showSubNoteFooter), + value: settings.showSubNoteFooter, + onChanged: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setShowSubNoteFooter(value), + ), + ListTile( + title: Text(t.aria.font), + subtitle: Text(settings.fontFamily ?? t.misskey.system), + trailing: const Icon(Icons.navigate_next), + onTap: () async { + final result = await showRadioDialog( + context, + title: Text(t.aria.font), + values: [ + (null,), + (FontFamily.bIZUDGothic,), + (FontFamily.bIZUDMincho,), + (FontFamily.mPlus1,), + (FontFamily.mPlus2,), + (FontFamily.notoSansJP,), + (FontFamily.notoSansKR,), + (FontFamily.notoSansSC,), + (FontFamily.notoSansTC,), + (FontFamily.notoSerifJP,), + (FontFamily.nunito,), + (FontFamily.pretendard,), + ], + initialValue: (settings.fontFamily,), + itemBuilder: (context, value) => Text( + value.$1 ?? t.misskey.system, + style: TextStyle(fontFamily: value.$1), + ), + ); + if (result != null) { + await ref + .read(generalSettingsNotifierProvider.notifier) + .setFontFamily(result.$1); + } + }, + ), + ListTile( + title: Text(t.misskey.fontSize), + subtitle: Slider( + value: fontSize.value, + min: minFontSize, + max: maxFontSize, + label: fontSize.value.toStringAsFixed(1), + onChanged: (value) => fontSize.value = value, + onChangeEnd: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setFontSize(value), + ), + trailing: IconButton( + onPressed: () { + fontSize.value = defaultFontSize; + ref + .read(generalSettingsNotifierProvider.notifier) + .setFontSize(defaultFontSize); + }, + icon: const Icon(Icons.refresh), + ), + ), + ListTile( + title: Text(t.misskey.reactionsDisplaySize), + subtitle: Slider( + value: reactionsDisplayScale.value, + min: minReactionsDisplayScale, + max: maxReactionsDisplayScale, + label: reactionsDisplayScale.value.toStringAsFixed(3), + onChanged: (value) => reactionsDisplayScale.value = value, + onChangeEnd: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setReactionsDisplayScale(value), + ), + trailing: IconButton( + onPressed: () { + reactionsDisplayScale.value = 1.0; + ref + .read(generalSettingsNotifierProvider.notifier) + .setReactionsDisplayScale(1.0); + }, + icon: const Icon(Icons.refresh), + ), + ), + // SwitchListTile( + // title: Text(t.misskey.limitWidthOfReaction), + // value: settings.limitWidthOfReaction, + // onChanged: (value) => ref + // .read(generalSettingsNotifierProvider.notifier) + // .setLimitWidthOfReaction(value), + // ), + ListTile( + title: Text(t.aria.noteFooterSize), + subtitle: Slider( + value: noteFooterScale.value, + min: minNoteFooterScale, + max: maxNoteFooterScale, + label: noteFooterScale.value.toStringAsFixed(3), + onChanged: (value) => noteFooterScale.value = value, + onChangeEnd: (value) => ref + .read(generalSettingsNotifierProvider.notifier) + .setNoteFooterScale(value), + ), + trailing: IconButton( + onPressed: () { + noteFooterScale.value = 1.0; + ref + .read(generalSettingsNotifierProvider.notifier) + .setNoteFooterScale(1.0); + }, + icon: const Icon(Icons.refresh), + ), + ), + ], + ), + SingleChildScrollView( + child: NoteWidget( + account: const Account(host: '', username: ''), + noteId: '', + note: Note( + id: '', + createdAt: DateTime.now(), + text: r'$[jelly.speed=2s $[x4 🍮]]', + user: UserLite( + id: '', + username: 'user', + avatarUrl: Uri.https( + 'raw.githubusercontent.com', + 'jdecked/twemoji/main/assets/72x72/${TwemojiUtils.toUnicode('🍮')}.png', + ), + avatarDecorations: [ + const UserAvatarDecoration( + id: '', + url: + 'https://media.misskeyusercontent.jp/io/7f797e40-9ab0-4f3b-b4c6-9d1103d637f2.png', + ), + ], + ), + userId: '', + visibility: NoteVisibility.public, + renoteCount: 0, + repliesCount: 0, + reactionCount: 55, + reactions: defaultPinnedEmojis + .asMap() + .map((key, value) => MapEntry(value, key + 1)), + fileIds: [], + files: [ + DriveFile( + id: '', + createdAt: DateTime.now(), + name: '', + type: 'image/png', + md5: '', + size: 0, + isSensitive: false, + properties: const DriveFileProperties(), + thumbnailUrl: Uri.https( + 'raw.githubusercontent.com', + 'jdecked/twemoji/main/assets/72x72/${TwemojiUtils.toUnicode('👍')}.png', + ).toString(), + url: Uri.https( + 'raw.githubusercontent.com', + 'jdecked/twemoji/main/assets/72x72/${TwemojiUtils.toUnicode('👍')}.png', + ).toString(), + ), + DriveFile( + id: '', + createdAt: DateTime.now(), + name: '', + type: 'image/png', + md5: '', + size: 0, + isSensitive: true, + properties: const DriveFileProperties(), + thumbnailUrl: Uri.https( + 'raw.githubusercontent.com', + 'jdecked/twemoji/main/assets/72x72/${TwemojiUtils.toUnicode('❤️')}.png', + ).toString(), + url: Uri.https( + 'raw.githubusercontent.com', + 'jdecked/twemoji/main/assets/72x72/${TwemojiUtils.toUnicode('❤️')}.png', + ).toString(), + ), + ], + renoteId: '', + renote: Note( + id: '', + createdAt: DateTime.now(), + text: 'just setting up my msky', + user: UserLite( + id: '', + username: 'admin', + avatarUrl: Uri.https( + 'raw.githubusercontent.com', + 'jdecked/twemoji/main/assets/72x72/${TwemojiUtils.toUnicode('1️⃣')}.png', + ), + ), + userId: '', + visibility: NoteVisibility.public, + renoteCount: 1, + repliesCount: 0, + reactionCount: 55, + reactions: defaultPinnedEmojis + .asMap() + .map((key, value) => MapEntry(value, key + 1)), + fileIds: [], + files: [], + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/view/page/settings/settings_page.dart b/lib/view/page/settings/settings_page.dart index 9af819026..422cd6060 100644 --- a/lib/view/page/settings/settings_page.dart +++ b/lib/view/page/settings/settings_page.dart @@ -74,6 +74,11 @@ class SettingsPage extends HookConsumerWidget { title: Text(t.misskey.uiLanguage), onTap: () => context.push('/settings/language'), ), + ListTile( + leading: const Icon(Icons.article), + title: Text(t.misskey.displayOfNote), + onTap: () => context.push('/settings/note-display'), + ), ListTile( leading: const Icon(Icons.brush), title: Text(t.misskey.appearance), diff --git a/lib/view/widget/media_card.dart b/lib/view/widget/media_card.dart index 62485a21c..5e1a67f1a 100644 --- a/lib/view/widget/media_card.dart +++ b/lib/view/widget/media_card.dart @@ -186,6 +186,14 @@ class MediaCard extends HookConsumerWidget { dataSaver || (file.isSensitive && sensitive != SensitiveMediaDisplay.ignore), ); + ref.listen( + generalSettingsNotifierProvider.select((settings) => settings.sensitive), + (_, sensitive) { + hide.value = sensitive == SensitiveMediaDisplay.force || + dataSaver || + (file.isSensitive && sensitive != SensitiveMediaDisplay.ignore); + }, + ); final colors = ref.watch(misskeyColorsProvider(Theme.of(context).brightness)); final style = DefaultTextStyle.of(context).style; diff --git a/lib/view/widget/mfm.dart b/lib/view/widget/mfm.dart index 540ce4800..e5c20756f 100644 --- a/lib/view/widget/mfm.dart +++ b/lib/view/widget/mfm.dart @@ -143,9 +143,6 @@ class Mfm extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final emojiStyle = ref.watch( - generalSettingsNotifierProvider.select((settings) => settings.emojiStyle), - ); final colors = ref.watch(misskeyColorsProvider(Theme.of(context).brightness)); final span = useMemoized( @@ -165,7 +162,7 @@ class Mfm extends HookConsumerWidget { maxLines: maxLines, ), ), - [account, text, nodes, simple, style, author, colors, emojis, emojiStyle], + [account, text, nodes, simple, style, author, colors, emojis], ); if (selectable) { diff --git a/lib/view/widget/note_detailed_widget.dart b/lib/view/widget/note_detailed_widget.dart index 734721801..570d7d8f1 100644 --- a/lib/view/widget/note_detailed_widget.dart +++ b/lib/view/widget/note_detailed_widget.dart @@ -447,7 +447,7 @@ class NoteDetailedWidget extends HookConsumerWidget { ), NoteFooter( account: account, - noteId: noteId, + noteId: appearNote.id, hideDetails: true, ), if (children diff --git a/lib/view/widget/note_footer.dart b/lib/view/widget/note_footer.dart index a02a00771..634a17f36 100644 --- a/lib/view/widget/note_footer.dart +++ b/lib/view/widget/note_footer.dart @@ -13,8 +13,8 @@ import '../../model/account.dart'; import '../../provider/api/i_notifier_provider.dart'; import '../../provider/api/meta_provider.dart'; import '../../provider/api/post_notifier_provider.dart'; -import '../../provider/appear_note_provider.dart'; import '../../provider/general_settings_notifier_provider.dart'; +import '../../provider/note_provider.dart'; import '../../provider/notes_notifier_provider.dart'; import '../../util/future_with_dialog.dart'; import '../dialog/clip_dialog.dart'; @@ -33,17 +33,19 @@ class NoteFooter extends ConsumerWidget { required this.noteId, this.hideDetails = false, this.postFormFocusNode, + this.note, }); final Account account; final String noteId; final bool hideDetails; final FocusNode? postFormFocusNode; + final Note? note; @override Widget build(BuildContext context, WidgetRef ref) { - final appearNote = ref.watch(appearNoteProvider(account, noteId)); - if (appearNote == null) { + final note = this.note ?? ref.watch(noteProvider(account, noteId)); + if (note == null) { return const SizedBox.shrink(); } final i = ref.watch(iNotifierProvider(account)).valueOrNull; @@ -64,8 +66,8 @@ class NoteFooter extends ConsumerWidget { generalSettingsNotifierProvider .select((settings) => settings.showReactionsCount), ); - final isMyNote = i != null && appearNote.user.id == i.id; - final canRenote = switch (appearNote.visibility) { + final isMyNote = i != null && note.user.id == i.id; + final canRenote = switch (note.visibility) { NoteVisibility.public || NoteVisibility.home => true, NoteVisibility.followers => isMyNote, _ => false, @@ -93,7 +95,7 @@ class NoteFooter extends ConsumerWidget { ? () { ref .read(postNotifierProvider(account).notifier) - .setReply(appearNote); + .setReply(note); if (postFormFocusNode != null) { postFormFocusNode?.requestFocus(); } else { @@ -105,13 +107,13 @@ class NoteFooter extends ConsumerWidget { mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.reply), - if (appearNote.repliesCount > 0) + if (note.repliesCount > 0) Padding( padding: const EdgeInsets.symmetric( horizontal: 2.0, ), child: Text( - NumberFormat().format(appearNote.repliesCount), + NumberFormat().format(note.repliesCount), style: style, ), ), @@ -120,26 +122,26 @@ class NoteFooter extends ConsumerWidget { ), if (canRenote) GestureDetector( - onLongPress: appearNote.renoteCount > 0 + onLongPress: note.renoteCount > 0 ? () { HapticFeedback.lightImpact(); showModalBottomSheet( context: context, builder: (context) => RenoteUsersSheet( account: account, - noteId: appearNote.id, + noteId: note.id, ), isScrollControlled: true, ); } : null, child: IconButton( - tooltip: appearNote.renoteCount <= 0 ? t.misskey.renote : null, + tooltip: note.renoteCount <= 0 ? t.misskey.renote : null, onPressed: i != null ? () { ref .read(postNotifierProvider(account).notifier) - .setRenote(appearNote); + .setRenote(note); if (postFormFocusNode != null) { postFormFocusNode?.requestFocus(); } else { @@ -151,13 +153,13 @@ class NoteFooter extends ConsumerWidget { mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.repeat_rounded), - if (appearNote.renoteCount > 0) + if (note.renoteCount > 0) Padding( padding: const EdgeInsets.symmetric( horizontal: 2.0, ), child: Text( - NumberFormat().format(appearNote.renoteCount), + NumberFormat().format(note.renoteCount), style: style, ), ), @@ -171,38 +173,37 @@ class NoteFooter extends ConsumerWidget { onPressed: null, icon: const Icon(Icons.block), ), - if (appearNote.myReaction == null) + if (note.myReaction == null) GestureDetector( - onLongPress: appearNote.reactionAcceptance == - ReactionAcceptance.likeOnly && - (appearNote.reactionCount ?? 0) > 0 - ? () => showModalBottomSheet( - context: context, - builder: (context) => ReactionUsersSheet( - account: account, - noteId: noteId, - reaction: '❤️', - ), - isScrollControlled: true, - ) - : null, + onLongPress: + note.reactionAcceptance == ReactionAcceptance.likeOnly && + (note.reactionCount ?? 0) > 0 + ? () => showModalBottomSheet( + context: context, + builder: (context) => ReactionUsersSheet( + account: account, + noteId: noteId, + reaction: '❤️', + ), + isScrollControlled: true, + ) + : null, child: IconButton( - tooltip: - appearNote.reactionAcceptance != ReactionAcceptance.likeOnly - ? t.misskey.reaction - : (appearNote.reactionCount ?? 0) <= 0 - ? t.misskey.like - : null, + tooltip: note.reactionAcceptance != ReactionAcceptance.likeOnly + ? t.misskey.reaction + : (note.reactionCount ?? 0) <= 0 + ? t.misskey.like + : null, onPressed: i != null ? () async { - final emoji = appearNote.reactionAcceptance == + final emoji = note.reactionAcceptance == ReactionAcceptance.likeOnly ? '❤️' : await pickEmoji( ref, account, reaction: true, - targetNote: appearNote, + targetNote: note, ); if (!context.mounted) return; if (emoji != null) { @@ -213,7 +214,7 @@ class NoteFooter extends ConsumerWidget { context, account: account, emoji: emoji, - note: appearNote, + note: note, ); if (!confirmed) return; } @@ -222,7 +223,7 @@ class NoteFooter extends ConsumerWidget { context, ref .read(notesNotifierProvider(account).notifier) - .react(appearNote.id, emoji), + .react(note.id, emoji), ); } } @@ -230,19 +231,17 @@ class NoteFooter extends ConsumerWidget { icon: Row( mainAxisSize: MainAxisSize.min, children: [ - if (appearNote.reactionAcceptance == - ReactionAcceptance.likeOnly) + if (note.reactionAcceptance == ReactionAcceptance.likeOnly) const Icon(Icons.favorite_border) else const Icon(Icons.add), - if (showReactionsCount && - (appearNote.reactionCount ?? 0) > 0) + if (showReactionsCount && (note.reactionCount ?? 0) > 0) Padding( padding: const EdgeInsets.symmetric( horizontal: 2.0, ), child: Text( - NumberFormat().format(appearNote.reactionCount), + NumberFormat().format(note.reactionCount), style: style, ), ), @@ -253,7 +252,7 @@ class NoteFooter extends ConsumerWidget { else GestureDetector( onLongPress: - appearNote.reactionAcceptance == ReactionAcceptance.likeOnly + note.reactionAcceptance == ReactionAcceptance.likeOnly ? () => showModalBottomSheet( context: context, builder: (context) => ReactionUsersSheet( @@ -265,10 +264,9 @@ class NoteFooter extends ConsumerWidget { ) : null, child: IconButton( - tooltip: - appearNote.reactionAcceptance != ReactionAcceptance.likeOnly - ? t.misskey.reaction - : null, + tooltip: note.reactionAcceptance != ReactionAcceptance.likeOnly + ? t.misskey.reaction + : null, onPressed: () async { final confirmed = await confirm( context, @@ -280,14 +278,13 @@ class NoteFooter extends ConsumerWidget { context, ref .read(notesNotifierProvider(account).notifier) - .unreact(appearNote.id), + .unreact(note.id), ); }, icon: Row( mainAxisSize: MainAxisSize.min, children: [ - if (appearNote.reactionAcceptance == - ReactionAcceptance.likeOnly) + if (note.reactionAcceptance == ReactionAcceptance.likeOnly) const Icon( Icons.favorite, color: eventReactionHeart, @@ -297,16 +294,16 @@ class NoteFooter extends ConsumerWidget { Icons.remove, color: Theme.of(context).colorScheme.primary, ), - if ((appearNote.reactionAcceptance == + if ((note.reactionAcceptance == ReactionAcceptance.likeOnly || showReactionsCount) && - (appearNote.reactionCount ?? 0) > 0) + (note.reactionCount ?? 0) > 0) Padding( padding: const EdgeInsets.symmetric( horizontal: 2.0, ), child: Text( - NumberFormat().format(appearNote.reactionCount), + NumberFormat().format(note.reactionCount), style: style, ), ), @@ -338,7 +335,7 @@ class NoteFooter extends ConsumerWidget { context: context, builder: (context) => TranslatedNoteSheet( account: account, - note: appearNote, + note: note, ), ); } else { @@ -346,7 +343,7 @@ class NoteFooter extends ConsumerWidget { Uri.https( 'translate.google.com', '', - {'text': appearNote.text}, + {'text': note.text}, ), ); } @@ -355,17 +352,19 @@ class NoteFooter extends ConsumerWidget { ), IconButton( tooltip: t.misskey.menu, - onPressed: () => showModalBottomSheet( - context: context, - builder: (context) => NoteSheet( - account: account, - noteId: noteId, - hideDetails: hideDetails, - postFormFocusNode: postFormFocusNode, - ), - clipBehavior: Clip.hardEdge, - isScrollControlled: true, - ), + onPressed: noteId.isNotEmpty + ? () => showModalBottomSheet( + context: context, + builder: (context) => NoteSheet( + account: account, + noteId: noteId, + hideDetails: hideDetails, + postFormFocusNode: postFormFocusNode, + ), + clipBehavior: Clip.hardEdge, + isScrollControlled: true, + ) + : null, icon: const Icon(Icons.more_horiz), ), ], diff --git a/lib/view/widget/note_header.dart b/lib/view/widget/note_header.dart index cadad5698..d7e07e697 100644 --- a/lib/view/widget/note_header.dart +++ b/lib/view/widget/note_header.dart @@ -39,7 +39,9 @@ class NoteHeader extends HookConsumerWidget { child: Align( alignment: Alignment.centerLeft, child: InkWell( - onTap: () => context.push('/$account/users/${note.userId}'), + onTap: note.userId.isNotEmpty + ? () => context.push('/$account/users/${note.userId}') + : null, child: Text.rich( TextSpan( children: [ @@ -107,7 +109,9 @@ class NoteHeader extends HookConsumerWidget { style: style.apply(fontSizeFactor: 0.9), child: TimeWidget( time: note.createdAt, - onTap: () => context.push('/$account/notes/${note.id}'), + onTap: note.id.isNotEmpty + ? () => context.push('/$account/notes/${note.id}') + : null, ), ), IconTheme.merge( diff --git a/lib/view/widget/note_simple_widget.dart b/lib/view/widget/note_simple_widget.dart index faf3ce44b..cff414cf9 100644 --- a/lib/view/widget/note_simple_widget.dart +++ b/lib/view/widget/note_simple_widget.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:misskey_dart/misskey_dart.dart'; import '../../extension/text_style_extension.dart'; import '../../model/account.dart'; @@ -22,6 +23,7 @@ class NoteSimpleWidget extends HookConsumerWidget { this.borderRadius, this.showFooter, this.postFormFocusNode, + this.note, }); final Account account; @@ -29,10 +31,11 @@ class NoteSimpleWidget extends HookConsumerWidget { final BorderRadius? borderRadius; final bool? showFooter; final FocusNode? postFormFocusNode; + final Note? note; @override Widget build(BuildContext context, WidgetRef ref) { - final note = ref.watch(noteProvider(account, noteId)); + final note = this.note ?? ref.watch(noteProvider(account, noteId)); if (note == null) { return const SizedBox.shrink(); } @@ -50,7 +53,7 @@ class NoteSimpleWidget extends HookConsumerWidget { ); final showAvatars = ref.watch( generalSettingsNotifierProvider - .select((settings) => settings.showAvatarsInNote), + .select((settings) => settings.showAvatarsInSubNote), ); final showContent = useState(false); @@ -122,6 +125,7 @@ class NoteSimpleWidget extends HookConsumerWidget { noteId: noteId, showFooter: showFooter, postFormFocusNode: postFormFocusNode, + note: this.note, ), ], ), diff --git a/lib/view/widget/note_sub_widget.dart b/lib/view/widget/note_sub_widget.dart index fcdc8de10..ce5ac71b5 100644 --- a/lib/view/widget/note_sub_widget.dart +++ b/lib/view/widget/note_sub_widget.dart @@ -54,7 +54,7 @@ class NoteSubWidget extends HookConsumerWidget { ); final showAvatars = ref.watch( generalSettingsNotifierProvider - .select((settings) => settings.showAvatarsInNote), + .select((settings) => settings.showAvatarsInSubNote), ); final children = showReplies && depth < 5 ? ref.watch(childrenNotesNotifierProvider(account, noteId)) diff --git a/lib/view/widget/note_widget.dart b/lib/view/widget/note_widget.dart index 69a325a35..802f53401 100644 --- a/lib/view/widget/note_widget.dart +++ b/lib/view/widget/note_widget.dart @@ -149,6 +149,11 @@ class NoteWidget extends HookConsumerWidget { generalSettingsNotifierProvider .select((settings) => settings.noteLongPressAction), ); + final mfmSettings = ref.watch( + generalSettingsNotifierProvider.select( + (settings) => (settings.advancedMfm, settings.animatedMfm), + ), + ); final i = ref.watch(iNotifierProvider(account)).valueOrNull; final isRenote = note.isRenote; final isMyRenote = i != null && note.user.id == i.id; @@ -239,8 +244,11 @@ class NoteWidget extends HookConsumerWidget { child: UserAvatar( user: appearNote.user, size: style.lineHeight, - onTap: () => context - .push('/$account/users/${appearNote.userId}'), + onTap: appearNote.userId.isNotEmpty + ? () => context.push( + '/$account/users/${appearNote.userId}', + ) + : null, ), ) else @@ -273,8 +281,11 @@ class NoteWidget extends HookConsumerWidget { child: UserAvatar( user: appearNote.user, size: style.lineHeight * 2.5, - onTap: () => context - .push('/$account/users/${appearNote.userId}'), + onTap: appearNote.userId.isNotEmpty + ? () => context.push( + '/$account/users/${appearNote.userId}', + ) + : null, ), ) else @@ -384,6 +395,7 @@ class NoteWidget extends HookConsumerWidget { appearNote.user, appearNote.emojis, isCollapsed.value, + mfmSettings, ], ), ], @@ -427,6 +439,7 @@ class NoteWidget extends HookConsumerWidget { BorderRadius.circular(4.0), showFooter: this.showFooter, postFormFocusNode: postFormFocusNode, + note: this.note?.renote, ), ), ), @@ -484,12 +497,14 @@ class NoteWidget extends HookConsumerWidget { ReactionsViewer( account: account, noteId: appearNote.id, + note: this.note, ), if (showFooter) NoteFooter( account: account, - noteId: noteId, + noteId: appearNote.id, postFormFocusNode: postFormFocusNode, + note: this.note, ), ], ), diff --git a/lib/view/widget/reaction_button.dart b/lib/view/widget/reaction_button.dart index c41b66993..d4cca1b88 100644 --- a/lib/view/widget/reaction_button.dart +++ b/lib/view/widget/reaction_button.dart @@ -22,14 +22,14 @@ class ReactionButton extends ConsumerWidget { const ReactionButton({ super.key, required this.account, - this.note, + required this.note, required this.emoji, required this.count, this.scale, }); final Account account; - final Note? note; + final Note note; final String emoji; final int count; final double? scale; @@ -46,12 +46,11 @@ class ReactionButton extends ConsumerWidget { ) : null; final canReact = !account.isGuest && - note != null && (!isCustomEmoji || - data != null && checkReactionPermissions(i, note!, data)); - final isMyReaction = emoji == note?.myReaction; + data != null && checkReactionPermissions(i, note, data)); + final isMyReaction = emoji == note.myReaction; // In v12, `note.emojis` contains emoji urls for both text and reactions. - final emojis = {...?note?.emojis, ...?note?.reactionEmojis}; + final emojis = {...note.emojis, ...note.reactionEmojis}; final double scale = this.scale ?? ref.watch( generalSettingsNotifierProvider @@ -65,7 +64,8 @@ class ReactionButton extends ConsumerWidget { return ElevatedButton( onPressed: canReact ? () async { - if (note!.myReaction == null) { + if (note.id.isEmpty) return; + if (note.myReaction == null) { if (ref .read(generalSettingsNotifierProvider) .confirmBeforeReact || @@ -74,7 +74,7 @@ class ReactionButton extends ConsumerWidget { context, account: account, emoji: emoji, - note: note!, + note: note, ); if (!confirmed) return; } @@ -83,7 +83,7 @@ class ReactionButton extends ConsumerWidget { context, ref .read(notesNotifierProvider(account).notifier) - .react(note!.id, emoji), + .react(note.id, emoji), ); } else if (isMyReaction) { final confirmed = await confirm( @@ -96,7 +96,7 @@ class ReactionButton extends ConsumerWidget { context, ref .read(notesNotifierProvider(account).notifier) - .unreact(note!.id), + .unreact(note.id), ); } else { final confirmed = await confirm( @@ -121,17 +121,17 @@ class ReactionButton extends ConsumerWidget { context, ref .read(notesNotifierProvider(account).notifier) - .changeReaction(note!.id, emoji), + .changeReaction(note.id, emoji), ); } } : null, - onLongPress: note != null + onLongPress: note.id.isNotEmpty ? () => showModalBottomSheet( context: context, builder: (context) => ReactionUsersSheet( account: account, - noteId: note!.id, + noteId: note.id, reaction: emoji, ), isScrollControlled: true, diff --git a/lib/view/widget/reactions_viewer.dart b/lib/view/widget/reactions_viewer.dart index f982ff63b..2f053ed95 100644 --- a/lib/view/widget/reactions_viewer.dart +++ b/lib/view/widget/reactions_viewer.dart @@ -2,6 +2,7 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:misskey_dart/misskey_dart.dart'; import '../../i18n/strings.g.dart'; import '../../model/account.dart'; @@ -15,15 +16,17 @@ class ReactionsViewer extends HookConsumerWidget { required this.account, required this.noteId, this.showAllReactions = false, + this.note, }); final Account account; final String noteId; final bool showAllReactions; + final Note? note; @override Widget build(BuildContext context, WidgetRef ref) { - final note = ref.watch(noteProvider(account, noteId)); + final note = this.note ?? ref.watch(noteProvider(account, noteId)); if (note == null) { return const SizedBox.shrink(); } diff --git a/lib/view/widget/sub_note_content.dart b/lib/view/widget/sub_note_content.dart index 90c087dbc..4b8c34a66 100644 --- a/lib/view/widget/sub_note_content.dart +++ b/lib/view/widget/sub_note_content.dart @@ -26,16 +26,18 @@ class SubNoteContent extends HookConsumerWidget { required this.noteId, this.showFooter, this.postFormFocusNode, + this.note, }); final Account account; final String noteId; final bool? showFooter; final FocusNode? postFormFocusNode; + final Note? note; @override Widget build(BuildContext context, WidgetRef ref) { - final note = ref.watch(noteProvider(account, noteId)); + final note = this.note ?? ref.watch(noteProvider(account, noteId)); if (note == null) { return const SizedBox.shrink(); } @@ -172,12 +174,17 @@ class SubNoteContent extends HookConsumerWidget { ), if (showReactionsViewer && note.reactionAcceptance != ReactionAcceptance.likeOnly) - ReactionsViewer(account: account, noteId: noteId), + ReactionsViewer( + account: account, + noteId: noteId, + note: this.note, + ), if (showFooter) NoteFooter( account: account, noteId: noteId, postFormFocusNode: postFormFocusNode, + note: this.note, ), ], ); diff --git a/pubspec.lock b/pubspec.lock index 7536fc2e3..efcdda92d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1223,6 +1223,14 @@ packages: url: "https://github.com/poppingmoon/misskey_dart" source: git version: "1.0.0" + multi_split_view: + dependency: "direct main" + description: + name: multi_split_view + sha256: d68e129bff71fc9e6b66de59e1b79deaf4b91f30940130bfbd2d704c1c713499 + url: "https://pub.dev" + source: hosted + version: "2.4.0" nested: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e667b7a97..8bddff2b8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,6 +66,7 @@ dependencies: git: url: https://github.com/poppingmoon/misskey_dart ref: e430aec5a1a2774811a608d98bcc19edaf1b1eb4 + multi_split_view: ^2.4.0 package_info_plus: ^4.2.0 photo_view: ^0.14.0 punycode: ^1.0.0