Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions assets/svg/iconoir_coins-swap.svg

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
// SPDX-License-Identifier: ice License 1.0

import 'package:ion/app/features/feed/data/models/entities/generic_repost.f.dart';
import 'package:ion/app/features/feed/providers/user_posts_data_source_provider.r.dart';
import 'package:ion/app/features/ion_connect/model/ion_connect_entity.dart';
import 'package:ion/app/features/ion_connect/providers/entities_paged_data_provider.m.dart';
import 'package:ion/app/features/tokenized_communities/models/entities/community_token_action.f.dart';
import 'package:ion/app/features/tokenized_communities/models/entities/community_token_definition.f.dart';
import 'package:ion/app/features/tokenized_communities/utils/ion_connect_entity_extension.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'user_holdings_provider.r.g.dart';
part 'user_holdings_tab_provider.r.g.dart';

@riverpod
class UserHoldings extends _$UserHoldings with DelegatedPagedNotifier {
class UserHoldingsTab extends _$UserHoldingsTab with DelegatedPagedNotifier {
@override
({Iterable<IonConnectEntity>? items, bool hasMore}) build(String pubkey) {
final dataSources = ref.watch(userPostsDataSourceProvider(pubkey));
Expand All @@ -30,7 +28,7 @@ class UserHoldings extends _$UserHoldings with DelegatedPagedNotifier {
}

// Filter to include only tokenized community entities
final holdingsItems = allItems.where(_isTokenizedCommunityEntity);
final holdingsItems = allItems.where((entity) => entity.isTokenizedCommunityEntity);

// If filtered items are empty but we've loaded data, show empty state
// (set hasMore to false to prevent infinite loading)
Expand All @@ -47,12 +45,4 @@ class UserHoldings extends _$UserHoldings with DelegatedPagedNotifier {
}
return ref.read(entitiesPagedDataProvider(dataSources).notifier);
}

bool _isTokenizedCommunityEntity(IonConnectEntity entity) {
return entity is CommunityTokenActionEntity ||
entity is CommunityTokenDefinitionEntity ||
(entity is GenericRepostEntity &&
(entity.data.kind == GenericRepostEntity.communityTokenDefinitionRepostKind ||
entity.data.kind == GenericRepostEntity.communityTokenActionRepostKind));
}
}
15 changes: 3 additions & 12 deletions lib/app/features/feed/providers/user_posts_provider.r.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import 'package:ion/app/features/feed/providers/repost_notifier.r.dart';
import 'package:ion/app/features/feed/providers/user_posts_data_source_provider.r.dart';
import 'package:ion/app/features/ion_connect/model/ion_connect_entity.dart';
import 'package:ion/app/features/ion_connect/providers/entities_paged_data_provider.m.dart';
import 'package:ion/app/features/tokenized_communities/models/entities/community_token_action.f.dart';
import 'package:ion/app/features/tokenized_communities/models/entities/community_token_definition.f.dart';
import 'package:ion/app/features/tokenized_communities/utils/ion_connect_entity_extension.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'user_posts_provider.r.g.dart';
Expand Down Expand Up @@ -47,7 +46,7 @@ class UserPosts extends _$UserPosts with DelegatedPagedNotifier {
}

// Filter to exclude tokenized community entities (those go to Holdings tab)
final nonTokenizedItems = allItems.where((entity) => !_isTokenizedCommunityEntity(entity));
final nonTokenizedItems = allItems.where((entity) => !entity.isTokenizedCommunityEntity);

// If filtered items are empty but we've loaded data, show empty state
// (set hasMore to false to prevent infinite loading)
Expand All @@ -71,7 +70,7 @@ class UserPosts extends _$UserPosts with DelegatedPagedNotifier {
}

// Exclude tokenized community entities (those go to Holdings tab)
if (_isTokenizedCommunityEntity(entity)) {
if (entity.isTokenizedCommunityEntity) {
return false;
}

Expand All @@ -85,12 +84,4 @@ class UserPosts extends _$UserPosts with DelegatedPagedNotifier {
entity is RepostEntity ||
entity is ArticleEntity;
}

bool _isTokenizedCommunityEntity(IonConnectEntity entity) {
return entity is CommunityTokenActionEntity ||
entity is CommunityTokenDefinitionEntity ||
(entity is GenericRepostEntity &&
(entity.data.kind == GenericRepostEntity.communityTokenDefinitionRepostKind ||
entity.data.kind == GenericRepostEntity.communityTokenActionRepostKind));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: ice License 1.0

import 'package:ion/app/features/feed/data/models/entities/generic_repost.f.dart';
import 'package:ion/app/features/ion_connect/model/ion_connect_entity.dart';
import 'package:ion/app/features/tokenized_communities/models/entities/community_token_action.f.dart';
import 'package:ion/app/features/tokenized_communities/models/entities/community_token_definition.f.dart';

extension IsTokenizedCommunityEntityExtension on IonConnectEntity {
bool get isTokenizedCommunityEntity {
return this is CommunityTokenActionEntity ||
this is CommunityTokenDefinitionEntity ||
(this is GenericRepostEntity &&
((this as GenericRepostEntity).data.kind ==
GenericRepostEntity.communityTokenDefinitionRepostKind ||
(this as GenericRepostEntity).data.kind ==
GenericRepostEntity.communityTokenActionRepostKind));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// SPDX-License-Identifier: ice License 1.0

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:ion/app/extensions/extensions.dart';
import 'package:ion/app/features/user/pages/profile_page/components/tabs/user_holdings_list_item.dart';
import 'package:ion/app/features/user/providers/user_holdings_provider.r.dart';
import 'package:ion/app/features/user/providers/user_metadata_provider.r.dart';
import 'package:ion/app/router/app_routes.gr.dart';
import 'package:ion/generated/assets.gen.dart';

class HoldingsList extends ConsumerWidget {
const HoldingsList({
required this.pubkey,
super.key,
});

final String pubkey;

@override
Widget build(BuildContext context, WidgetRef ref) {
final userMetadata = ref.watch(userMetadataProvider(pubkey)).valueOrNull;
final holderAddress = userMetadata?.toEventReference().toString();

if (holderAddress == null) {
return const SizedBox.shrink();
}

final holdingsAsync = ref.watch(userHoldingsProvider(holderAddress));

return holdingsAsync.when(
data: (holdingsData) {
final holdings = holdingsData.items;
final totalHoldingsCount = holdingsData.totalHoldings;

if (totalHoldingsCount == 0 || holdings.isEmpty) {
return const SizedBox.shrink();
}

return Container(
color: context.theme.appColors.secondaryBackground,
padding: EdgeInsets.symmetric(horizontal: 16.0.s, vertical: 12.0.s),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_Header(holdingsCount: totalHoldingsCount, holderAddress: holderAddress),
SizedBox(height: 14.0.s),
...holdings.asMap().entries.map(
(entry) {
final index = entry.key;
final token = entry.value;
final isLast = index == holdings.length - 1;
return Padding(
padding: EdgeInsetsDirectional.only(bottom: isLast ? 0.0 : 14.0.s),
child: UserHoldingsListItem(token: token),
);
},
),
],
),
);
},
loading: () => const SizedBox.shrink(),
error: (_, __) => const SizedBox.shrink(),
);
}
}

class _Header extends StatelessWidget {
const _Header({
required this.holdingsCount,
required this.holderAddress,
});

final int holdingsCount;
final String holderAddress;

@override
Widget build(BuildContext context) {
final colors = context.theme.appColors;
final texts = context.theme.appTextThemes;

return Row(
children: [
Assets.svg.iconTabsCoins.icon(
size: 18.0.s,
color: colors.onTertiaryBackground,
),
SizedBox(width: 6.0.s),
Text(
context.i18n.profile_holdings_with_count(holdingsCount),
style: texts.subtitle3.copyWith(
color: colors.onTertiaryBackground,
),
),
const Spacer(),
GestureDetector(
onTap: () {
UserHoldingsRoute(holderAddress: holderAddress).push<void>(context);
},
behavior: HitTestBehavior.opaque,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 6.0.s, vertical: 4.0.s),
child: Text(
context.i18n.core_view_all,
style: texts.caption.copyWith(
color: colors.primaryAccent,
),
),
),
),
],
);
}
}
Loading