From 0f6acd5167112a4fa32f2535acf9a1158abc0c85 Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Sun, 27 Apr 2025 14:02:58 +0100 Subject: [PATCH 01/14] feat: implement categories and hashtag API endpoints for create wager screen --- .../category_remote_datasource.dart | 57 +++++++ .../hashtag_remote_datasource.dart | 57 +++++++ .../category_repository_impl.dart | 14 ++ .../repositories/hashtag_repository_impl.dart | 14 ++ lib/domain/models/category.dart | 34 ++++ lib/domain/models/hashtag.dart | 34 ++++ .../repositories/category_repository.dart | 5 + .../repositories/hashtag_repository.dart | 5 + lib/domain/usecases/get_all_categories.dart | 12 ++ lib/domain/usecases/get_all_hashtags.dart | 12 ++ .../create_wager/create_wager_screen.dart | 155 +++++++++++++----- .../provider/category_provider.dart | 37 ++++- .../provider/hashtag_provider.dart | 51 ++++-- .../create_wager/state/category_state.dart | 39 +++++ .../create_wager/state/hashtag_state.dart | 38 +++++ lib/features/feature.dart | 2 + 16 files changed, 509 insertions(+), 57 deletions(-) create mode 100644 lib/data/datasources/category_remote_datasource.dart create mode 100644 lib/data/datasources/hashtag_remote_datasource.dart create mode 100644 lib/data/repositories/category_repository_impl.dart create mode 100644 lib/data/repositories/hashtag_repository_impl.dart create mode 100644 lib/domain/models/category.dart create mode 100644 lib/domain/models/hashtag.dart create mode 100644 lib/domain/repositories/category_repository.dart create mode 100644 lib/domain/repositories/hashtag_repository.dart create mode 100644 lib/domain/usecases/get_all_categories.dart create mode 100644 lib/domain/usecases/get_all_hashtags.dart create mode 100644 lib/features/create_wager/state/category_state.dart diff --git a/lib/data/datasources/category_remote_datasource.dart b/lib/data/datasources/category_remote_datasource.dart new file mode 100644 index 0000000..1651945 --- /dev/null +++ b/lib/data/datasources/category_remote_datasource.dart @@ -0,0 +1,57 @@ +import 'package:dio/dio.dart'; +import '../../core/error/failures.dart'; +import '../../core/network/api_client.dart'; +import '../../domain/models/category.dart'; +import '../../presentation/providers/auth_provider.dart'; +import '../../presentation/states/auth_state.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +abstract class CategoryRemoteDatasource { + Future getAllCategories(); +} + +class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource { + final ApiClient apiClient; + final Ref ref; + + CategoryRemoteDatasourceImpl(this.apiClient, this.ref); + + @override + Future getAllCategories() async { + try { + // Check if the user is authenticated + final authState = ref.read(authNotifierProvider); + if (authState is! AuthSuccess) { + throw ServerFailure( + message: 'Authentication required to fetch categories', + ); + } + + // Get the access token + final token = authState.response.tokens.accessToken; + + // Make the API request with the token + final response = await apiClient.get( + '/categories/all', + options: Options( + headers: { + 'Authorization': 'Bearer $token', + }, + ), + ); + + final data = response.data as Map; + return CategoriesResponse.fromJson(data); + } on DioException catch (e) { + throw ServerFailure( + message: e.message ?? 'An error occurred while fetching categories', + code: e.response?.statusCode, + ); + } catch (e) { + if (e is ServerFailure) { + rethrow; + } + throw ServerFailure(message: e.toString()); + } + } +} \ No newline at end of file diff --git a/lib/data/datasources/hashtag_remote_datasource.dart b/lib/data/datasources/hashtag_remote_datasource.dart new file mode 100644 index 0000000..418c99e --- /dev/null +++ b/lib/data/datasources/hashtag_remote_datasource.dart @@ -0,0 +1,57 @@ +import 'package:dio/dio.dart'; +import '../../core/error/failures.dart'; +import '../../core/network/api_client.dart'; +import '../../domain/models/hashtag.dart'; +import '../../presentation/providers/auth_provider.dart'; +import '../../presentation/states/auth_state.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +abstract class HashtagRemoteDatasource { + Future getAllHashtags(); +} + +class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource { + final ApiClient apiClient; + final Ref ref; + + HashtagRemoteDatasourceImpl(this.apiClient, this.ref); + + @override + Future getAllHashtags() async { + try { + // Check if the user is authenticated + final authState = ref.read(authNotifierProvider); + if (authState is! AuthSuccess) { + throw ServerFailure( + message: 'Authentication required to fetch hashtags', + ); + } + + // Get the access token + final token = authState.response.tokens.accessToken; + + // Make the API request with the token + final response = await apiClient.get( + '/hashtags', + options: Options( + headers: { + 'Authorization': 'Bearer $token', + }, + ), + ); + + final data = response.data as Map; + return HashtagsResponse.fromJson(data); + } on DioException catch (e) { + throw ServerFailure( + message: e.message ?? 'An error occurred while fetching hashtags', + code: e.response?.statusCode, + ); + } catch (e) { + if (e is ServerFailure) { + rethrow; + } + throw ServerFailure(message: e.toString()); + } + } +} \ No newline at end of file diff --git a/lib/data/repositories/category_repository_impl.dart b/lib/data/repositories/category_repository_impl.dart new file mode 100644 index 0000000..9559c9c --- /dev/null +++ b/lib/data/repositories/category_repository_impl.dart @@ -0,0 +1,14 @@ +import '../../domain/models/category.dart'; +import '../../domain/repositories/category_repository.dart'; +import '../datasources/category_remote_datasource.dart'; + +class CategoryRepositoryImpl implements CategoryRepository { + final CategoryRemoteDatasource remoteDatasource; + + CategoryRepositoryImpl(this.remoteDatasource); + + @override + Future getAllCategories() { + return remoteDatasource.getAllCategories(); + } +} \ No newline at end of file diff --git a/lib/data/repositories/hashtag_repository_impl.dart b/lib/data/repositories/hashtag_repository_impl.dart new file mode 100644 index 0000000..c32733f --- /dev/null +++ b/lib/data/repositories/hashtag_repository_impl.dart @@ -0,0 +1,14 @@ +import '../../domain/models/hashtag.dart'; +import '../../domain/repositories/hashtag_repository.dart'; +import '../datasources/hashtag_remote_datasource.dart'; + +class HashtagRepositoryImpl implements HashtagRepository { + final HashtagRemoteDatasource remoteDatasource; + + HashtagRepositoryImpl(this.remoteDatasource); + + @override + Future getAllHashtags() { + return remoteDatasource.getAllHashtags(); + } +} \ No newline at end of file diff --git a/lib/domain/models/category.dart b/lib/domain/models/category.dart new file mode 100644 index 0000000..8140390 --- /dev/null +++ b/lib/domain/models/category.dart @@ -0,0 +1,34 @@ +class Category { + final String id; + final String name; + final String createdAt; + final String updatedAt; + + Category({ + required this.id, + required this.name, + required this.createdAt, + required this.updatedAt, + }); + + factory Category.fromJson(Map json) => Category( + id: json['id'] ?? '', + name: json['name'] ?? '', + createdAt: json['createdAt'] ?? '', + updatedAt: json['updatedAt'] ?? '', + ); +} + +class CategoriesResponse { + final List categories; + + CategoriesResponse({required this.categories}); + + factory CategoriesResponse.fromJson(Map json) { + final List categoriesData = json['data'] ?? []; + final categories = categoriesData + .map((categoryJson) => Category.fromJson(categoryJson)) + .toList(); + return CategoriesResponse(categories: categories); + } +} \ No newline at end of file diff --git a/lib/domain/models/hashtag.dart b/lib/domain/models/hashtag.dart new file mode 100644 index 0000000..d3f42b7 --- /dev/null +++ b/lib/domain/models/hashtag.dart @@ -0,0 +1,34 @@ +class Hashtag { + final String id; + final String name; + final String createdAt; + final String updatedAt; + + Hashtag({ + required this.id, + required this.name, + required this.createdAt, + required this.updatedAt, + }); + + factory Hashtag.fromJson(Map json) => Hashtag( + id: json['id'] ?? '', + name: json['name'] ?? '', + createdAt: json['createdAt'] ?? '', + updatedAt: json['updatedAt'] ?? '', + ); +} + +class HashtagsResponse { + final List hashtags; + + HashtagsResponse({required this.hashtags}); + + factory HashtagsResponse.fromJson(Map json) { + final List hashtagsData = json['data'] ?? []; + final hashtags = hashtagsData + .map((hashtagJson) => Hashtag.fromJson(hashtagJson)) + .toList(); + return HashtagsResponse(hashtags: hashtags); + } +} \ No newline at end of file diff --git a/lib/domain/repositories/category_repository.dart b/lib/domain/repositories/category_repository.dart new file mode 100644 index 0000000..e41de6c --- /dev/null +++ b/lib/domain/repositories/category_repository.dart @@ -0,0 +1,5 @@ +import '../models/category.dart'; + +abstract class CategoryRepository { + Future getAllCategories(); +} \ No newline at end of file diff --git a/lib/domain/repositories/hashtag_repository.dart b/lib/domain/repositories/hashtag_repository.dart new file mode 100644 index 0000000..acd31d4 --- /dev/null +++ b/lib/domain/repositories/hashtag_repository.dart @@ -0,0 +1,5 @@ +import '../models/hashtag.dart'; + +abstract class HashtagRepository { + Future getAllHashtags(); +} \ No newline at end of file diff --git a/lib/domain/usecases/get_all_categories.dart b/lib/domain/usecases/get_all_categories.dart new file mode 100644 index 0000000..0a8f39f --- /dev/null +++ b/lib/domain/usecases/get_all_categories.dart @@ -0,0 +1,12 @@ +import '../models/category.dart'; +import '../repositories/category_repository.dart'; + +class GetAllCategories { + final CategoryRepository repository; + + GetAllCategories(this.repository); + + Future call() async { + return await repository.getAllCategories(); + } +} \ No newline at end of file diff --git a/lib/domain/usecases/get_all_hashtags.dart b/lib/domain/usecases/get_all_hashtags.dart new file mode 100644 index 0000000..c73038d --- /dev/null +++ b/lib/domain/usecases/get_all_hashtags.dart @@ -0,0 +1,12 @@ +import '../models/hashtag.dart'; +import '../repositories/hashtag_repository.dart'; + +class GetAllHashtags { + final HashtagRepository repository; + + GetAllHashtags(this.repository); + + Future call() async { + return await repository.getAllHashtags(); + } +} \ No newline at end of file diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index 918d2fb..1c7acd2 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -1,13 +1,67 @@ part of '../feature.dart'; -class CreateWagerScreen extends ConsumerWidget { +class CreateWagerScreen extends ConsumerStatefulWidget { const CreateWagerScreen({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => _CreateWagerScreenState(); +} + +class _CreateWagerScreenState extends ConsumerState { + bool _isLoadingCategories = false; + bool _isLoadingHashtags = false; + String? _categoriesError; + String? _hashtagsError; + + @override + void initState() { + super.initState(); + // Fetch categories and hashtags when screen initializes + SchedulerBinding.instance.addPostFrameCallback((_) { + // Initial fetch of categories and hashtags + _fetchCategoriesAndHashtags(); + }); + } + + void _fetchCategoriesAndHashtags() async { + setState(() { + _isLoadingCategories = true; + _isLoadingHashtags = true; + _categoriesError = null; + _hashtagsError = null; + }); + + try { + await ref.read(categoriesNotifierProvider.notifier).fetchCategories(); + } catch (e) { + setState(() { + _categoriesError = e.toString(); + }); + } finally { + setState(() { + _isLoadingCategories = false; + }); + } + + try { + await ref.read(hashtagsApiNotifierProvider.notifier).fetchHashtags(); + } catch (e) { + setState(() { + _hashtagsError = e.toString(); + }); + } finally { + setState(() { + _isLoadingHashtags = false; + }); + } + } + + @override + Widget build(BuildContext context) { final size = MediaQuery.of(context).size; final selectedHashtags = ref.watch(selectedHashtagsProvider); final selectedCategory = ref.watch(selectedCategoryProvider); + String getDisplayText() { if (selectedHashtags.isEmpty) { return 'addHashtags'.tr(); @@ -44,6 +98,23 @@ class CreateWagerScreen extends ConsumerWidget { verticalSpace(size.height * 0.02), if (context.isMobile) Divider(), verticalSpace(size.height * 0.03), + // Show API states if needed for debugging + if (_categoriesError != null || _hashtagsError != null) + Container( + padding: EdgeInsets.all(10), + margin: EdgeInsets.only(bottom: 10), + decoration: BoxDecoration( + color: Colors.red.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + _categoriesError != null + ? 'Error loading categories: $_categoriesError' + : 'Error loading hashtags: $_hashtagsError', + style: TextStyle(color: Colors.red), + ), + ), + // Continue with the rest of the UI Row( children: [ Expanded( @@ -60,11 +131,13 @@ class CreateWagerScreen extends ConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: Text( - selectedCategory ?? 'selectCategory'.tr(), - style: AppTheme.of(context).textMediumMedium, - overflow: TextOverflow.ellipsis, - ), + child: _isLoadingCategories + ? Center(child: SizedBox(height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2))) + : Text( + selectedCategory ?? 'selectCategory'.tr(), + style: AppTheme.of(context).textMediumMedium, + overflow: TextOverflow.ellipsis, + ), ), Icon(Icons.arrow_drop_down, color: context @@ -90,11 +163,13 @@ class CreateWagerScreen extends ConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: Text( - getDisplayText(), - style: AppTheme.of(context).textMediumMedium, - overflow: TextOverflow.ellipsis, - ), + child: _isLoadingHashtags + ? Center(child: SizedBox(height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2))) + : Text( + getDisplayText(), + style: AppTheme.of(context).textMediumMedium, + overflow: TextOverflow.ellipsis, + ), ), Icon(Icons.arrow_drop_down, color: context.primaryTextColor), @@ -586,15 +661,16 @@ class HashtagDialog extends ConsumerWidget { mainAxisSize: MainAxisSize.min, children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - horizontalSpace(140), - Text( - textAlign: TextAlign.center, - 'addHashtag(s)'.tr(), - style: AppTheme.of(context).titleExtraLarge24, + const SizedBox(width: 48), // Space for visual balance + Expanded( + child: Text( + 'addHashtag(s)'.tr(), + textAlign: TextAlign.center, + style: AppTheme.of(context).titleExtraLarge24, + ), ), - Spacer(), IconButton( icon: Icon( Icons.close, @@ -606,15 +682,10 @@ class HashtagDialog extends ConsumerWidget { ], ), verticalSpace(8), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - textAlign: TextAlign.center, - 'hashtagshelpotherusersfindyourwagereasilyandquickly'.tr(), - style: AppTheme.of(context).textMediumNormal, - ), - ], + Text( + 'hashtagshelpotherusersfindyourwagereasilyandquickly'.tr(), + textAlign: TextAlign.center, + style: AppTheme.of(context).textMediumNormal, ), verticalSpace(24), Wrap( @@ -650,15 +721,16 @@ class HashtagBottomSheet extends ConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - horizontalSpace(95), - Text( - textAlign: TextAlign.center, - 'addHashtag(s)'.tr(), - style: AppTheme.of(context).titleExtraLarge24, + const SizedBox(width: 48), // Space for visual balance + Expanded( + child: Text( + 'addHashtag(s)'.tr(), + textAlign: TextAlign.center, + style: AppTheme.of(context).titleExtraLarge24, + ), ), - Spacer(), IconButton( icon: Icon( Icons.close, @@ -670,15 +742,10 @@ class HashtagBottomSheet extends ConsumerWidget { ], ), verticalSpace(8), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - textAlign: TextAlign.center, - 'hashtagshelpotherusersfindyourwagereasilyandquickly'.tr(), - style: AppTheme.of(context).textMediumNormal, - ), - ], + Text( + 'hashtagshelpotherusersfindyourwagereasilyandquickly'.tr(), + textAlign: TextAlign.center, + style: AppTheme.of(context).textMediumNormal, ), verticalSpace(24), Wrap( diff --git a/lib/features/create_wager/provider/category_provider.dart b/lib/features/create_wager/provider/category_provider.dart index 3bc2221..9b1f47d 100644 --- a/lib/features/create_wager/provider/category_provider.dart +++ b/lib/features/create_wager/provider/category_provider.dart @@ -1,8 +1,39 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../../core/network/api_client.dart'; +import '../../../data/datasources/category_remote_datasource.dart'; +import '../../../data/repositories/category_repository_impl.dart'; +import '../../../domain/models/category.dart'; +import '../../../domain/usecases/get_all_categories.dart'; +import '../state/category_state.dart'; final selectedCategoryProvider = StateProvider((ref) => null); -final categoriesProvider = Provider>((ref) => [ +// Provider to supply the GetAllCategories use case +final getAllCategoriesUseCaseProvider = Provider((ref) { + final apiClient = ref.read(apiClientProvider); + final remoteDatasource = CategoryRemoteDatasourceImpl(apiClient, ref); + final repository = CategoryRepositoryImpl(remoteDatasource); + return GetAllCategories(repository); +}); + +// State notifier to handle category loading state +final categoriesNotifierProvider = + StateNotifierProvider((ref) { + final getAllCategories = ref.read(getAllCategoriesUseCaseProvider); + return CategoriesNotifier(getAllCategories); +}); + +// Provider to expose just the list of category names for UI consumption +final categoriesProvider = Provider>((ref) { + final state = ref.watch(categoriesNotifierProvider); + + if (state is CategoryLoaded) { + return state.categories.categories + .map((category) => category.name) + .toList(); + } else { + // Fallback if categories haven't loaded yet + return [ 'Sports', 'ESports', 'Politics', @@ -11,4 +42,6 @@ final categoriesProvider = Provider>((ref) => [ 'Entertainment', 'Games', 'Others' - ]); + ]; + } +}); diff --git a/lib/features/create_wager/provider/hashtag_provider.dart b/lib/features/create_wager/provider/hashtag_provider.dart index 9491016..a23ce70 100644 --- a/lib/features/create_wager/provider/hashtag_provider.dart +++ b/lib/features/create_wager/provider/hashtag_provider.dart @@ -1,5 +1,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:starkwager/features/create_wager/state/hashtag_state.dart'; +import '../../../core/network/api_client.dart'; +import '../../../data/datasources/hashtag_remote_datasource.dart'; +import '../../../data/repositories/hashtag_repository_impl.dart'; +import '../../../domain/usecases/get_all_hashtags.dart'; +import '../state/hashtag_state.dart'; final selectedHashtagsProvider = StateNotifierProvider>((ref) { @@ -11,15 +15,40 @@ final wagerTitleProvider = return WagerTitleNotifier(); }); +// Provider to supply the GetAllHashtags use case +final getAllHashtagsUseCaseProvider = Provider((ref) { + final apiClient = ref.read(apiClientProvider); + final remoteDatasource = HashtagRemoteDatasourceImpl(apiClient, ref); + final repository = HashtagRepositoryImpl(remoteDatasource); + return GetAllHashtags(repository); +}); + +// State notifier to handle hashtag loading state +final hashtagsApiNotifierProvider = + StateNotifierProvider((ref) { + final getAllHashtags = ref.read(getAllHashtagsUseCaseProvider); + return HashtagApiNotifier(getAllHashtags); +}); + +// Provider to expose just the list of hashtag names for UI consumption final hashtagsListProvider = Provider>((ref) { - return [ - 'Bitcoin', - 'STRKBet', - 'BTCto100k', - 'CryptoBetting', - 'BlockchainWager', - 'CryptoTrends', - 'Web3Challenge', - 'DeFiPrediction' - ]; + final state = ref.watch(hashtagsApiNotifierProvider); + + if (state is HashtagApiLoaded) { + return state.hashtags.hashtags + .map((hashtag) => hashtag.name) + .toList(); + } else { + // Fallback if hashtags haven't loaded yet + return [ + 'Bitcoin', + 'STRKBet', + 'BTCto100k', + 'CryptoBetting', + 'BlockchainWager', + 'CryptoTrends', + 'Web3Challenge', + 'DeFiPrediction' + ]; + } }); diff --git a/lib/features/create_wager/state/category_state.dart b/lib/features/create_wager/state/category_state.dart new file mode 100644 index 0000000..a10e27d --- /dev/null +++ b/lib/features/create_wager/state/category_state.dart @@ -0,0 +1,39 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../../domain/models/category.dart'; +import '../../../domain/usecases/get_all_categories.dart'; + +// Category States +abstract class CategoryState {} + +class CategoryInitial extends CategoryState {} + +class CategoryLoading extends CategoryState {} + +class CategoryLoaded extends CategoryState { + final CategoriesResponse categories; + CategoryLoaded(this.categories); +} + +class CategoryError extends CategoryState { + final String message; + CategoryError(this.message); +} + +// Category Notifier +class CategoriesNotifier extends StateNotifier { + final GetAllCategories getAllCategories; + + CategoriesNotifier(this.getAllCategories) : super(CategoryInitial()) { + fetchCategories(); + } + + Future fetchCategories() async { + try { + state = CategoryLoading(); + final categories = await getAllCategories(); + state = CategoryLoaded(categories); + } catch (e) { + state = CategoryError(e.toString()); + } + } +} \ No newline at end of file diff --git a/lib/features/create_wager/state/hashtag_state.dart b/lib/features/create_wager/state/hashtag_state.dart index 915e96d..5d43d20 100644 --- a/lib/features/create_wager/state/hashtag_state.dart +++ b/lib/features/create_wager/state/hashtag_state.dart @@ -1,4 +1,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../../domain/models/hashtag.dart'; +import '../../../domain/usecases/get_all_hashtags.dart'; class HashtagsNotifier extends StateNotifier> { HashtagsNotifier() : super({}); @@ -23,3 +25,39 @@ class WagerTitleNotifier extends StateNotifier { state = title; } } + +// API Hashtag States +abstract class HashtagApiState {} + +class HashtagApiInitial extends HashtagApiState {} + +class HashtagApiLoading extends HashtagApiState {} + +class HashtagApiLoaded extends HashtagApiState { + final HashtagsResponse hashtags; + HashtagApiLoaded(this.hashtags); +} + +class HashtagApiError extends HashtagApiState { + final String message; + HashtagApiError(this.message); +} + +// Hashtag API Notifier +class HashtagApiNotifier extends StateNotifier { + final GetAllHashtags getAllHashtags; + + HashtagApiNotifier(this.getAllHashtags) : super(HashtagApiInitial()) { + fetchHashtags(); + } + + Future fetchHashtags() async { + try { + state = HashtagApiLoading(); + final hashtags = await getAllHashtags(); + state = HashtagApiLoaded(hashtags); + } catch (e) { + state = HashtagApiError(e.toString()); + } + } +} diff --git a/lib/features/feature.dart b/lib/features/feature.dart index 84faa32..cb33a32 100644 --- a/lib/features/feature.dart +++ b/lib/features/feature.dart @@ -22,6 +22,8 @@ import 'package:starkwager/extensions/currency_extension.dart'; import 'package:starkwager/extensions/string_extension.dart'; import 'package:starkwager/features/create_wager/provider/hashtag_provider.dart'; import 'package:starkwager/features/create_wager/provider/stake_provider.dart'; +import 'package:starkwager/features/create_wager/state/category_state.dart'; +import 'package:starkwager/features/create_wager/state/hashtag_state.dart'; import 'package:starkwager/features/create_wager/widgets/wager_summary_cancel_claim.dart'; import 'package:starkwager/features/profile_setting/widget/theme_select_bottom_sheet.dart'; import 'package:starkwager/features/profile_setup/avatar_widget.dart'; From d5ca650ece2c4ba2f35e94205d2319a2d2dd113d Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Sun, 27 Apr 2025 14:12:56 +0100 Subject: [PATCH 02/14] style: apply dart format to fix formatting issues --- .../category_remote_datasource.dart | 6 +-- .../hashtag_remote_datasource.dart | 6 +-- .../category_repository_impl.dart | 6 +-- .../repositories/hashtag_repository_impl.dart | 6 +-- lib/domain/models/category.dart | 2 +- lib/domain/models/hashtag.dart | 2 +- .../repositories/category_repository.dart | 2 +- .../repositories/hashtag_repository.dart | 2 +- lib/domain/usecases/get_all_categories.dart | 2 +- lib/domain/usecases/get_all_hashtags.dart | 2 +- .../create_wager/create_wager_screen.dart | 49 ++++++++++++------- .../provider/category_provider.dart | 2 +- .../provider/hashtag_provider.dart | 6 +-- .../create_wager/state/category_state.dart | 2 +- 14 files changed, 53 insertions(+), 42 deletions(-) diff --git a/lib/data/datasources/category_remote_datasource.dart b/lib/data/datasources/category_remote_datasource.dart index 1651945..8f68b89 100644 --- a/lib/data/datasources/category_remote_datasource.dart +++ b/lib/data/datasources/category_remote_datasource.dart @@ -29,7 +29,7 @@ class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource { // Get the access token final token = authState.response.tokens.accessToken; - + // Make the API request with the token final response = await apiClient.get( '/categories/all', @@ -39,7 +39,7 @@ class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource { }, ), ); - + final data = response.data as Map; return CategoriesResponse.fromJson(data); } on DioException catch (e) { @@ -54,4 +54,4 @@ class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource { throw ServerFailure(message: e.toString()); } } -} \ No newline at end of file +} diff --git a/lib/data/datasources/hashtag_remote_datasource.dart b/lib/data/datasources/hashtag_remote_datasource.dart index 418c99e..59c3866 100644 --- a/lib/data/datasources/hashtag_remote_datasource.dart +++ b/lib/data/datasources/hashtag_remote_datasource.dart @@ -29,7 +29,7 @@ class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource { // Get the access token final token = authState.response.tokens.accessToken; - + // Make the API request with the token final response = await apiClient.get( '/hashtags', @@ -39,7 +39,7 @@ class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource { }, ), ); - + final data = response.data as Map; return HashtagsResponse.fromJson(data); } on DioException catch (e) { @@ -54,4 +54,4 @@ class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource { throw ServerFailure(message: e.toString()); } } -} \ No newline at end of file +} diff --git a/lib/data/repositories/category_repository_impl.dart b/lib/data/repositories/category_repository_impl.dart index 9559c9c..ba57fa3 100644 --- a/lib/data/repositories/category_repository_impl.dart +++ b/lib/data/repositories/category_repository_impl.dart @@ -4,11 +4,11 @@ import '../datasources/category_remote_datasource.dart'; class CategoryRepositoryImpl implements CategoryRepository { final CategoryRemoteDatasource remoteDatasource; - + CategoryRepositoryImpl(this.remoteDatasource); - + @override Future getAllCategories() { return remoteDatasource.getAllCategories(); } -} \ No newline at end of file +} diff --git a/lib/data/repositories/hashtag_repository_impl.dart b/lib/data/repositories/hashtag_repository_impl.dart index c32733f..07c8b01 100644 --- a/lib/data/repositories/hashtag_repository_impl.dart +++ b/lib/data/repositories/hashtag_repository_impl.dart @@ -4,11 +4,11 @@ import '../datasources/hashtag_remote_datasource.dart'; class HashtagRepositoryImpl implements HashtagRepository { final HashtagRemoteDatasource remoteDatasource; - + HashtagRepositoryImpl(this.remoteDatasource); - + @override Future getAllHashtags() { return remoteDatasource.getAllHashtags(); } -} \ No newline at end of file +} diff --git a/lib/domain/models/category.dart b/lib/domain/models/category.dart index 8140390..26a613b 100644 --- a/lib/domain/models/category.dart +++ b/lib/domain/models/category.dart @@ -31,4 +31,4 @@ class CategoriesResponse { .toList(); return CategoriesResponse(categories: categories); } -} \ No newline at end of file +} diff --git a/lib/domain/models/hashtag.dart b/lib/domain/models/hashtag.dart index d3f42b7..94f4b93 100644 --- a/lib/domain/models/hashtag.dart +++ b/lib/domain/models/hashtag.dart @@ -31,4 +31,4 @@ class HashtagsResponse { .toList(); return HashtagsResponse(hashtags: hashtags); } -} \ No newline at end of file +} diff --git a/lib/domain/repositories/category_repository.dart b/lib/domain/repositories/category_repository.dart index e41de6c..777bbd9 100644 --- a/lib/domain/repositories/category_repository.dart +++ b/lib/domain/repositories/category_repository.dart @@ -2,4 +2,4 @@ import '../models/category.dart'; abstract class CategoryRepository { Future getAllCategories(); -} \ No newline at end of file +} diff --git a/lib/domain/repositories/hashtag_repository.dart b/lib/domain/repositories/hashtag_repository.dart index acd31d4..0cb8b6b 100644 --- a/lib/domain/repositories/hashtag_repository.dart +++ b/lib/domain/repositories/hashtag_repository.dart @@ -2,4 +2,4 @@ import '../models/hashtag.dart'; abstract class HashtagRepository { Future getAllHashtags(); -} \ No newline at end of file +} diff --git a/lib/domain/usecases/get_all_categories.dart b/lib/domain/usecases/get_all_categories.dart index 0a8f39f..bbc4abd 100644 --- a/lib/domain/usecases/get_all_categories.dart +++ b/lib/domain/usecases/get_all_categories.dart @@ -9,4 +9,4 @@ class GetAllCategories { Future call() async { return await repository.getAllCategories(); } -} \ No newline at end of file +} diff --git a/lib/domain/usecases/get_all_hashtags.dart b/lib/domain/usecases/get_all_hashtags.dart index c73038d..147084d 100644 --- a/lib/domain/usecases/get_all_hashtags.dart +++ b/lib/domain/usecases/get_all_hashtags.dart @@ -9,4 +9,4 @@ class GetAllHashtags { Future call() async { return await repository.getAllHashtags(); } -} \ No newline at end of file +} diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index 1c7acd2..26c513f 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -61,7 +61,7 @@ class _CreateWagerScreenState extends ConsumerState { final size = MediaQuery.of(context).size; final selectedHashtags = ref.watch(selectedHashtagsProvider); final selectedCategory = ref.watch(selectedCategoryProvider); - + String getDisplayText() { if (selectedHashtags.isEmpty) { return 'addHashtags'.tr(); @@ -108,9 +108,9 @@ class _CreateWagerScreenState extends ConsumerState { borderRadius: BorderRadius.circular(8), ), child: Text( - _categoriesError != null - ? 'Error loading categories: $_categoriesError' - : 'Error loading hashtags: $_hashtagsError', + _categoriesError != null + ? 'Error loading categories: $_categoriesError' + : 'Error loading hashtags: $_hashtagsError', style: TextStyle(color: Colors.red), ), ), @@ -131,13 +131,20 @@ class _CreateWagerScreenState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: _isLoadingCategories - ? Center(child: SizedBox(height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2))) - : Text( - selectedCategory ?? 'selectCategory'.tr(), - style: AppTheme.of(context).textMediumMedium, - overflow: TextOverflow.ellipsis, - ), + child: _isLoadingCategories + ? Center( + child: SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + strokeWidth: 2))) + : Text( + selectedCategory ?? + 'selectCategory'.tr(), + style: AppTheme.of(context) + .textMediumMedium, + overflow: TextOverflow.ellipsis, + ), ), Icon(Icons.arrow_drop_down, color: context @@ -163,13 +170,19 @@ class _CreateWagerScreenState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: _isLoadingHashtags - ? Center(child: SizedBox(height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2))) - : Text( - getDisplayText(), - style: AppTheme.of(context).textMediumMedium, - overflow: TextOverflow.ellipsis, - ), + child: _isLoadingHashtags + ? Center( + child: SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + strokeWidth: 2))) + : Text( + getDisplayText(), + style: AppTheme.of(context) + .textMediumMedium, + overflow: TextOverflow.ellipsis, + ), ), Icon(Icons.arrow_drop_down, color: context.primaryTextColor), diff --git a/lib/features/create_wager/provider/category_provider.dart b/lib/features/create_wager/provider/category_provider.dart index 9b1f47d..f8957c5 100644 --- a/lib/features/create_wager/provider/category_provider.dart +++ b/lib/features/create_wager/provider/category_provider.dart @@ -26,7 +26,7 @@ final categoriesNotifierProvider = // Provider to expose just the list of category names for UI consumption final categoriesProvider = Provider>((ref) { final state = ref.watch(categoriesNotifierProvider); - + if (state is CategoryLoaded) { return state.categories.categories .map((category) => category.name) diff --git a/lib/features/create_wager/provider/hashtag_provider.dart b/lib/features/create_wager/provider/hashtag_provider.dart index a23ce70..30b20af 100644 --- a/lib/features/create_wager/provider/hashtag_provider.dart +++ b/lib/features/create_wager/provider/hashtag_provider.dart @@ -33,11 +33,9 @@ final hashtagsApiNotifierProvider = // Provider to expose just the list of hashtag names for UI consumption final hashtagsListProvider = Provider>((ref) { final state = ref.watch(hashtagsApiNotifierProvider); - + if (state is HashtagApiLoaded) { - return state.hashtags.hashtags - .map((hashtag) => hashtag.name) - .toList(); + return state.hashtags.hashtags.map((hashtag) => hashtag.name).toList(); } else { // Fallback if hashtags haven't loaded yet return [ diff --git a/lib/features/create_wager/state/category_state.dart b/lib/features/create_wager/state/category_state.dart index a10e27d..beabc1b 100644 --- a/lib/features/create_wager/state/category_state.dart +++ b/lib/features/create_wager/state/category_state.dart @@ -36,4 +36,4 @@ class CategoriesNotifier extends StateNotifier { state = CategoryError(e.toString()); } } -} \ No newline at end of file +} From 07461d55c7cf86692ad9130c430d199190f84dc8 Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Sun, 27 Apr 2025 14:18:27 +0100 Subject: [PATCH 03/14] fix: resolve analyzer warnings --- lib/features/create_wager/create_wager_screen.dart | 2 +- lib/features/create_wager/provider/category_provider.dart | 1 - lib/features/feature.dart | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index 26c513f..8779822 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -104,7 +104,7 @@ class _CreateWagerScreenState extends ConsumerState { padding: EdgeInsets.all(10), margin: EdgeInsets.only(bottom: 10), decoration: BoxDecoration( - color: Colors.red.withOpacity(0.1), + color: Colors.red.withValues(alpha: 26), borderRadius: BorderRadius.circular(8), ), child: Text( diff --git a/lib/features/create_wager/provider/category_provider.dart b/lib/features/create_wager/provider/category_provider.dart index f8957c5..0fbdad2 100644 --- a/lib/features/create_wager/provider/category_provider.dart +++ b/lib/features/create_wager/provider/category_provider.dart @@ -2,7 +2,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/network/api_client.dart'; import '../../../data/datasources/category_remote_datasource.dart'; import '../../../data/repositories/category_repository_impl.dart'; -import '../../../domain/models/category.dart'; import '../../../domain/usecases/get_all_categories.dart'; import '../state/category_state.dart'; diff --git a/lib/features/feature.dart b/lib/features/feature.dart index cb33a32..84faa32 100644 --- a/lib/features/feature.dart +++ b/lib/features/feature.dart @@ -22,8 +22,6 @@ import 'package:starkwager/extensions/currency_extension.dart'; import 'package:starkwager/extensions/string_extension.dart'; import 'package:starkwager/features/create_wager/provider/hashtag_provider.dart'; import 'package:starkwager/features/create_wager/provider/stake_provider.dart'; -import 'package:starkwager/features/create_wager/state/category_state.dart'; -import 'package:starkwager/features/create_wager/state/hashtag_state.dart'; import 'package:starkwager/features/create_wager/widgets/wager_summary_cancel_claim.dart'; import 'package:starkwager/features/profile_setting/widget/theme_select_bottom_sheet.dart'; import 'package:starkwager/features/profile_setup/avatar_widget.dart'; From aa71e8547f30ddc8d9652e046ba4a6eec3aa109e Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Mon, 28 Apr 2025 09:52:48 +0100 Subject: [PATCH 04/14] fix: handle array response format for categories and hashtags endpoints --- .../datasources/category_remote_datasource.dart | 8 ++++---- .../datasources/hashtag_remote_datasource.dart | 8 ++++---- lib/domain/models/category.dart | 14 ++++++++++++-- lib/domain/models/hashtag.dart | 14 ++++++++++++-- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/data/datasources/category_remote_datasource.dart b/lib/data/datasources/category_remote_datasource.dart index 8f68b89..8e9ddba 100644 --- a/lib/data/datasources/category_remote_datasource.dart +++ b/lib/data/datasources/category_remote_datasource.dart @@ -29,7 +29,7 @@ class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource { // Get the access token final token = authState.response.tokens.accessToken; - + // Make the API request with the token final response = await apiClient.get( '/categories/all', @@ -39,9 +39,9 @@ class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource { }, ), ); - - final data = response.data as Map; - return CategoriesResponse.fromJson(data); + + // Pass the direct response data to the fromJson method + return CategoriesResponse.fromJson(response.data); } on DioException catch (e) { throw ServerFailure( message: e.message ?? 'An error occurred while fetching categories', diff --git a/lib/data/datasources/hashtag_remote_datasource.dart b/lib/data/datasources/hashtag_remote_datasource.dart index 59c3866..358f785 100644 --- a/lib/data/datasources/hashtag_remote_datasource.dart +++ b/lib/data/datasources/hashtag_remote_datasource.dart @@ -29,7 +29,7 @@ class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource { // Get the access token final token = authState.response.tokens.accessToken; - + // Make the API request with the token final response = await apiClient.get( '/hashtags', @@ -39,9 +39,9 @@ class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource { }, ), ); - - final data = response.data as Map; - return HashtagsResponse.fromJson(data); + + // Pass the direct response data to the fromJson method + return HashtagsResponse.fromJson(response.data); } on DioException catch (e) { throw ServerFailure( message: e.message ?? 'An error occurred while fetching hashtags', diff --git a/lib/domain/models/category.dart b/lib/domain/models/category.dart index 26a613b..1aa2e14 100644 --- a/lib/domain/models/category.dart +++ b/lib/domain/models/category.dart @@ -24,8 +24,18 @@ class CategoriesResponse { CategoriesResponse({required this.categories}); - factory CategoriesResponse.fromJson(Map json) { - final List categoriesData = json['data'] ?? []; + factory CategoriesResponse.fromJson(dynamic json) { + // Handle both array response and object with data field + List categoriesData = []; + + if (json is List) { + // Direct array response + categoriesData = json; + } else if (json is Map) { + // Response with data field + categoriesData = json['data'] ?? []; + } + final categories = categoriesData .map((categoryJson) => Category.fromJson(categoryJson)) .toList(); diff --git a/lib/domain/models/hashtag.dart b/lib/domain/models/hashtag.dart index 94f4b93..4998bc4 100644 --- a/lib/domain/models/hashtag.dart +++ b/lib/domain/models/hashtag.dart @@ -24,8 +24,18 @@ class HashtagsResponse { HashtagsResponse({required this.hashtags}); - factory HashtagsResponse.fromJson(Map json) { - final List hashtagsData = json['data'] ?? []; + factory HashtagsResponse.fromJson(dynamic json) { + // Handle both array response and object with data field + List hashtagsData = []; + + if (json is List) { + // Direct array response + hashtagsData = json; + } else if (json is Map) { + // Response with data field + hashtagsData = json['data'] ?? []; + } + final hashtags = hashtagsData .map((hashtagJson) => Hashtag.fromJson(hashtagJson)) .toList(); From 6c3d07846dd21914ace2b6713db015a23cafd588 Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Mon, 28 Apr 2025 09:56:25 +0100 Subject: [PATCH 05/14] style: apply dart format to recent API response handling changes --- lib/data/datasources/category_remote_datasource.dart | 4 ++-- lib/data/datasources/hashtag_remote_datasource.dart | 4 ++-- lib/domain/models/category.dart | 4 ++-- lib/domain/models/hashtag.dart | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/data/datasources/category_remote_datasource.dart b/lib/data/datasources/category_remote_datasource.dart index 8e9ddba..3bc9359 100644 --- a/lib/data/datasources/category_remote_datasource.dart +++ b/lib/data/datasources/category_remote_datasource.dart @@ -29,7 +29,7 @@ class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource { // Get the access token final token = authState.response.tokens.accessToken; - + // Make the API request with the token final response = await apiClient.get( '/categories/all', @@ -39,7 +39,7 @@ class CategoryRemoteDatasourceImpl implements CategoryRemoteDatasource { }, ), ); - + // Pass the direct response data to the fromJson method return CategoriesResponse.fromJson(response.data); } on DioException catch (e) { diff --git a/lib/data/datasources/hashtag_remote_datasource.dart b/lib/data/datasources/hashtag_remote_datasource.dart index 358f785..9689c80 100644 --- a/lib/data/datasources/hashtag_remote_datasource.dart +++ b/lib/data/datasources/hashtag_remote_datasource.dart @@ -29,7 +29,7 @@ class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource { // Get the access token final token = authState.response.tokens.accessToken; - + // Make the API request with the token final response = await apiClient.get( '/hashtags', @@ -39,7 +39,7 @@ class HashtagRemoteDatasourceImpl implements HashtagRemoteDatasource { }, ), ); - + // Pass the direct response data to the fromJson method return HashtagsResponse.fromJson(response.data); } on DioException catch (e) { diff --git a/lib/domain/models/category.dart b/lib/domain/models/category.dart index 1aa2e14..7e483b5 100644 --- a/lib/domain/models/category.dart +++ b/lib/domain/models/category.dart @@ -27,7 +27,7 @@ class CategoriesResponse { factory CategoriesResponse.fromJson(dynamic json) { // Handle both array response and object with data field List categoriesData = []; - + if (json is List) { // Direct array response categoriesData = json; @@ -35,7 +35,7 @@ class CategoriesResponse { // Response with data field categoriesData = json['data'] ?? []; } - + final categories = categoriesData .map((categoryJson) => Category.fromJson(categoryJson)) .toList(); diff --git a/lib/domain/models/hashtag.dart b/lib/domain/models/hashtag.dart index 4998bc4..17d5bcc 100644 --- a/lib/domain/models/hashtag.dart +++ b/lib/domain/models/hashtag.dart @@ -27,7 +27,7 @@ class HashtagsResponse { factory HashtagsResponse.fromJson(dynamic json) { // Handle both array response and object with data field List hashtagsData = []; - + if (json is List) { // Direct array response hashtagsData = json; @@ -35,7 +35,7 @@ class HashtagsResponse { // Response with data field hashtagsData = json['data'] ?? []; } - + final hashtags = hashtagsData .map((hashtagJson) => Hashtag.fromJson(hashtagJson)) .toList(); From ee26c8ea02b4d3ea6dccd61675665e508421c587 Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Wed, 30 Apr 2025 22:45:36 +0100 Subject: [PATCH 06/14] fix: restore state imports in feature.dart to prevent UI issues --- lib/features/feature.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/features/feature.dart b/lib/features/feature.dart index 84faa32..cb33a32 100644 --- a/lib/features/feature.dart +++ b/lib/features/feature.dart @@ -22,6 +22,8 @@ import 'package:starkwager/extensions/currency_extension.dart'; import 'package:starkwager/extensions/string_extension.dart'; import 'package:starkwager/features/create_wager/provider/hashtag_provider.dart'; import 'package:starkwager/features/create_wager/provider/stake_provider.dart'; +import 'package:starkwager/features/create_wager/state/category_state.dart'; +import 'package:starkwager/features/create_wager/state/hashtag_state.dart'; import 'package:starkwager/features/create_wager/widgets/wager_summary_cancel_claim.dart'; import 'package:starkwager/features/profile_setting/widget/theme_select_bottom_sheet.dart'; import 'package:starkwager/features/profile_setup/avatar_widget.dart'; From 230f29100df8776dda18efbe3f3503e5bfa4784c Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Wed, 30 Apr 2025 22:53:02 +0100 Subject: [PATCH 07/14] fix: restore original UI for hashtag dialog and bottom sheet --- .../create_wager/create_wager_screen.dart | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index 8779822..3b5e960 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -143,8 +143,8 @@ class _CreateWagerScreenState extends ConsumerState { 'selectCategory'.tr(), style: AppTheme.of(context) .textMediumMedium, - overflow: TextOverflow.ellipsis, - ), + overflow: TextOverflow.ellipsis, + ), ), Icon(Icons.arrow_drop_down, color: context @@ -178,11 +178,11 @@ class _CreateWagerScreenState extends ConsumerState { child: CircularProgressIndicator( strokeWidth: 2))) : Text( - getDisplayText(), + getDisplayText(), style: AppTheme.of(context) .textMediumMedium, - overflow: TextOverflow.ellipsis, - ), + overflow: TextOverflow.ellipsis, + ), ), Icon(Icons.arrow_drop_down, color: context.primaryTextColor), @@ -674,16 +674,15 @@ class HashtagDialog extends ConsumerWidget { mainAxisSize: MainAxisSize.min, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.start, children: [ - const SizedBox(width: 48), // Space for visual balance - Expanded( - child: Text( - 'addHashtag(s)'.tr(), - textAlign: TextAlign.center, - style: AppTheme.of(context).titleExtraLarge24, - ), + horizontalSpace(140), + Text( + textAlign: TextAlign.center, + 'addHashtag(s)'.tr(), + style: AppTheme.of(context).titleExtraLarge24, ), + Spacer(), IconButton( icon: Icon( Icons.close, @@ -695,10 +694,15 @@ class HashtagDialog extends ConsumerWidget { ], ), verticalSpace(8), - Text( - 'hashtagshelpotherusersfindyourwagereasilyandquickly'.tr(), - textAlign: TextAlign.center, - style: AppTheme.of(context).textMediumNormal, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + textAlign: TextAlign.center, + 'hashtagshelpotherusersfindyourwagereasilyandquickly'.tr(), + style: AppTheme.of(context).textMediumNormal, + ), + ], ), verticalSpace(24), Wrap( @@ -734,16 +738,15 @@ class HashtagBottomSheet extends ConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.start, children: [ - const SizedBox(width: 48), // Space for visual balance - Expanded( - child: Text( - 'addHashtag(s)'.tr(), - textAlign: TextAlign.center, - style: AppTheme.of(context).titleExtraLarge24, - ), + horizontalSpace(95), + Text( + textAlign: TextAlign.center, + 'addHashtag(s)'.tr(), + style: AppTheme.of(context).titleExtraLarge24, ), + Spacer(), IconButton( icon: Icon( Icons.close, @@ -755,10 +758,15 @@ class HashtagBottomSheet extends ConsumerWidget { ], ), verticalSpace(8), - Text( - 'hashtagshelpotherusersfindyourwagereasilyandquickly'.tr(), - textAlign: TextAlign.center, - style: AppTheme.of(context).textMediumNormal, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + textAlign: TextAlign.center, + 'hashtagshelpotherusersfindyourwagereasilyandquickly'.tr(), + style: AppTheme.of(context).textMediumNormal, + ), + ], ), verticalSpace(24), Wrap( From 87b4fa5e9a2bdd0a43326cd7f29925552038fe2f Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:00:43 +0100 Subject: [PATCH 08/14] style: fix formatting in create_wager_screen.dart --- lib/features/create_wager/create_wager_screen.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index 3b5e960..1136a25 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -143,8 +143,8 @@ class _CreateWagerScreenState extends ConsumerState { 'selectCategory'.tr(), style: AppTheme.of(context) .textMediumMedium, - overflow: TextOverflow.ellipsis, - ), + overflow: TextOverflow.ellipsis, + ), ), Icon(Icons.arrow_drop_down, color: context @@ -178,11 +178,11 @@ class _CreateWagerScreenState extends ConsumerState { child: CircularProgressIndicator( strokeWidth: 2))) : Text( - getDisplayText(), + getDisplayText(), style: AppTheme.of(context) .textMediumMedium, - overflow: TextOverflow.ellipsis, - ), + overflow: TextOverflow.ellipsis, + ), ), Icon(Icons.arrow_drop_down, color: context.primaryTextColor), From 1754699415e6ba79fc8f2a8ccdeec9e7275e2b55 Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:04:59 +0100 Subject: [PATCH 09/14] fix: remove unused imports from feature.dart --- lib/features/feature.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/features/feature.dart b/lib/features/feature.dart index cb33a32..84faa32 100644 --- a/lib/features/feature.dart +++ b/lib/features/feature.dart @@ -22,8 +22,6 @@ import 'package:starkwager/extensions/currency_extension.dart'; import 'package:starkwager/extensions/string_extension.dart'; import 'package:starkwager/features/create_wager/provider/hashtag_provider.dart'; import 'package:starkwager/features/create_wager/provider/stake_provider.dart'; -import 'package:starkwager/features/create_wager/state/category_state.dart'; -import 'package:starkwager/features/create_wager/state/hashtag_state.dart'; import 'package:starkwager/features/create_wager/widgets/wager_summary_cancel_claim.dart'; import 'package:starkwager/features/profile_setting/widget/theme_select_bottom_sheet.dart'; import 'package:starkwager/features/profile_setup/avatar_widget.dart'; From e329a8e1539576ae1db18723f0e1af3e2f8a5f54 Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:39:44 +0100 Subject: [PATCH 10/14] fix: remove extra space below category list in bottom sheet --- .../create_wager/create_wager_screen.dart | 140 +++++++++--------- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index 1136a25..f11047e 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -394,10 +394,7 @@ class _CreateWagerScreenState extends ConsumerState { topRight: Radius.circular(20), ), ), - child: FractionallySizedBox( - heightFactor: 0.6, - child: child, - ), + child: child, ), ); } @@ -484,74 +481,85 @@ class _CreateWagerScreenState extends ConsumerState { } Widget buildBottomSheet(List categories) { - return SizedBox( - width: 500, - child: Column( - children: [ - Container( - padding: const EdgeInsets.only(right: 20, top: 10), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container(), - Container(), - Text( - 'selectCategory'.tr(), - style: AppTheme.of(context).titleExtraLarge24, - ), - IconButton( - icon: Icon( - Icons.close, - size: 24, - color: context.primaryTextColor, + return Padding( + padding: + EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: SizedBox( + width: 500, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: const EdgeInsets.only(right: 20, top: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container(), + Container(), + Text( + 'selectCategory'.tr(), + style: AppTheme.of(context).titleExtraLarge24, ), - onPressed: () => Navigator.pop(context), - ), - ], + IconButton( + icon: Icon( + Icons.close, + size: 24, + color: context.primaryTextColor, + ), + onPressed: () => Navigator.pop(context), + ), + ], + ), ), - ), - verticalSpace(30), - Expanded( - child: SingleChildScrollView( - child: Column( - children: categories.map((category) { - return Column( - children: [ - InkWell( - onTap: () { - Navigator.of(context).pop(category); - ref.read(selectedCategoryProvider.notifier).state = - category; - }, - child: Container( - width: double.infinity, - padding: EdgeInsets.symmetric( - vertical: 15, horizontal: 20), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - category, - style: AppTheme.of(context).textSmallMedium, - ), - SizedBox(width: 5), - if (ref.watch(selectedCategoryProvider) == - category) - SvgPicture.asset(AppIcons.checked), - ], + verticalSpace(20), + ConstrainedBox( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.5, + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: categories.map((category) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + onTap: () { + Navigator.of(context).pop(category); + ref + .read(selectedCategoryProvider.notifier) + .state = category; + }, + child: Container( + width: double.infinity, + padding: EdgeInsets.symmetric( + vertical: 15, horizontal: 20), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + category, + style: AppTheme.of(context).textSmallMedium, + ), + SizedBox(width: 5), + if (ref.watch(selectedCategoryProvider) == + category) + SvgPicture.asset(AppIcons.checked), + ], + ), ), ), - ), - if (category != categories[categories.length - 1]) - buildDotedBorder(context), - ], - ); - }).toList(), + if (category != categories[categories.length - 1]) + buildDotedBorder(context), + ], + ); + }).toList(), + ), ), ), - ), - ], + ], + ), ), ); } From 1addb600253ca7928de67701b76317ec110ae93c Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:55:19 +0100 Subject: [PATCH 11/14] Updated hashtag UI: centered Add Hashtag(s) title and implemented theme-aware colors --- .../create_wager/create_wager_screen.dart | 78 +++++++++++-------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index f11047e..38e2adb 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -681,23 +681,26 @@ class HashtagDialog extends ConsumerWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, + Stack( + alignment: Alignment.center, children: [ - horizontalSpace(140), - Text( - textAlign: TextAlign.center, - 'addHashtag(s)'.tr(), - style: AppTheme.of(context).titleExtraLarge24, + Align( + alignment: Alignment.center, + child: Text( + 'addHashtag(s)'.tr(), + style: AppTheme.of(context).titleExtraLarge24, + ), ), - Spacer(), - IconButton( - icon: Icon( - Icons.close, - size: 24, - color: context.primaryTextColor, + Align( + alignment: Alignment.centerRight, + child: IconButton( + icon: Icon( + Icons.close, + size: 24, + color: context.primaryTextColor, + ), + onPressed: () => Navigator.pop(context), ), - onPressed: () => Navigator.pop(context), ), ], ), @@ -745,23 +748,26 @@ class HashtagBottomSheet extends ConsumerWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, + Stack( + alignment: Alignment.center, children: [ - horizontalSpace(95), - Text( - textAlign: TextAlign.center, - 'addHashtag(s)'.tr(), - style: AppTheme.of(context).titleExtraLarge24, + Align( + alignment: Alignment.center, + child: Text( + 'addHashtag(s)'.tr(), + style: AppTheme.of(context).titleExtraLarge24, + ), ), - Spacer(), - IconButton( - icon: Icon( - Icons.close, - size: 24, - color: context.primaryTextColor, + Align( + alignment: Alignment.centerRight, + child: IconButton( + icon: Icon( + Icons.close, + size: 24, + color: context.primaryTextColor, + ), + onPressed: () => Navigator.pop(context), ), - onPressed: () => Navigator.pop(context), ), ], ), @@ -807,8 +813,12 @@ List _buildHashtagChips(BuildContext context, List hashtags, ), decoration: BoxDecoration( color: isSelected - ? context.primaryTextColor - : context.secondaryTextColor, + ? context.isDarkMode + ? AppColors.buttonColor // Yellow in dark mode + : AppColors.tabSelectedColor // Blue in light mode + : context.isDarkMode + ? AppColors.grayNeutral800 // Dark in dark mode + : AppColors.grayCool100, // Light gray in light mode borderRadius: BorderRadius.circular(20), ), child: Row( @@ -818,7 +828,9 @@ List _buildHashtagChips(BuildContext context, List hashtags, AppIcons.hashTagIcon, colorFilter: ColorFilter.mode( isSelected - ? context.primaryBackgroundColor + ? context.isDarkMode + ? AppColors.grayNeutral800 // Dark text on yellow in dark mode + : AppColors.white // White text on blue in light mode : context.primaryTextColor, BlendMode.srcIn), ), @@ -827,7 +839,9 @@ List _buildHashtagChips(BuildContext context, List hashtags, hashtag, style: AppTheme.of(context).textRegularMedium.copyWith( color: isSelected - ? context.primaryBackgroundColor + ? context.isDarkMode + ? AppColors.grayNeutral800 // Dark text on yellow in dark mode + : AppColors.white // White text on blue in light mode : context.primaryTextColor, ), ), From 133ecd162e737456041a50b3cd695b91e353782d Mon Sep 17 00:00:00 2001 From: akintewe <85641756+akintewe@users.noreply.github.com> Date: Wed, 30 Apr 2025 23:58:45 +0100 Subject: [PATCH 12/14] Fixed hashtag bottomsheet color to match category bottomsheet in dark mode --- lib/features/create_wager/create_wager_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index 38e2adb..bff8da3 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -741,7 +741,7 @@ class HashtagBottomSheet extends ConsumerWidget { return Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( - color: context.containerColor, + color: context.primaryBackgroundColor, borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), child: Column( From f7c4f6eb0c5858f01004046f09f1463098b36973 Mon Sep 17 00:00:00 2001 From: hoossayn Date: Fri, 27 Jun 2025 16:36:40 +0100 Subject: [PATCH 13/14] fix starknet package error --- .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle | 2 +- pubspec.lock | 150 ++++++++++++------ pubspec.yaml | 2 + 4 files changed, 107 insertions(+), 49 deletions(-) diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index b5fc5a7..5e6b542 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index 86c3a05..ccc1cdd 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.2.1" apply false + id "com.android.application" version "8.3.0" apply false id "org.jetbrains.kotlin.android" version "2.0.0" apply false } diff --git a/pubspec.lock b/pubspec.lock index 2888d1f..0e90e36 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -58,10 +58,10 @@ packages: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.13.0" avatar_plus: dependency: "direct main" description: @@ -78,14 +78,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + bip32: + dependency: transitive + description: + name: bip32 + sha256: "54787cd7a111e9d37394aabbf53d1fc5e2e0e0af2cd01c459147a97c0e3f8a97" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + bip39: + dependency: transitive + description: + name: bip39 + sha256: de1ee27ebe7d96b84bb3a04a4132a0a3007dcdd5ad27dd14aa87a29d97c45edc + url: "https://pub.dev" + source: hosted + version: "1.0.6" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" bs58: dependency: transitive description: @@ -94,6 +110,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + bs58check: + dependency: transitive + description: + name: bs58check + sha256: c4a164d42b25c2f6bc88a8beccb9fc7d01440f3c60ba23663a20a70faf484ea9 + url: "https://pub.dev" + source: hosted + version: "1.0.2" build: dependency: transitive description: @@ -186,10 +210,10 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" checked_yaml: dependency: transitive description: @@ -218,10 +242,10 @@ packages: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" code_builder: dependency: transitive description: @@ -242,10 +266,10 @@ packages: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" connectivity_plus: dependency: "direct main" description: @@ -402,10 +426,10 @@ packages: dependency: "direct main" description: name: easy_localization - sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201 + sha256: "0f5239c7b8ab06c66440cfb0e9aa4b4640429c6668d5a42fe389c5de42220b12" url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "3.0.7+1" easy_logger: dependency: transitive description: @@ -458,10 +482,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" ffi: dependency: transitive description: @@ -531,6 +555,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.1" + flutter_dotenv: + dependency: "direct main" + description: + name: flutter_dotenv + sha256: b7c7be5cd9f6ef7a78429cabd2774d3c4af50e79cb2b7593e3d5d763ef95c61b + url: "https://pub.dev" + source: hosted + version: "5.2.1" flutter_lints: dependency: "direct dev" description: @@ -634,14 +666,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + hex: + dependency: transitive + description: + name: hex + sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a" + url: "https://pub.dev" + source: hosted + version: "0.2.0" hotreloader: dependency: transitive description: name: hotreloader - sha256: ed56fdc1f3a8ac924e717257621d09e9ec20e308ab6352a73a50a1d7a4d9158e + sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "4.3.0" http: dependency: transitive description: @@ -734,10 +774,10 @@ packages: dependency: transitive description: name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" url: "https://pub.dev" source: hosted - version: "0.19.0" + version: "0.20.2" io: dependency: transitive description: @@ -782,18 +822,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "10.0.9" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -838,10 +878,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -854,10 +894,10 @@ packages: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.16.0" mime: dependency: transitive description: @@ -918,10 +958,10 @@ packages: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_drawing: dependency: transitive description: @@ -1275,10 +1315,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" sprintf: dependency: transitive description: @@ -1331,10 +1371,26 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + starknet: + dependency: "direct main" + description: + name: starknet + sha256: "748be6927a0c2eee3dbdfc795d4ad0ace09b8840bac267fa2e5ccee3ac096e96" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "0.1.2+1" + starknet_provider: + dependency: transitive + description: + name: starknet_provider + sha256: "74213a24a032e5ab599ff0cb35c6eaa4e1ee3e5ff4eece080e6f5884bc280923" + url: "https://pub.dev" + source: hosted + version: "0.1.1+2" state_notifier: dependency: transitive description: @@ -1347,10 +1403,10 @@ packages: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" stream_transform: dependency: transitive description: @@ -1363,10 +1419,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" synchronized: dependency: transitive description: @@ -1379,34 +1435,34 @@ packages: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test: dependency: "direct dev" description: name: test - sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" url: "https://pub.dev" source: hosted - version: "1.25.8" + version: "1.25.15" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.4" test_core: dependency: transitive description: name: test_core - sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.8" timing: dependency: transitive description: @@ -1531,10 +1587,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "15.0.0" wallet: dependency: transitive description: @@ -1664,5 +1720,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.5.0 <3.27.1" + dart: ">=3.7.0-0 <3.27.1" flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index b4c2e5a..04fe077 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,6 +46,8 @@ dependencies: dotted_line: ^3.2.3 avatar_plus: ^0.0.1 shimmer: ^3.0.0 + starknet: ^0.1.2+1 + flutter_dotenv: ^5.2.1 dev_dependencies: flutter_test: From 193284dfd4b3430078bb8a0db64470591c9d8066 Mon Sep 17 00:00:00 2001 From: hoossayn Date: Fri, 27 Jun 2025 16:46:06 +0100 Subject: [PATCH 14/14] format files --- lib/features/create_wager/create_wager_screen.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/features/create_wager/create_wager_screen.dart b/lib/features/create_wager/create_wager_screen.dart index bff8da3..86d8933 100644 --- a/lib/features/create_wager/create_wager_screen.dart +++ b/lib/features/create_wager/create_wager_screen.dart @@ -829,7 +829,8 @@ List _buildHashtagChips(BuildContext context, List hashtags, colorFilter: ColorFilter.mode( isSelected ? context.isDarkMode - ? AppColors.grayNeutral800 // Dark text on yellow in dark mode + ? AppColors + .grayNeutral800 // Dark text on yellow in dark mode : AppColors.white // White text on blue in light mode : context.primaryTextColor, BlendMode.srcIn), @@ -840,8 +841,10 @@ List _buildHashtagChips(BuildContext context, List hashtags, style: AppTheme.of(context).textRegularMedium.copyWith( color: isSelected ? context.isDarkMode - ? AppColors.grayNeutral800 // Dark text on yellow in dark mode - : AppColors.white // White text on blue in light mode + ? AppColors + .grayNeutral800 // Dark text on yellow in dark mode + : AppColors + .white // White text on blue in light mode : context.primaryTextColor, ), ),