added splash screen
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
@@ -4,6 +4,7 @@ class AssetsManager {
|
||||
//logo
|
||||
static const logoSmall = 'assets/icons/logo_small.svg';
|
||||
static const logoBig = 'assets/icons/logo_big.svg';
|
||||
static const logoBigPng = 'assets/pngs/logo-big.png';
|
||||
|
||||
//bottom navigation
|
||||
static const homeActive = 'assets/icons/home_active.svg';
|
||||
|
||||
@@ -12,6 +12,7 @@ import '../../views/final_completion_of_documents/pages/final_completion_of_docu
|
||||
import '../../views/forgot_password/pages/forgot_password_screen.dart';
|
||||
import '../../views/notification/pages/notification_screen.dart';
|
||||
import '../../views/profile/pages/profile_screen.dart';
|
||||
import '../../views/splash/pages/splash_screen.dart';
|
||||
import '../../views/tenders/pages/tenders_screen.dart';
|
||||
import '../../views/your_tenders/pages/your_tenders_screen.dart';
|
||||
import 'app_shell/app_shell_screen.dart';
|
||||
@@ -31,7 +32,7 @@ final GlobalKey<NavigatorState> notificationNavigatorKey =
|
||||
// Main app router
|
||||
final GoRouter appRouter = GoRouter(
|
||||
routes: $appRoutes,
|
||||
initialLocation: '/login',
|
||||
initialLocation: '/splash',
|
||||
navigatorKey: rootNavigatorKey,
|
||||
);
|
||||
|
||||
@@ -46,6 +47,17 @@ class LoginScreenRoute extends GoRouteData with _$LoginScreenRoute {
|
||||
}
|
||||
}
|
||||
|
||||
// splash route - outside the shell
|
||||
@TypedGoRoute<SplashScreenRoute>(path: '/splash')
|
||||
class SplashScreenRoute extends GoRouteData with _$SplashScreenRoute {
|
||||
const SplashScreenRoute();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
return const SplashScreen();
|
||||
}
|
||||
}
|
||||
|
||||
// Shell route with bottom navigation using StatefulShellRoute.indexedStack
|
||||
@TypedStatefulShellRoute<AppShellRouteData>(
|
||||
branches: <TypedStatefulShellBranch<StatefulShellBranchData>>[
|
||||
|
||||
@@ -8,6 +8,7 @@ part of 'app_routes.dart';
|
||||
|
||||
List<RouteBase> get $appRoutes => [
|
||||
$loginScreenRoute,
|
||||
$splashScreenRoute,
|
||||
$appShellRouteData,
|
||||
$yourTendersRouteData,
|
||||
$finalCompletionOfDocumentsRouteData,
|
||||
@@ -43,6 +44,33 @@ mixin _$LoginScreenRoute on GoRouteData {
|
||||
void replace(BuildContext context) => context.replace(location);
|
||||
}
|
||||
|
||||
RouteBase get $splashScreenRoute => GoRouteData.$route(
|
||||
path: '/splash',
|
||||
|
||||
factory: _$SplashScreenRoute._fromState,
|
||||
);
|
||||
|
||||
mixin _$SplashScreenRoute on GoRouteData {
|
||||
static SplashScreenRoute _fromState(GoRouterState state) =>
|
||||
const SplashScreenRoute();
|
||||
|
||||
@override
|
||||
String get location => GoRouteData.$location('/splash');
|
||||
|
||||
@override
|
||||
void go(BuildContext context) => context.go(location);
|
||||
|
||||
@override
|
||||
Future<T?> push<T>(BuildContext context) => context.push<T>(location);
|
||||
|
||||
@override
|
||||
void pushReplacement(BuildContext context) =>
|
||||
context.pushReplacement(location);
|
||||
|
||||
@override
|
||||
void replace(BuildContext context) => context.replace(location);
|
||||
}
|
||||
|
||||
RouteBase get $appShellRouteData => StatefulShellRouteData.$route(
|
||||
parentNavigatorKey: AppShellRouteData.$parentNavigatorKey,
|
||||
factory: $AppShellRouteDataExtension._fromState,
|
||||
|
||||
@@ -47,4 +47,8 @@ class AuthRepository {
|
||||
}) async {
|
||||
return _authService.verifyOtp(code: code, email: email);
|
||||
}
|
||||
|
||||
Future<Result<bool>> checkIsLoggedIn() async {
|
||||
return _authService.checkIsLoggedIn();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,4 +113,13 @@ class AuthService {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Result<bool>> checkIsLoggedIn() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final token = prefs.getString('bearer');
|
||||
if (token == null) {
|
||||
return const Result.ok(false);
|
||||
}
|
||||
return const Result.ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,8 +230,8 @@ class $AssetsPngsGen {
|
||||
AssetGenImage get forgotPassword =>
|
||||
const AssetGenImage('assets/pngs/forgot_password.png');
|
||||
|
||||
/// File path: assets/pngs/logo.png
|
||||
AssetGenImage get logo => const AssetGenImage('assets/pngs/logo.png');
|
||||
/// File path: assets/pngs/logo-big.png
|
||||
AssetGenImage get logoBig => const AssetGenImage('assets/pngs/logo-big.png');
|
||||
|
||||
/// File path: assets/pngs/web_login_image.png
|
||||
AssetGenImage get webLoginImage =>
|
||||
@@ -241,7 +241,7 @@ class $AssetsPngsGen {
|
||||
List<AssetGenImage> get values => [
|
||||
appLogo,
|
||||
forgotPassword,
|
||||
logo,
|
||||
logoBig,
|
||||
webLoginImage,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ class AuthViewModel with ChangeNotifier {
|
||||
|
||||
// Auth state
|
||||
bool _isLoading = false;
|
||||
bool _isLoggedIn = false;
|
||||
bool _isResetPasswordLoading = false;
|
||||
String? _errorMessage;
|
||||
String? _resetPasswordErrorMessage;
|
||||
@@ -59,6 +60,7 @@ class AuthViewModel with ChangeNotifier {
|
||||
bool _verifyOtpSuccess = false;
|
||||
|
||||
bool get isLoading => _isLoading;
|
||||
bool get isLoggedIn => _isLoggedIn;
|
||||
bool get isLoadingForgot => _isLoadingForgot;
|
||||
bool get isLoadingOtp => _isLoadingOtp;
|
||||
bool get isResetPasswordLoading => _isResetPasswordLoading;
|
||||
@@ -282,6 +284,21 @@ class AuthViewModel with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> checkIsLoggedIn() async {
|
||||
final result = await _authRepository.checkIsLoggedIn();
|
||||
|
||||
if (result is Ok<bool>) {
|
||||
if (result.value) {
|
||||
_isLoggedIn = result.value;
|
||||
} else {
|
||||
_isLoggedIn = false;
|
||||
}
|
||||
} else {
|
||||
_isLoggedIn = false;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void clearResetPasswordSuccess() {
|
||||
_resetPasswordSuccess = false;
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/routes/app_routes.dart';
|
||||
import 'package:tm_app/view_models/auth_view_model.dart';
|
||||
|
||||
import '../../../core/constants/assets.dart';
|
||||
|
||||
class DesktopSplashPage extends StatefulWidget {
|
||||
const DesktopSplashPage({super.key});
|
||||
|
||||
@override
|
||||
State<DesktopSplashPage> createState() => _DesktopSplashPageState();
|
||||
}
|
||||
|
||||
class _DesktopSplashPageState extends State<DesktopSplashPage> {
|
||||
late final AuthViewModel viewModel;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
viewModel = context.read<AuthViewModel>();
|
||||
Future.delayed(const Duration(seconds: 1), () async {
|
||||
await viewModel.checkIsLoggedIn();
|
||||
});
|
||||
viewModel.addListener(_viewModelListener);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
viewModel.removeListener(_viewModelListener);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _viewModelListener() {
|
||||
if (viewModel.isLoggedIn) {
|
||||
Router.neglect(context, () => const HomeRouteData().go(context));
|
||||
} else {
|
||||
Router.neglect(context, () => const LoginScreenRoute().go(context));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Image.asset(AssetsManager.logoBigPng, fit: BoxFit.cover),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/constants/assets.dart';
|
||||
import 'package:tm_app/core/routes/app_routes.dart';
|
||||
import 'package:tm_app/view_models/auth_view_model.dart';
|
||||
|
||||
class MobileSplashPage extends StatefulWidget {
|
||||
const MobileSplashPage({super.key});
|
||||
|
||||
@override
|
||||
State<MobileSplashPage> createState() => _MobileSplashPageState();
|
||||
}
|
||||
|
||||
class _MobileSplashPageState extends State<MobileSplashPage> {
|
||||
late final AuthViewModel viewModel;
|
||||
@override
|
||||
void initState() {
|
||||
viewModel = context.read<AuthViewModel>();
|
||||
Future.delayed(const Duration(seconds: 1), () async {
|
||||
await viewModel.checkIsLoggedIn();
|
||||
});
|
||||
viewModel.addListener(_viewModelListener);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _viewModelListener() {
|
||||
if (viewModel.isLoggedIn) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
Router.neglect(context, () => const HomeRouteData().go(context));
|
||||
});
|
||||
} else {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
Router.neglect(context, () => const LoginScreenRoute().go(context));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
viewModel.removeListener(_viewModelListener);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Image.asset(AssetsManager.logoBigPng, fit: BoxFit.cover),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/views/shared/responsive_builder.dart';
|
||||
import 'package:tm_app/views/splash/pages/d_splash_page.dart';
|
||||
import 'package:tm_app/views/splash/pages/m_splash_page.dart';
|
||||
import 'package:tm_app/views/splash/pages/t_splash_page.dart';
|
||||
|
||||
class SplashScreen extends StatelessWidget {
|
||||
const SplashScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SizeConfig.init(context);
|
||||
return const ResponsiveBuilder(
|
||||
mobile: MobileSplashPage(),
|
||||
tablet: TabletSplashPage(),
|
||||
desktop: DesktopSplashPage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/view_models/auth_view_model.dart';
|
||||
|
||||
import '../../../core/constants/assets.dart';
|
||||
import '../../../core/routes/app_routes.dart';
|
||||
|
||||
class TabletSplashPage extends StatefulWidget {
|
||||
const TabletSplashPage({super.key});
|
||||
|
||||
@override
|
||||
State<TabletSplashPage> createState() => _TabletSplashPageState();
|
||||
}
|
||||
|
||||
class _TabletSplashPageState extends State<TabletSplashPage> {
|
||||
late final AuthViewModel viewModel;
|
||||
@override
|
||||
void initState() {
|
||||
viewModel = context.read<AuthViewModel>();
|
||||
Future.delayed(const Duration(seconds: 1), () async {
|
||||
await viewModel.checkIsLoggedIn();
|
||||
});
|
||||
viewModel.addListener(_viewModelListener);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _viewModelListener() {
|
||||
if (viewModel.isLoggedIn) {
|
||||
Router.neglect(context, () => const HomeRouteData().go(context));
|
||||
} else {
|
||||
Router.neglect(context, () => const LoginScreenRoute().go(context));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
viewModel.removeListener(_viewModelListener);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Image.asset(AssetsManager.logoBigPng, fit: BoxFit.cover),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -45,10 +45,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
version: "2.13.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -269,10 +269,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -572,10 +572,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.8"
|
||||
version: "10.0.9"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1049,10 +1049,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.1"
|
||||
version: "15.0.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
Reference in New Issue
Block a user