Commit 1e34e480 authored by Ilham Maulana's avatar Ilham Maulana 💻

fix: session management with splash screen

parent 7ed39de1
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:library_app/src/screens/list/list_screen.dart';
import 'package:library_app/src/screens/profile_edit_screen.dart'; import 'package:library_app/src/screens/profile_edit_screen.dart';
import 'package:library_app/src/widgets/splash_screen.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:library_app/src/providers/auth_provider.dart'; import 'package:library_app/src/providers/auth_provider.dart';
import 'package:library_app/src/providers/navigations_provider.dart'; import 'package:library_app/src/providers/navigations_provider.dart';
import 'package:library_app/src/providers/book_provider.dart'; import 'package:library_app/src/providers/book_provider.dart';
import 'package:library_app/src/screens/form_screen.dart'; import 'package:library_app/src/screens/form_screen.dart';
import 'package:library_app/src/screens/list/list_screen.dart';
void main() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final isAuthenticated = prefs.getString('access_token') != null;
runApp(isAuthenticated ? const LibraryApp() : const LoginScreen()); void main() {
runApp(const LibraryApp());
} }
class LibraryApp extends StatefulWidget { class LibraryApp extends StatelessWidget {
const LibraryApp({super.key}); const LibraryApp({super.key});
@override
State<LibraryApp> createState() => _LibraryApp();
}
class _LibraryApp extends State<LibraryApp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const title = 'Library App'; const title = 'Library App';
...@@ -36,19 +28,19 @@ class _LibraryApp extends State<LibraryApp> { ...@@ -36,19 +28,19 @@ class _LibraryApp extends State<LibraryApp> {
routes: [ routes: [
GoRoute( GoRoute(
path: '/', path: '/',
builder: (context, state) => const ListScreen(), builder: (context, state) => const SplashScreen(),
), ),
GoRoute( GoRoute(
path: '/sign-up', path: '/home',
builder: (context, state) => const SignUpScreen(), builder: (context, state) => const ListScreen(),
), ),
GoRoute( GoRoute(
path: '/reset-password', path: '/login',
builder: (context, state) => const ResetPasswordScreen(), builder: (context, state) => const LoginScreen(),
), ),
GoRoute( GoRoute(
path: '/confirm-reset-password', path: '/sign-up',
builder: (context, state) => const ConfirmResetPasswordScreen(), builder: (context, state) => const SignUpScreen(),
), ),
GoRoute( GoRoute(
path: "/change-password", path: "/change-password",
......
...@@ -99,7 +99,7 @@ class AuthProvider with ChangeNotifier { ...@@ -99,7 +99,7 @@ class AuthProvider with ChangeNotifier {
await storeAccessToken(token); await storeAccessToken(token);
setInvalidUsernameOrPassword(false); setInvalidUsernameOrPassword(false);
if (context.mounted) context.go("/");
debugPrint("Login successful $token"); debugPrint("Login successful $token");
} else if (response.statusCode == 400) { } else if (response.statusCode == 400) {
setInvalidUsernameOrPassword(true); setInvalidUsernameOrPassword(true);
...@@ -116,7 +116,7 @@ class AuthProvider with ChangeNotifier { ...@@ -116,7 +116,7 @@ class AuthProvider with ChangeNotifier {
} }
} }
Future<void> signOut() async { Future<void> signOut(BuildContext context) async {
final token = await getAccessToken(); final token = await getAccessToken();
try { try {
...@@ -133,6 +133,7 @@ class AuthProvider with ChangeNotifier { ...@@ -133,6 +133,7 @@ class AuthProvider with ChangeNotifier {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('access_token'); prefs.remove('access_token');
resetAllState(); resetAllState();
if (context.mounted) context.go("/");
} else { } else {
debugPrint("Logout failed: ${response.statusCode} ${response.body}"); debugPrint("Logout failed: ${response.statusCode} ${response.body}");
} }
......
...@@ -86,7 +86,7 @@ class SignUpScreen extends StatelessWidget { ...@@ -86,7 +86,7 @@ class SignUpScreen extends StatelessWidget {
return FormScreen( return FormScreen(
title: title, title: title,
backRoute: "/", backRoute: "/login",
body: const SignUpForm(), body: const SignUpForm(),
); );
} }
...@@ -116,7 +116,7 @@ class ResetPasswordScreen extends StatelessWidget { ...@@ -116,7 +116,7 @@ class ResetPasswordScreen extends StatelessWidget {
return FormScreen( return FormScreen(
title: title, title: title,
backRoute: "/", backRoute: "/login",
body: const ResetPasswordForm(), body: const ResetPasswordForm(),
); );
} }
......
...@@ -15,9 +15,11 @@ class ListScreen extends StatefulWidget { ...@@ -15,9 +15,11 @@ class ListScreen extends StatefulWidget {
class _ListScreen extends State<ListScreen> { class _ListScreen extends State<ListScreen> {
@override @override
void initState() { void initState() {
if (context.mounted) { Future.delayed(Duration.zero, () {
Provider.of<NavigationsProvider>(context, listen: false).navigate(0); if (context.mounted) {
} Provider.of<NavigationsProvider>(context, listen: false).navigate(0);
}
});
super.initState(); super.initState();
} }
......
...@@ -140,13 +140,6 @@ class _LoginForm extends State<LoginForm> { ...@@ -140,13 +140,6 @@ class _LoginForm extends State<LoginForm> {
onPressed: () => context.go("/sign-up"), onPressed: () => context.go("/sign-up"),
), ),
), ),
SizedBox(
width: double.infinity,
child: TextButton(
child: const Text("Forgot Password"),
onPressed: () => context.go("/reset-password"),
),
),
], ],
), ),
], ],
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:go_router/go_router.dart';
import 'package:library_app/src/widgets/ui/button_custom.dart'; import 'package:library_app/src/widgets/ui/button_custom.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
...@@ -147,13 +146,6 @@ class _SignUpForm extends State<SignUpForm> { ...@@ -147,13 +146,6 @@ class _SignUpForm extends State<SignUpForm> {
child: const Text("Submit"), child: const Text("Submit"),
), ),
), ),
SizedBox(
width: double.infinity,
child: TextButton(
child: const Text("Login"),
onPressed: () => context.go("/"),
),
),
], ],
), ),
], ],
......
...@@ -17,9 +17,11 @@ class _HomePage extends State<HomePage> { ...@@ -17,9 +17,11 @@ class _HomePage extends State<HomePage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (context.mounted) { Future.delayed(Duration.zero, () {
Provider.of<AuthProvider>(context, listen: false).getUserDetail(); if (context.mounted) {
} Provider.of<AuthProvider>(context, listen: false).getUserDetail();
}
});
} }
@override @override
......
...@@ -27,9 +27,11 @@ class _AdminLoanList extends State<AdminLoanList> { ...@@ -27,9 +27,11 @@ class _AdminLoanList extends State<AdminLoanList> {
@override @override
void initState() { void initState() {
if (context.mounted) { Future.delayed(Duration.zero, () {
Provider.of<AuthProvider>(context, listen: false).getLoans(type); if (context.mounted) {
} Provider.of<AuthProvider>(context, listen: false).getLoans(type);
}
});
super.initState(); super.initState();
} }
......
...@@ -17,9 +17,11 @@ class LoanList extends StatefulWidget { ...@@ -17,9 +17,11 @@ class LoanList extends StatefulWidget {
class _LoanList extends State<LoanList> { class _LoanList extends State<LoanList> {
@override @override
void initState() { void initState() {
if (context.mounted) { Future.delayed(Duration.zero, () {
Provider.of<AuthProvider>(context, listen: false).getMemberLoan(); if (context.mounted) {
} Provider.of<AuthProvider>(context, listen: false).getMemberLoan();
}
});
super.initState(); super.initState();
} }
......
...@@ -16,11 +16,13 @@ class _Profile extends State<Profile> { ...@@ -16,11 +16,13 @@ class _Profile extends State<Profile> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (context.mounted) { Future.delayed(Duration.zero, () {
if (Provider.of<AuthProvider>(context, listen: false).user == null) { if (context.mounted) {
Provider.of<AuthProvider>(context, listen: false).getUserDetail(); if (Provider.of<AuthProvider>(context, listen: false).user == null) {
Provider.of<AuthProvider>(context, listen: false).getUserDetail();
}
} }
} });
} }
@override @override
...@@ -97,7 +99,7 @@ class _Profile extends State<Profile> { ...@@ -97,7 +99,7 @@ class _Profile extends State<Profile> {
OutlinedButton( OutlinedButton(
child: const Text("Log Out"), child: const Text("Log Out"),
onPressed: () { onPressed: () {
authProvider.signOut(); authProvider.signOut(context);
}, },
), ),
], ],
......
import "package:flutter/material.dart";
import "package:go_router/go_router.dart";
import "package:provider/provider.dart";
import 'package:flutter_svg/flutter_svg.dart';
import "package:library_app/src/providers/auth_provider.dart";
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
@override
State<SplashScreen> createState() => _SplashScreen();
}
class _SplashScreen extends State<SplashScreen> {
@override
void initState() {
super.initState();
isAutheticated();
}
void isAutheticated() async {
final token = await Provider.of<AuthProvider>(context, listen: false)
.getAccessToken();
if (token != null) {
Future.delayed(const Duration(milliseconds: 1500), () {
if (context.mounted) context.go("/home");
});
} else {
Future.delayed(const Duration(milliseconds: 1500), () {
if (context.mounted) context.go("/login");
});
}
}
@override
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
"assets/images/splash_image.svg",
semanticsLabel: "Splash Screen",
height: screenSize.height * 0.3,
),
const SizedBox(
height: 40.0,
),
const SizedBox(
width: 30.0,
height: 30.0,
child: CircularProgressIndicator(),
),
],
)),
);
}
}
...@@ -164,18 +164,18 @@ packages: ...@@ -164,18 +164,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.5" version: "10.0.4"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.5" version: "3.0.3"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
...@@ -212,18 +212,18 @@ packages: ...@@ -212,18 +212,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.11.1" version: "0.8.0"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.15.0" version: "1.12.0"
nested: nested:
dependency: transitive dependency: transitive
description: description:
...@@ -433,10 +433,10 @@ packages: ...@@ -433,10 +433,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.2" version: "0.7.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
...@@ -481,10 +481,10 @@ packages: ...@@ -481,10 +481,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.2.4" version: "14.2.1"
web: web:
dependency: transitive dependency: transitive
description: description:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment