mirror of
https://github.com/Uuttssaavv/flutter-clean-architecture-riverpod.git
synced 2025-08-06 16:19:42 +08:00
Merge pull request #6 from Uuttssaavv/incremental-updates
Incremental updates
This commit is contained in:
@ -728,7 +728,7 @@
|
||||
"languageVersion": "2.17"
|
||||
}
|
||||
],
|
||||
"generated": "2023-03-02T05:13:43.781981Z",
|
||||
"generated": "2023-03-07T21:36:00.991378Z",
|
||||
"generator": "pub",
|
||||
"generatorVersion": "2.18.4"
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
# This is a generated file; do not edit or check into version control.
|
||||
connectivity_plus=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.9/
|
||||
connectivity_plus_linux=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/
|
||||
connectivity_plus_macos=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_macos-1.2.6/
|
||||
connectivity_plus_web=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.5/
|
||||
connectivity_plus_windows=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_windows-1.2.2/
|
||||
path_provider_linux=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.1.8/
|
||||
path_provider_windows=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-2.1.3/
|
||||
shared_preferences=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.17/
|
||||
shared_preferences_android=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_android-2.0.15/
|
||||
shared_preferences_foundation=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_foundation-2.1.3/
|
||||
shared_preferences_linux=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_linux-2.1.3/
|
||||
shared_preferences_web=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-2.0.4/
|
||||
shared_preferences_windows=/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_windows-2.1.3/
|
@ -1 +0,0 @@
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity_plus","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.9/","native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_foundation-2.1.3/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.9/","native_build":true,"dependencies":[]},{"name":"shared_preferences_android","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_android-2.0.15/","native_build":true,"dependencies":[]}],"macos":[{"name":"connectivity_plus_macos","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_macos-1.2.6/","native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_foundation-2.1.3/","native_build":true,"dependencies":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","native_build":false,"dependencies":[]},{"name":"path_provider_linux","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-2.1.8/","native_build":false,"dependencies":[]},{"name":"shared_preferences_linux","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_linux-2.1.3/","native_build":false,"dependencies":["path_provider_linux"]}],"windows":[{"name":"connectivity_plus_windows","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_windows-1.2.2/","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-2.1.3/","native_build":false,"dependencies":[]},{"name":"shared_preferences_windows","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_windows-2.1.3/","native_build":false,"dependencies":["path_provider_windows"]}],"web":[{"name":"connectivity_plus_web","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.5/","dependencies":[]},{"name":"shared_preferences_web","path":"/Users/theutsavg/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-2.0.4/","dependencies":[]}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":["connectivity_plus_linux","connectivity_plus_macos","connectivity_plus_web","connectivity_plus_windows"]},{"name":"connectivity_plus_linux","dependencies":[]},{"name":"connectivity_plus_macos","dependencies":[]},{"name":"connectivity_plus_web","dependencies":[]},{"name":"connectivity_plus_windows","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2023-03-02 10:58:43.875612","version":"3.3.8"}
|
52
.gitignore
vendored
Normal file
52
.gitignore
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
#all generated code
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
/coverage/*
|
||||
!/coverage/lcov.info
|
||||
.vscode
|
@ -3,6 +3,7 @@ import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_project/features/dashboard/presentation/providers/dashboard_state_provider.dart';
|
||||
import 'package:flutter_project/features/dashboard/presentation/providers/state/dashboard_state.dart';
|
||||
import 'package:flutter_project/features/dashboard/presentation/widgets/dashboard_drawer.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class DashboardScreen extends ConsumerStatefulWidget {
|
||||
@ -51,6 +52,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = ref.watch(dashboardNotifierProvider);
|
||||
|
||||
ref.listen(
|
||||
dashboardNotifierProvider.select((value) => value),
|
||||
((DashboardState? previous, DashboardState next) {
|
||||
@ -67,8 +69,22 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
appBar: AppBar(
|
||||
title: isSearchActive
|
||||
? TextField(
|
||||
decoration: const InputDecoration(
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Search here',
|
||||
hintStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
border: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
),
|
||||
controller: searchController,
|
||||
onChanged: _onSearchChanged,
|
||||
@ -94,6 +110,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
drawer: const DashboardDrawer(),
|
||||
body: state.state == DashboardConcreteState.loading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: state.hasData
|
||||
@ -112,10 +129,17 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
leading: CircleAvatar(
|
||||
backgroundImage:
|
||||
NetworkImage(product.thumbnail)),
|
||||
title: Text(product.title),
|
||||
trailing: Text('\$${product.price}'),
|
||||
title: Text(
|
||||
product.title,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
trailing: Text(
|
||||
'\$${product.price}',
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
subtitle: Text(
|
||||
product.description,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
|
@ -0,0 +1,76 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_project/routes/app_route.gr.dart';
|
||||
import 'package:flutter_project/services/user_cache_service/domain/providers/current_user_provider.dart';
|
||||
import 'package:flutter_project/services/user_cache_service/domain/providers/user_cache_provider.dart';
|
||||
import 'package:flutter_project/shared/theme/app_theme.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class DashboardDrawer extends ConsumerWidget {
|
||||
const DashboardDrawer({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final currentUser = ref.watch(currentUserProvider).asData?.value;
|
||||
|
||||
return SafeArea(
|
||||
bottom: false,
|
||||
child: Drawer(
|
||||
child: Column(
|
||||
children: [
|
||||
UserAccountsDrawerHeader(
|
||||
margin: EdgeInsets.zero,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).backgroundColor,
|
||||
),
|
||||
accountName: Text(
|
||||
'${currentUser?.firstName}',
|
||||
style: Theme.of(context).textTheme.displaySmall,
|
||||
),
|
||||
accountEmail: Text(
|
||||
'${currentUser?.email}',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
currentAccountPicture: CircleAvatar(
|
||||
backgroundImage: NetworkImage('${currentUser?.image}'),
|
||||
),
|
||||
otherAccountsPictures: [
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
await ref.read(userLocalRepositoryProvider).deleteUser();
|
||||
// ignore: use_build_context_synchronously
|
||||
AutoRouter.of(context).pushAndPopUntil(
|
||||
LoginScreen(),
|
||||
predicate: (_) => false,
|
||||
);
|
||||
},
|
||||
child: CircleAvatar(
|
||||
child: Icon(
|
||||
Icons.logout,
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
ref.read(appThemeProvider.notifier).toggleTheme();
|
||||
},
|
||||
child: CircleAvatar(
|
||||
child: Icon(
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? Icons.light_mode
|
||||
: Icons.dark_mode,
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ class _SplashScreenState extends ConsumerState<SplashScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.blue.shade700,
|
||||
backgroundColor: Theme.of(context).backgroundColor,
|
||||
body: const Center(
|
||||
child: Text(
|
||||
'Splash Screen',
|
||||
|
@ -1,16 +1,8 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_project/routes/app_route.gr.dart';
|
||||
import 'package:flutter_project/shared/theme/app_theme.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final initializationProvider = FutureProvider<Unit>(
|
||||
(ref) async {
|
||||
// final authNotifier = ref.read(authNotifierProvider.notifier);
|
||||
// await authNotifier.checkIfAuthenticated();
|
||||
return unit;
|
||||
},
|
||||
);
|
||||
|
||||
class MyApp extends ConsumerWidget {
|
||||
MyApp({super.key});
|
||||
|
||||
@ -18,8 +10,12 @@ class MyApp extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final themeMode = ref.watch(appThemeProvider);
|
||||
return MaterialApp.router(
|
||||
title: 'Flutter TDD',
|
||||
theme: AppTheme.lightTheme,
|
||||
darkTheme: AppTheme.darkTheme,
|
||||
themeMode: themeMode,
|
||||
routeInformationParser: appRouter.defaultRouteParser(),
|
||||
routerDelegate: appRouter.delegate(),
|
||||
debugShowCheckedModeBanner: false,
|
||||
|
@ -35,14 +35,14 @@ class UserLocalDatasource extends UserDataSource {
|
||||
),
|
||||
);
|
||||
}
|
||||
final userJson = jsonDecode('$data');
|
||||
final userJson = jsonDecode(data.toString());
|
||||
|
||||
return Right(User.fromJson(userJson));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> saveUser({required User user}) async {
|
||||
return await stroageService.set(storageKey, user.toJson().toString());
|
||||
return await stroageService.set(storageKey, jsonEncode(user.toJson()));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -0,0 +1,10 @@
|
||||
import 'package:flutter_project/services/user_cache_service/domain/providers/user_cache_provider.dart';
|
||||
import 'package:flutter_project/shared/domain/models/models.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final currentUserProvider = FutureProvider<User?>((ref) async {
|
||||
final repository = ref.watch(userLocalRepositoryProvider);
|
||||
final eitherType = (await repository.fetchUser());
|
||||
|
||||
return eitherType.fold((l) => null, (r) => r);
|
||||
});
|
@ -3,3 +3,4 @@ import 'dart:io';
|
||||
final kTestMode = Platform.environment.containsKey('FLUTTER_TEST');
|
||||
const int PRODUCTS_PER_PAGE = 20;
|
||||
const String USER_LOCAL_STORAGE_KEY = 'user';
|
||||
const String APP_THEME_STORAGE_KEY = 'AppTheme';
|
||||
|
@ -1,20 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_project/shared/data/local/storage_service.dart';
|
||||
import 'package:flutter_project/shared/domain/providers/sharedpreferences_storage_service_provider.dart';
|
||||
import 'package:flutter_project/shared/globals.dart';
|
||||
import 'package:flutter_project/shared/theme/app_colors.dart';
|
||||
import 'package:flutter_project/shared/theme/test_styles.dart';
|
||||
import 'package:flutter_project/shared/theme/text_theme.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final appThemeProvider = StateNotifierProvider<AppThemeModeNotifier, ThemeMode>(
|
||||
(_) => AppThemeModeNotifier(),
|
||||
(ref) {
|
||||
final storage = ref.watch(storageServiceProvider);
|
||||
return AppThemeModeNotifier(storage);
|
||||
},
|
||||
);
|
||||
|
||||
class AppThemeModeNotifier extends StateNotifier<ThemeMode> {
|
||||
final StroageService stroageService;
|
||||
|
||||
ThemeMode currentTheme = ThemeMode.light;
|
||||
|
||||
AppThemeModeNotifier() : super(ThemeMode.light);
|
||||
AppThemeModeNotifier(this.stroageService) : super(ThemeMode.light) {
|
||||
getCurrentTheme();
|
||||
}
|
||||
|
||||
void toggleTheme() {
|
||||
state = state == ThemeMode.dark ? ThemeMode.light : ThemeMode.dark;
|
||||
stroageService.set(APP_THEME_STORAGE_KEY, state.name);
|
||||
}
|
||||
|
||||
void getCurrentTheme() async {
|
||||
final theme = await stroageService.get(APP_THEME_STORAGE_KEY);
|
||||
final value = ThemeMode.values.byName('${theme ?? 'light'}');
|
||||
state = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +73,7 @@ class AppTheme {
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
elevation: 0,
|
||||
backgroundColor: AppColors.white,
|
||||
backgroundColor: AppColors.primary,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user