diff --git a/lib/route.dart b/lib/route.dart index b0899c1b..9c182366 100644 --- a/lib/route.dart +++ b/lib/route.dart @@ -6,7 +6,6 @@ import 'package:flutter/foundation.dart' show kIsWeb; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/screens/about.dart'; -import 'package:island/screens/account/credits.dart'; import 'package:island/screens/developers/app_detail.dart'; import 'package:island/screens/developers/bot_detail.dart'; import 'package:island/screens/developers/edit_app.dart'; @@ -655,11 +654,6 @@ final routerProvider = Provider((ref) { path: '/account/wallet', builder: (context, state) => const WalletScreen(), ), - GoRoute( - name: 'socialCredits', - path: '/account/credits', - builder: (context, state) => const SocialCreditsScreen(), - ), GoRoute( name: 'relationships', path: '/account/relationships', diff --git a/lib/screens/account.dart b/lib/screens/account.dart index bd2e2718..f0ae4a61 100644 --- a/lib/screens/account.dart +++ b/lib/screens/account.dart @@ -265,16 +265,6 @@ class AccountScreen extends HookConsumerWidget { context.pushNamed('webFeedMarketplace'); }, ), - ListTile( - minTileHeight: 48, - leading: const Icon(Symbols.star), - trailing: const Icon(Symbols.chevron_right), - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Text('credits').tr(), - onTap: () { - context.pushNamed('socialCredits'); - }, - ), ListTile( minTileHeight: 48, title: Text('abuseReport').tr(), diff --git a/lib/screens/account/credits.dart b/lib/screens/account/credits.dart index 5150fd42..71b3284e 100644 --- a/lib/screens/account/credits.dart +++ b/lib/screens/account/credits.dart @@ -4,7 +4,6 @@ import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/account.dart'; import 'package:island/pods/network.dart'; -import 'package:island/widgets/app_scaffold.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; @@ -59,94 +58,93 @@ class SocialCreditHistoryNotifier extends _$SocialCreditHistoryNotifier } } -class SocialCreditsScreen extends HookConsumerWidget { - const SocialCreditsScreen({super.key}); +class SocialCreditsTab extends HookConsumerWidget { + const SocialCreditsTab({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final socialCredits = ref.watch(socialCreditsProvider); - - return AppScaffold( - appBar: AppBar(title: Text('socialCredits').tr()), - body: Column( - children: [ - Card( - margin: EdgeInsets.only(left: 16, right: 16, top: 8), - child: socialCredits - .when( - data: - (credits) => Stack( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - credits < 100 - ? 'socialCreditsLevelPoor'.tr() - : credits < 150 - ? 'socialCreditsLevelNormal'.tr() - : credits < 200 - ? 'socialCreditsLevelGood'.tr() - : 'socialCreditsLevelExcellent'.tr(), - ).tr().bold().fontSize(20), - Text( - '${credits.toStringAsFixed(2)} pts', - ).fontSize(14), - const Gap(8), - LinearProgressIndicator(value: credits / 200), - ], + return Column( + children: [ + const Gap(8), + Card( + margin: const EdgeInsets.only(left: 16, right: 16, top: 8), + child: socialCredits + .when( + data: + (credits) => Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + credits < 100 + ? 'socialCreditsLevelPoor'.tr() + : credits < 150 + ? 'socialCreditsLevelNormal'.tr() + : credits < 200 + ? 'socialCreditsLevelGood'.tr() + : 'socialCreditsLevelExcellent'.tr(), + ).tr().bold().fontSize(20), + Text( + '${credits.toStringAsFixed(2)} pts', + ).fontSize(14), + const Gap(8), + LinearProgressIndicator(value: credits / 200), + ], + ), + Positioned( + right: 0, + top: 0, + child: IconButton( + onPressed: () {}, + icon: const Icon(Symbols.info), + tooltip: 'socialCreditsDescription'.tr(), ), - Positioned( - right: 0, - top: 0, - child: IconButton( - onPressed: () {}, - icon: const Icon(Symbols.info), - tooltip: 'socialCreditsDescription'.tr(), - ), - ), - ], + ), + ], + ), + error: (_, _) => Text('Error loading credits'), + loading: () => const LinearProgressIndicator(), + ) + .padding(horizontal: 20, vertical: 16), + ), + Expanded( + child: PagingHelperView( + provider: socialCreditHistoryNotifierProvider, + futureRefreshable: socialCreditHistoryNotifierProvider.future, + notifierRefreshable: socialCreditHistoryNotifierProvider.notifier, + contentBuilder: + (data, widgetCount, endItemView) => ListView.builder( + padding: EdgeInsets.zero, + itemCount: widgetCount, + itemBuilder: (context, index) { + if (index == widgetCount - 1) { + return endItemView; + } + final record = data.items[index]; + return ListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 24, ), - error: (_, _) => Text('Error loading credits'), - loading: () => const LinearProgressIndicator(), - ) - .padding(horizontal: 20, vertical: 16), - ), - Expanded( - child: PagingHelperView( - provider: socialCreditHistoryNotifierProvider, - futureRefreshable: socialCreditHistoryNotifierProvider.future, - notifierRefreshable: socialCreditHistoryNotifierProvider.notifier, - contentBuilder: - (data, widgetCount, endItemView) => ListView.builder( - padding: EdgeInsets.zero, - itemCount: widgetCount, - itemBuilder: (context, index) { - if (index == widgetCount - 1) { - return endItemView; - } - final record = data.items[index]; - return ListTile( - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Text(record.reason), - subtitle: Text( - DateFormat.yMMMd().format(record.createdAt), + title: Text(record.reason), + subtitle: Text( + DateFormat.yMMMd().format(record.createdAt), + ), + trailing: Text( + record.delta > 0 + ? '+${record.delta}' + : '${record.delta}', + style: TextStyle( + color: record.delta > 0 ? Colors.green : Colors.red, ), - trailing: Text( - record.delta > 0 - ? '+${record.delta}' - : '${record.delta}', - style: TextStyle( - color: record.delta > 0 ? Colors.green : Colors.red, - ), - ), - ); - }, - ), - ), + ), + ); + }, + ), ), - ], - ), + ), + ], ); } } diff --git a/lib/screens/account/leveling.dart b/lib/screens/account/leveling.dart index cfd29c29..f985e853 100644 --- a/lib/screens/account/leveling.dart +++ b/lib/screens/account/leveling.dart @@ -4,12 +4,12 @@ import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/account.dart'; import 'package:island/models/wallet.dart'; import 'package:island/pods/network.dart'; import 'package:island/pods/userinfo.dart'; +import 'package:island/screens/account/credits.dart'; import 'package:island/services/responsive.dart'; import 'package:island/services/time.dart'; import 'package:island/widgets/account/leveling_progress.dart'; @@ -89,7 +89,7 @@ class LevelingScreen extends HookConsumerWidget { } return DefaultTabController( - length: 2, + length: 3, child: AppScaffold( appBar: AppBar( title: Text('levelingProgress'.tr()), @@ -104,6 +104,15 @@ class LevelingScreen extends HookConsumerWidget { ), ), ), + Tab( + child: Text( + 'socialCredits'.tr(), + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).appBarTheme.foregroundColor!, + ), + ), + ), Tab( child: Text( 'stellarProgram'.tr(), @@ -119,6 +128,7 @@ class LevelingScreen extends HookConsumerWidget { body: TabBarView( children: [ _buildLevelingTab(context, ref, user.value!), + const SocialCreditsTab(), _buildStellarProgramTab(context, ref), ], ), @@ -164,10 +174,33 @@ class LevelingScreen extends HookConsumerWidget { ), const SliverGap(16), - // Stairs visualization with fixed height and horizontal scroll - SliverToBoxAdapter(child: _buildLevelStairs(context, currentLevel)), - const SliverGap(24), - + SliverToBoxAdapter( + child: Card( + margin: EdgeInsets.zero, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + LinearProgressIndicator( + value: currentLevel / 120, + minHeight: 10, + stopIndicatorRadius: 0, + trackGap: 0, + color: Theme.of(context).colorScheme.primary, + backgroundColor: + Theme.of(context).colorScheme.surfaceContainerHigh, + borderRadius: BorderRadius.circular(32), + ), + const Gap(8), + Text( + '${'levelingProgressLevel'.tr(args: [currentLevel.toString()])} / 120', + textAlign: TextAlign.right, + style: Theme.of(context).textTheme.bodySmall, + ), + ], + ).padding(horizontal: 16, top: 16, bottom: 12), + ), + ), + const SliverGap(16), // Leveling History SliverToBoxAdapter( child: Text( @@ -254,126 +287,6 @@ class LevelingScreen extends HookConsumerWidget { ); } - Widget _buildLevelStairs(BuildContext context, int currentLevel) { - const totalLevels = 14; - const stairHeight = 20.0; - const stairWidth = 50.0; - const containerHeight = 280.0; - - return Container( - height: containerHeight, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: Theme.of(context).colorScheme.outline.withOpacity(0.2), - ), - ), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.symmetric(horizontal: 16), - child: SizedBox( - width: (totalLevels * (stairWidth + 8)) + 40, - height: containerHeight, - child: CustomPaint( - painter: LevelStairsPainter( - currentLevel: currentLevel, - totalLevels: totalLevels, - primaryColor: Theme.of(context).colorScheme.primary, - surfaceColor: Theme.of(context).colorScheme.surfaceContainerHigh, - onSurfaceColor: Theme.of(context).colorScheme.onSurface, - stairHeight: stairHeight, - stairWidth: stairWidth, - ), - child: Stack( - children: List.generate(totalLevels, (index) { - final level = index + 1; - final isCompleted = level <= currentLevel; - final isCurrent = level == currentLevel; - - // Calculate position from bottom - final bottomPosition = 0.0; - final leftPosition = 20.0 + (index * (stairWidth + 8)); - - // Make higher levels progressively taller - final progressiveHeight = - 40.0 + (index * 15.0); // Base height + progressive increase - - return Positioned( - left: leftPosition, - bottom: bottomPosition, - child: Container( - width: stairWidth, - height: progressiveHeight, - decoration: BoxDecoration( - color: - isCompleted - ? Theme.of(context).colorScheme.primary - : Theme.of( - context, - ).colorScheme.surfaceContainerHigh, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(6), - topRight: Radius.circular(6), - ), - border: - isCurrent - ? Border.all( - color: Theme.of(context).colorScheme.primary, - width: 2, - ) - : null, - boxShadow: - isCurrent - ? [ - BoxShadow( - color: Theme.of( - context, - ).colorScheme.primary.withOpacity(0.3), - blurRadius: 6, - spreadRadius: 1, - ), - ] - : null, - ), - child: Padding( - padding: const EdgeInsets.only(top: 8), - child: Column( - children: [ - Text( - level.toString(), - style: GoogleFonts.robotoMono( - fontSize: 14, - fontWeight: FontWeight.bold, - color: - isCompleted - ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.onSurface, - ), - ), - if (isCurrent) ...[ - const Gap(4), - Container( - width: 4, - height: 4, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onPrimary, - shape: BoxShape.circle, - ), - ), - ], - ], - ), - ), - ), - ); - }), - ), - ), - ), - ), - ); - } - Widget _buildMembershipSection( BuildContext context, WidgetRef ref, diff --git a/lib/widgets/account/account_devices.dart b/lib/widgets/account/account_devices.dart index ba307e07..ed9070c3 100644 --- a/lib/widgets/account/account_devices.dart +++ b/lib/widgets/account/account_devices.dart @@ -290,8 +290,9 @@ class AccountSessionSheet extends HookConsumerWidget { } catch (err) { showErrorAlert(err); } finally { - if (context.mounted) + if (context.mounted) { hideLoadingModal(context); + } } } return confirm; diff --git a/lib/widgets/account/leveling_progress.dart b/lib/widgets/account/leveling_progress.dart index f10f1dc5..9553a21c 100644 --- a/lib/widgets/account/leveling_progress.dart +++ b/lib/widgets/account/leveling_progress.dart @@ -45,6 +45,8 @@ class LevelingProgressCard extends StatelessWidget { child: LinearProgressIndicator( minHeight: 4, value: progress / 100, + stopIndicatorRadius: 0, + trackGap: 0, color: Theme.of(context).colorScheme.primary, backgroundColor: Theme.of(context).colorScheme.surfaceContainerHigh, diff --git a/lib/widgets/chat/public_room_preview.dart b/lib/widgets/chat/public_room_preview.dart index 70ec6ad3..7d404e32 100644 --- a/lib/widgets/chat/public_room_preview.dart +++ b/lib/widgets/chat/public_room_preview.dart @@ -18,7 +18,7 @@ import "package:material_symbols_icons/material_symbols_icons.dart"; import "package:styled_widget/styled_widget.dart"; import "package:super_sliver_list/super_sliver_list.dart"; import "package:material_symbols_icons/symbols.dart"; -import "package:riverpod_annotation/riverpod_annotation.dart"; + import "package:island/screens/chat/chat.dart"; class PublicRoomPreview extends HookConsumerWidget {