diff --git a/lib/router/app_router.gr.dart b/lib/router/app_router.gr.dart index 2477e2e3a..bda93569c 100644 --- a/lib/router/app_router.gr.dart +++ b/lib/router/app_router.gr.dart @@ -514,11 +514,12 @@ abstract class _$AppRouter extends RootStackRouter { final args = routeData.argsAs(); return AutoRoutePage( routeData: routeData, - child: RenoteModalSheet( + child: WrappedRoute( + child: RenoteModalSheet( note: args.note, account: args.account, key: args.key, - ), + )), ); }, RenoteUserRoute.name: (routeData) { diff --git a/lib/view/common/misskey_notes/renote_modal_sheet.dart b/lib/view/common/misskey_notes/renote_modal_sheet.dart index 5c15b3a0b..ae9f4f7a6 100644 --- a/lib/view/common/misskey_notes/renote_modal_sheet.dart +++ b/lib/view/common/misskey_notes/renote_modal_sheet.dart @@ -9,8 +9,12 @@ import "package:miria/extensions/note_visibility_extension.dart"; import "package:miria/model/account.dart"; import "package:miria/providers.dart"; import "package:miria/router/app_router.dart"; +import "package:miria/state_notifier/common/misskey_notes/misskey_note_notifier.dart"; +import "package:miria/view/common/account_scope.dart"; +import "package:miria/view/common/avatar_icon.dart"; import "package:miria/view/common/dialog/dialog_state.dart"; import "package:miria/view/common/misskey_notes/local_only_icon.dart"; +import "package:miria/view/common/misskey_notes/mfm_text.dart"; import "package:misskey_dart/misskey_dart.dart"; import "package:riverpod_annotation/riverpod_annotation.dart"; @@ -84,8 +88,48 @@ class RenoteChannelNotifier extends _$RenoteChannelNotifier { } } +@Riverpod(dependencies: [accountContext], keepAlive: false) +class RenoteOtherAccountNotifier extends _$RenoteOtherAccountNotifier { + @override + AsyncValue<(Account, Note)>? build(Account account, Note note) => null; + + Future renoteOtherAccount() async { + final selectedAccount = await ref.read(appRouterProvider).push( + AccountSelectRoute( + host: note.localOnly ? this.account.host : null, + remoteHost: + note.user.host != this.account.host && note.user.host != null + ? note.user.host + : null, + ), + ); + if (selectedAccount == null) return; + await ref.read(dialogStateNotifierProvider.notifier).guard(() async { + final accountContext = AccountContext( + getAccount: selectedAccount, + postAccount: selectedAccount.isDemoAccount + ? ref.read(accountContextProvider).postAccount + : selectedAccount, + ); + state = const AsyncLoading(); + final foundNote = note.user.host == null && + note.uri?.host == accountContext.getAccount.host + ? note + : await ref + .read(misskeyNoteNotifierProvider.notifier) + .lookupNote(note: note, accountContext: accountContext); + if (foundNote == null) { + state = null; + return; + } + ref.read(notesProvider(selectedAccount)).registerNote(foundNote); + state = AsyncValue.data((selectedAccount, foundNote)); + }); + } +} + @RoutePage() -class RenoteModalSheet extends HookConsumerWidget { +class RenoteModalSheet extends HookConsumerWidget implements AutoRouteWrapper { final Note note; final Account account; @@ -95,6 +139,12 @@ class RenoteModalSheet extends HookConsumerWidget { super.key, }); + @override + Widget wrappedRoute(BuildContext context) => AccountContextScope.as( + account: account, + child: this, + ); + @override Widget build(BuildContext context, WidgetRef ref) { final channel = note.channel; @@ -121,12 +171,26 @@ class RenoteModalSheet extends HookConsumerWidget { initialAccount: account, ), ); + }) + ..listen(renoteOtherAccountNotifierProvider(account, note), + (_, next) async { + if (next is! AsyncData<(Account, Note)>) return; + unawaited(context.maybePop()); + await context.pushRoute( + RenoteModalRoute( + account: next.value.$1, + note: next.value.$2, + ), + ); }); final renoteState = ref.watch(renoteNotifierProvider(account, note)); final renoteChannelState = ref.watch(renoteChannelNotifierProvider(account)); + final renoteOtherAccountState = + ref.watch(renoteOtherAccountNotifierProvider(account, note)); + final isLocalOnly = useState(false); final visibility = useState(NoteVisibility.public); useEffect( @@ -145,12 +209,34 @@ class RenoteModalSheet extends HookConsumerWidget { if (renoteState is AsyncLoading || renoteChannelState is AsyncLoading || + renoteOtherAccountState is AsyncLoading || renoteState is AsyncData || - renoteChannelState is AsyncData) { + renoteChannelState is AsyncData || + renoteOtherAccountState is AsyncData) { return const Center(child: CircularProgressIndicator.adaptive()); } return ListView( children: [ + ListTile( + leading: AvatarIcon(user: account.i), + title: SimpleMfmText( + account.i.name ?? account.i.username, + style: Theme.of(context).textTheme.titleMedium, + ), + subtitle: Text( + account.acct.toString(), + style: Theme.of(context).textTheme.bodySmall, + ), + trailing: IconButton( + onPressed: () async => await ref + .read( + renoteOtherAccountNotifierProvider(account, note).notifier, + ) + .renoteOtherAccount(), + icon: const Icon(Icons.keyboard_arrow_down), + ), + ), + Divider(color: Theme.of(context).primaryColor, thickness: 2), if (channel != null) ...[ ListTile( onTap: () async => diff --git a/lib/view/common/misskey_notes/renote_modal_sheet.g.dart b/lib/view/common/misskey_notes/renote_modal_sheet.g.dart index b406c57bb..ba6e0aa48 100644 --- a/lib/view/common/misskey_notes/renote_modal_sheet.g.dart +++ b/lib/view/common/misskey_notes/renote_modal_sheet.g.dart @@ -429,5 +429,232 @@ class _RenoteChannelNotifierProviderElement @override Account get account => (origin as RenoteChannelNotifierProvider).account; } + +String _$renoteOtherAccountNotifierHash() => + r'6ce80b97d6f49aa3302dfd27b2b1b8242dc559cb'; + +abstract class _$RenoteOtherAccountNotifier + extends BuildlessAutoDisposeNotifier?> { + late final Account account; + late final Note note; + + AsyncValue<(Account, Note)>? build( + Account account, + Note note, + ); +} + +/// See also [RenoteOtherAccountNotifier]. +@ProviderFor(RenoteOtherAccountNotifier) +const renoteOtherAccountNotifierProvider = RenoteOtherAccountNotifierFamily(); + +/// See also [RenoteOtherAccountNotifier]. +class RenoteOtherAccountNotifierFamily extends Family { + /// See also [RenoteOtherAccountNotifier]. + const RenoteOtherAccountNotifierFamily(); + + static final Iterable _dependencies = [ + accountContextProvider + ]; + + static final Iterable _allTransitiveDependencies = + { + accountContextProvider, + ...?accountContextProvider.allTransitiveDependencies + }; + + @override + Iterable? get dependencies => _dependencies; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'renoteOtherAccountNotifierProvider'; + + /// See also [RenoteOtherAccountNotifier]. + RenoteOtherAccountNotifierProvider call( + Account account, + Note note, + ) { + return RenoteOtherAccountNotifierProvider( + account, + note, + ); + } + + @visibleForOverriding + @override + RenoteOtherAccountNotifierProvider getProviderOverride( + covariant RenoteOtherAccountNotifierProvider provider, + ) { + return call( + provider.account, + provider.note, + ); + } + + /// Enables overriding the behavior of this provider, no matter the parameters. + Override overrideWith(RenoteOtherAccountNotifier Function() create) { + return _$RenoteOtherAccountNotifierFamilyOverride(this, create); + } +} + +class _$RenoteOtherAccountNotifierFamilyOverride implements FamilyOverride { + _$RenoteOtherAccountNotifierFamilyOverride( + this.overriddenFamily, this.create); + + final RenoteOtherAccountNotifier Function() create; + + @override + final RenoteOtherAccountNotifierFamily overriddenFamily; + + @override + RenoteOtherAccountNotifierProvider getProviderOverride( + covariant RenoteOtherAccountNotifierProvider provider, + ) { + return provider._copyWith(create); + } +} + +/// See also [RenoteOtherAccountNotifier]. +class RenoteOtherAccountNotifierProvider + extends AutoDisposeNotifierProviderImpl?> { + /// See also [RenoteOtherAccountNotifier]. + RenoteOtherAccountNotifierProvider( + Account account, + Note note, + ) : this._internal( + () => RenoteOtherAccountNotifier() + ..account = account + ..note = note, + from: renoteOtherAccountNotifierProvider, + name: r'renoteOtherAccountNotifierProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$renoteOtherAccountNotifierHash, + dependencies: RenoteOtherAccountNotifierFamily._dependencies, + allTransitiveDependencies: + RenoteOtherAccountNotifierFamily._allTransitiveDependencies, + account: account, + note: note, + ); + + RenoteOtherAccountNotifierProvider._internal( + super.create, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.account, + required this.note, + }) : super.internal(); + + final Account account; + final Note note; + + @override + AsyncValue<(Account, Note)>? runNotifierBuild( + covariant RenoteOtherAccountNotifier notifier, + ) { + return notifier.build( + account, + note, + ); + } + + @override + Override overrideWith(RenoteOtherAccountNotifier Function() create) { + return ProviderOverride( + origin: this, + override: RenoteOtherAccountNotifierProvider._internal( + () => create() + ..account = account + ..note = note, + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + account: account, + note: note, + ), + ); + } + + @override + ( + Account, + Note, + ) get argument { + return ( + account, + note, + ); + } + + @override + AutoDisposeNotifierProviderElement?> createElement() { + return _RenoteOtherAccountNotifierProviderElement(this); + } + + RenoteOtherAccountNotifierProvider _copyWith( + RenoteOtherAccountNotifier Function() create, + ) { + return RenoteOtherAccountNotifierProvider._internal( + () => create() + ..account = account + ..note = note, + name: name, + dependencies: dependencies, + allTransitiveDependencies: allTransitiveDependencies, + debugGetCreateSourceHash: debugGetCreateSourceHash, + from: from, + account: account, + note: note, + ); + } + + @override + bool operator ==(Object other) { + return other is RenoteOtherAccountNotifierProvider && + other.account == account && + other.note == note; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, account.hashCode); + hash = _SystemHash.combine(hash, note.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin RenoteOtherAccountNotifierRef + on AutoDisposeNotifierProviderRef?> { + /// The parameter `account` of this provider. + Account get account; + + /// The parameter `note` of this provider. + Note get note; +} + +class _RenoteOtherAccountNotifierProviderElement + extends AutoDisposeNotifierProviderElement?> with RenoteOtherAccountNotifierRef { + _RenoteOtherAccountNotifierProviderElement(super.provider); + + @override + Account get account => (origin as RenoteOtherAccountNotifierProvider).account; + @override + Note get note => (origin as RenoteOtherAccountNotifierProvider).note; +} // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, inference_failure_on_uninitialized_variable, inference_failure_on_function_return_type, inference_failure_on_untyped_parameter, deprecated_member_use_from_same_package