diff --git a/lib/screens/account/profile.dart b/lib/screens/account/profile.dart index 297ebc7e..a67032fc 100644 --- a/lib/screens/account/profile.dart +++ b/lib/screens/account/profile.dart @@ -9,6 +9,7 @@ import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/chat.dart'; import 'package:island/models/developer.dart'; +import 'package:island/models/publisher.dart'; import 'package:island/models/relationship.dart'; import 'package:island/models/account.dart'; import 'package:island/pods/config.dart'; @@ -224,7 +225,13 @@ class _AccountProfileDetail extends StatelessWidget { spacing: 6, children: [ Icon(Symbols.fingerprint, size: 17, fill: 1).padding(right: 2), - Text(data.id), + Flexible( + child: Text( + data.id, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), ], ), onTap: () { @@ -314,6 +321,56 @@ class _AccountProfileLinks extends StatelessWidget { } } +class _AccountPublisherList extends StatelessWidget { + final List publishers; + + const _AccountPublisherList({required this.publishers}); + + @override + Widget build(BuildContext context) { + if (publishers.isEmpty) return const SizedBox.shrink(); + return Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'publishers', + ).tr().bold().padding(horizontal: 24, top: 12, bottom: 4), + for (final publisher in publishers) + ListTile( + title: Text(publisher.nick), + subtitle: + publisher.bio.isNotEmpty + ? Text( + publisher.bio, + maxLines: 3, + overflow: TextOverflow.ellipsis, + ) + : null, + leading: ProfilePictureWidget( + file: publisher.picture, + borderRadius: publisher.type == 1 ? 8 : null, + ), + isThreeLine: true, + contentPadding: EdgeInsets.symmetric(horizontal: 24), + trailing: const Icon(Symbols.chevron_right), + shape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + ), + onTap: () { + Navigator.pop(context, true); + context.pushNamed( + 'publisherProfile', + pathParameters: {'name': publisher.name}, + ); + }, + ), + ], + ), + ); + } +} + class _AccountAction extends StatelessWidget { final SnAccount data; final AsyncValue accountRelationship; @@ -335,6 +392,7 @@ class _AccountAction extends StatelessWidget { Widget build(BuildContext context) { return Card( child: Column( + spacing: 8, children: [ Row( spacing: 8, @@ -427,6 +485,7 @@ class _AccountAction extends StatelessWidget { color: Theme.of(context).colorScheme.onError, ), style: ButtonStyle( + visualDensity: VisualDensity.compact, backgroundColor: WidgetStatePropertyAll( Theme.of(context).colorScheme.error, ), @@ -533,6 +592,20 @@ Future accountBotDeveloper(Ref ref, String uname) async { } } +@riverpod +Future> accountPublishers(Ref ref, String id) async { + final apiClient = ref.watch(apiClientProvider); + try { + final resp = await apiClient.get('/sphere/publishers/of/$id'); + return resp.data + .map((e) => SnPublisher.fromJson(e)) + .cast() + .toList(); + } catch (err) { + return []; + } +} + class AccountProfileScreen extends HookConsumerWidget { final String name; const AccountProfileScreen({super.key, required this.name}); @@ -625,245 +698,255 @@ class AccountProfileScreen extends HookConsumerWidget { ); return account.when( - data: - (data) => AppScaffold( - isNoBackground: false, - appBar: - isWideScreen(context) - ? AppBar( - foregroundColor: appbarColor.value, - leading: PageBackButton( - color: appbarColor.value, - shadows: [appbarShadow], - ), - flexibleSpace: Stack( - children: [ - Positioned.fill( - child: - data.profile.background?.id != null - ? CloudImageWidget( - file: data.profile.background, - ) - : Container( - color: - Theme.of( - context, - ).appBarTheme.backgroundColor, - ), - ), - FlexibleSpaceBar( - title: Text( - data.nick, - style: TextStyle( - color: - appbarColor.value ?? - Theme.of( - context, - ).appBarTheme.foregroundColor, - shadows: [appbarShadow], - ), - ), - ), - ], - ), - ) - : null, - body: - isWideScreen(context) - ? Row( + data: (data) { + final accountPublishers = ref.watch(accountPublishersProvider(data.id)); + return AppScaffold( + isNoBackground: false, + appBar: + isWideScreen(context) + ? AppBar( + foregroundColor: appbarColor.value, + leading: PageBackButton( + color: appbarColor.value, + shadows: [appbarShadow], + ), + flexibleSpace: Stack( children: [ - Flexible( - child: CustomScrollView( - slivers: [ - SliverToBoxAdapter( - child: _AccountBasicInfo( - data: data, - uname: name, - accountDeveloper: accountDeveloper, - ), - ), - if (data.badges.isNotEmpty) - SliverToBoxAdapter( - child: Card( - child: BadgeList( - badges: data.badges, - ).padding(horizontal: 26, vertical: 20), - ).padding(left: 2, right: 4), - ), - SliverToBoxAdapter( - child: Column( - spacing: 12, - children: [ - LevelingProgressCard( - level: data.profile.level, - experience: data.profile.experience, - progress: data.profile.levelingProgress, - ).padding(left: 2, right: 4), - if (data.profile.verification != null) - Card( - margin: EdgeInsets.zero, - child: VerificationStatusCard( - mark: data.profile.verification!, - ), - ), - ], - ).padding(horizontal: 4, top: 8), - ), - SliverToBoxAdapter( - child: _AccountProfileBio( - data: data, - ).padding(top: 4), - ), - if (data.profile.links.isNotEmpty) - SliverToBoxAdapter( - child: _AccountProfileLinks(data: data), - ), - SliverToBoxAdapter( - child: _AccountProfileDetail(data: data), - ), - ], - ), - ), - Flexible( - child: CustomScrollView( - slivers: [ - SliverGap(24), - if (user.value != null && !isCurrentUser) - SliverToBoxAdapter( - child: _AccountAction( - data: data, - accountRelationship: accountRelationship, - accountChat: accountChat, - relationshipAction: relationshipAction, - blockAction: blockAction, - directMessageAction: directMessageAction, - ), - ), - SliverToBoxAdapter( - child: Card( - child: FortuneGraphWidget( - events: accountEvents, - eventCalanderUser: data.name, - margin: EdgeInsets.zero, - ), - ), - ), - ], - ), - ), - ], - ).padding(horizontal: 24) - : CustomScrollView( - slivers: [ - SliverAppBar( - foregroundColor: appbarColor.value, - expandedHeight: 180, - pinned: true, - leading: PageBackButton( - color: appbarColor.value, - shadows: [appbarShadow], - ), - flexibleSpace: Stack( - children: [ - Positioned.fill( - child: - data.profile.background?.id != null - ? CloudImageWidget( - file: data.profile.background, - ) - : Container( - color: - Theme.of( - context, - ).appBarTheme.backgroundColor, - ), - ), - FlexibleSpaceBar( - title: Text( - data.nick, - style: TextStyle( + Positioned.fill( + child: + data.profile.background?.id != null + ? CloudImageWidget( + file: data.profile.background, + ) + : Container( color: - appbarColor.value ?? Theme.of( context, - ).appBarTheme.foregroundColor, - shadows: [appbarShadow], + ).appBarTheme.backgroundColor, ), - ), - ), - ], - ), ), - SliverToBoxAdapter( - child: _AccountBasicInfo( - data: data, - uname: name, - accountDeveloper: accountDeveloper, - ), - ), - if (data.badges.isNotEmpty) - SliverToBoxAdapter( - child: Card( - child: BadgeList( - badges: data.badges, - ).padding(horizontal: 26, vertical: 20), - ).padding(horizontal: 4), - ), - SliverToBoxAdapter( - child: Column( - children: [ - LevelingProgressCard( - level: data.profile.level, - experience: data.profile.experience, - progress: data.profile.levelingProgress, - ).padding(top: 8, horizontal: 8, bottom: 4), - if (data.profile.verification != null) - Card( - child: VerificationStatusCard( - mark: data.profile.verification!, - ), - ).padding(horizontal: 4), - ], - ), - ), - SliverToBoxAdapter( - child: _AccountProfileBio( - data: data, - ).padding(horizontal: 4), - ), - if (data.profile.links.isNotEmpty) - SliverToBoxAdapter( - child: _AccountProfileLinks( - data: data, - ).padding(horizontal: 4), - ), - SliverToBoxAdapter( - child: _AccountProfileDetail( - data: data, - ).padding(horizontal: 4), - ), - if (user.value != null && !isCurrentUser) - SliverToBoxAdapter( - child: _AccountAction( - data: data, - accountRelationship: accountRelationship, - accountChat: accountChat, - relationshipAction: relationshipAction, - blockAction: blockAction, - directMessageAction: directMessageAction, - ).padding(horizontal: 4), - ), - SliverToBoxAdapter( - child: Card( - child: FortuneGraphWidget( - events: accountEvents, - eventCalanderUser: data.name, + FlexibleSpaceBar( + title: Text( + data.nick, + style: TextStyle( + color: + appbarColor.value ?? + Theme.of(context).appBarTheme.foregroundColor, + shadows: [appbarShadow], ), - ).padding(horizontal: 4), + ), ), ], ), - ), + ) + : null, + body: + isWideScreen(context) + ? Row( + children: [ + Flexible( + child: CustomScrollView( + slivers: [ + SliverToBoxAdapter( + child: _AccountBasicInfo( + data: data, + uname: name, + accountDeveloper: accountDeveloper, + ), + ), + if (data.badges.isNotEmpty) + SliverToBoxAdapter( + child: Card( + child: BadgeList( + badges: data.badges, + ).padding(horizontal: 26, vertical: 20), + ).padding(left: 2, right: 4), + ), + SliverToBoxAdapter( + child: Column( + spacing: 12, + children: [ + LevelingProgressCard( + level: data.profile.level, + experience: data.profile.experience, + progress: data.profile.levelingProgress, + ).padding(left: 2, right: 4), + if (data.profile.verification != null) + Card( + margin: EdgeInsets.zero, + child: VerificationStatusCard( + mark: data.profile.verification!, + ), + ), + ], + ).padding(horizontal: 4, top: 8), + ), + SliverToBoxAdapter( + child: _AccountProfileBio( + data: data, + ).padding(top: 4), + ), + if (data.profile.links.isNotEmpty) + SliverToBoxAdapter( + child: _AccountProfileLinks(data: data), + ), + SliverToBoxAdapter( + child: _AccountProfileDetail(data: data), + ), + ], + ), + ), + Flexible( + child: CustomScrollView( + slivers: [ + SliverGap(24), + SliverToBoxAdapter( + child: _AccountPublisherList( + publishers: accountPublishers.value ?? [], + ), + ), + if (user.value != null && !isCurrentUser) + SliverToBoxAdapter( + child: _AccountAction( + data: data, + accountRelationship: accountRelationship, + accountChat: accountChat, + relationshipAction: relationshipAction, + blockAction: blockAction, + directMessageAction: directMessageAction, + ), + ), + SliverToBoxAdapter( + child: Card( + child: FortuneGraphWidget( + events: accountEvents, + eventCalanderUser: data.name, + margin: EdgeInsets.zero, + ), + ), + ), + ], + ), + ), + ], + ).padding(horizontal: 24) + : CustomScrollView( + slivers: [ + SliverAppBar( + foregroundColor: appbarColor.value, + expandedHeight: 180, + pinned: true, + leading: PageBackButton( + color: appbarColor.value, + shadows: [appbarShadow], + ), + flexibleSpace: Stack( + children: [ + Positioned.fill( + child: + data.profile.background?.id != null + ? CloudImageWidget( + file: data.profile.background, + ) + : Container( + color: + Theme.of( + context, + ).appBarTheme.backgroundColor, + ), + ), + FlexibleSpaceBar( + title: Text( + data.nick, + style: TextStyle( + color: + appbarColor.value ?? + Theme.of( + context, + ).appBarTheme.foregroundColor, + shadows: [appbarShadow], + ), + ), + ), + ], + ), + ), + SliverToBoxAdapter( + child: _AccountBasicInfo( + data: data, + uname: name, + accountDeveloper: accountDeveloper, + ), + ), + if (data.badges.isNotEmpty) + SliverToBoxAdapter( + child: Card( + child: BadgeList( + badges: data.badges, + ).padding(horizontal: 26, vertical: 20), + ).padding(horizontal: 4), + ), + SliverToBoxAdapter( + child: Column( + children: [ + LevelingProgressCard( + level: data.profile.level, + experience: data.profile.experience, + progress: data.profile.levelingProgress, + ).padding(top: 8, horizontal: 8, bottom: 4), + if (data.profile.verification != null) + Card( + child: VerificationStatusCard( + mark: data.profile.verification!, + ), + ).padding(horizontal: 4), + ], + ), + ), + SliverToBoxAdapter( + child: _AccountProfileBio( + data: data, + ).padding(horizontal: 4), + ), + if (data.profile.links.isNotEmpty) + SliverToBoxAdapter( + child: _AccountProfileLinks( + data: data, + ).padding(horizontal: 4), + ), + SliverToBoxAdapter( + child: _AccountPublisherList( + publishers: accountPublishers.value ?? [], + ).padding(horizontal: 4), + ), + SliverToBoxAdapter( + child: _AccountProfileDetail( + data: data, + ).padding(horizontal: 4), + ), + if (user.value != null && !isCurrentUser) + SliverToBoxAdapter( + child: _AccountAction( + data: data, + accountRelationship: accountRelationship, + accountChat: accountChat, + relationshipAction: relationshipAction, + blockAction: blockAction, + directMessageAction: directMessageAction, + ).padding(horizontal: 4), + ), + SliverToBoxAdapter( + child: Card( + child: FortuneGraphWidget( + events: accountEvents, + eventCalanderUser: data.name, + ), + ).padding(horizontal: 4), + ), + ], + ), + ); + }, error: (error, stackTrace) => AppScaffold( appBar: AppBar(leading: const PageBackButton()), diff --git a/lib/screens/account/profile.g.dart b/lib/screens/account/profile.g.dart index cc36a1c5..b977e0f7 100644 --- a/lib/screens/account/profile.g.dart +++ b/lib/screens/account/profile.g.dart @@ -762,5 +762,127 @@ class _AccountBotDeveloperProviderElement String get uname => (origin as AccountBotDeveloperProvider).uname; } +String _$accountPublishersHash() => r'25f5695b4a5154163d77f1769876d826bf736609'; + +/// See also [accountPublishers]. +@ProviderFor(accountPublishers) +const accountPublishersProvider = AccountPublishersFamily(); + +/// See also [accountPublishers]. +class AccountPublishersFamily extends Family>> { + /// See also [accountPublishers]. + const AccountPublishersFamily(); + + /// See also [accountPublishers]. + AccountPublishersProvider call(String id) { + return AccountPublishersProvider(id); + } + + @override + AccountPublishersProvider getProviderOverride( + covariant AccountPublishersProvider provider, + ) { + return call(provider.id); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'accountPublishersProvider'; +} + +/// See also [accountPublishers]. +class AccountPublishersProvider + extends AutoDisposeFutureProvider> { + /// See also [accountPublishers]. + AccountPublishersProvider(String id) + : this._internal( + (ref) => accountPublishers(ref as AccountPublishersRef, id), + from: accountPublishersProvider, + name: r'accountPublishersProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$accountPublishersHash, + dependencies: AccountPublishersFamily._dependencies, + allTransitiveDependencies: + AccountPublishersFamily._allTransitiveDependencies, + id: id, + ); + + AccountPublishersProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.id, + }) : super.internal(); + + final String id; + + @override + Override overrideWith( + FutureOr> Function(AccountPublishersRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: AccountPublishersProvider._internal( + (ref) => create(ref as AccountPublishersRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + id: id, + ), + ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _AccountPublishersProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is AccountPublishersProvider && other.id == id; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, id.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin AccountPublishersRef on AutoDisposeFutureProviderRef> { + /// The parameter `id` of this provider. + String get id; +} + +class _AccountPublishersProviderElement + extends AutoDisposeFutureProviderElement> + with AccountPublishersRef { + _AccountPublishersProviderElement(super.provider); + + @override + String get id => (origin as AccountPublishersProvider).id; +} + // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/screens/posts/pub_profile.dart b/lib/screens/posts/pub_profile.dart index 0c42bb07..567f028f 100644 --- a/lib/screens/posts/pub_profile.dart +++ b/lib/screens/posts/pub_profile.dart @@ -66,8 +66,8 @@ class _PublisherBasisWidget extends StatelessWidget { ), ), onTap: () { - Navigator.pop(context, true); if (data.account?.name != null) { + Navigator.pop(context, true); context.pushNamed( 'accountProfile', pathParameters: {'name': data.account!.name},