init
This commit is contained in:
commit
8e54cfffc5
91 changed files with 2686 additions and 0 deletions
49
lib/features/core/abstracts/app_setup.dart
Normal file
49
lib/features/core/abstracts/app_setup.dart
Normal file
|
@ -0,0 +1,49 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '/l10n/generated/l10n.dart';
|
||||
import '/locator.dart';
|
||||
|
||||
abstract class AppSetup {
|
||||
// TODO: When locator is properly refactored we should not have to use these stub methods for testing
|
||||
static Future<void> initialise() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
await SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown,
|
||||
]);
|
||||
|
||||
await Locator.setup();
|
||||
}
|
||||
|
||||
static final List<Locale> supportedLocales = kReleaseMode
|
||||
? <Locale>[
|
||||
const Locale.fromSubtags(languageCode: 'en'),
|
||||
]
|
||||
: Strings.delegate.supportedLocales;
|
||||
|
||||
static Locale resolveLocale(List<Locale>? preferredLocales, Iterable<Locale> supportedLocales) {
|
||||
for (final locale in preferredLocales ?? const <Locale>[]) {
|
||||
// Check if the current device locale is supported
|
||||
for (final supportedLocale in supportedLocales) {
|
||||
if (supportedLocale.languageCode == locale.languageCode) {
|
||||
return supportedLocale;
|
||||
}
|
||||
}
|
||||
}
|
||||
return supportedLocales.first;
|
||||
}
|
||||
|
||||
static Future<void> setupStrings() async {
|
||||
await Strings.load(resolveLocale(WidgetsBinding.instance.window.locales, supportedLocales));
|
||||
}
|
||||
|
||||
static void Function(Object error, StackTrace stackTrace) get onUncaughtException => (
|
||||
error,
|
||||
stackTrace,
|
||||
) {};
|
||||
}
|
73
lib/features/core/abstracts/base_view_model.dart
Normal file
73
lib/features/core/abstracts/base_view_model.dart
Normal file
|
@ -0,0 +1,73 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:mc_gallery/features/core/services/logging_service.dart';
|
||||
import 'package:mc_gallery/l10n/generated/l10n.dart';
|
||||
|
||||
import '../data/enums/view_model_state.dart';
|
||||
|
||||
abstract class BaseViewModel<E extends Object?> extends ChangeNotifier {
|
||||
final ValueNotifier<bool> _isInitialised = ValueNotifier(false);
|
||||
ValueListenable<bool> get isInitialised => _isInitialised;
|
||||
|
||||
final ValueNotifier<bool> _isBusy = ValueNotifier(false);
|
||||
ValueListenable<bool> get isBusy => _isBusy;
|
||||
|
||||
final ValueNotifier<bool> _hasError = ValueNotifier(false);
|
||||
ValueListenable<bool> get hasError => _hasError;
|
||||
final ValueNotifier<ViewModelState> _state = ValueNotifier(ViewModelState.isInitialising);
|
||||
ValueListenable<ViewModelState> get state => _state;
|
||||
|
||||
final LoggingService _loggingService = LoggingService.locate;
|
||||
|
||||
String? _errorMessage;
|
||||
String get errorMessage => _errorMessage ?? strings.somethingWentWrong;
|
||||
|
||||
@mustCallSuper
|
||||
void initialise(DisposableBuildContext disposableBuildContext, bool Function() mounted,
|
||||
[E? arguments]) {
|
||||
_mounted = mounted;
|
||||
_isInitialised.value = true;
|
||||
_state.value = ViewModelState.isInitialised;
|
||||
_loggingService.successfulInit(location: runtimeType.runtimeType.toString());
|
||||
}
|
||||
|
||||
void setBusy(bool isBusy) {
|
||||
_isBusy.value = isBusy;
|
||||
if (isBusy) {
|
||||
_state.value = ViewModelState.isBusy;
|
||||
} else {
|
||||
_state.value = ViewModelState.isInitialised;
|
||||
}
|
||||
}
|
||||
|
||||
void setError(
|
||||
bool hasError, {
|
||||
String? message,
|
||||
}) {
|
||||
_errorMessage = hasError ? message : null;
|
||||
_hasError.value = hasError;
|
||||
if (hasError) {
|
||||
_state.value = ViewModelState.hasError;
|
||||
} else {
|
||||
_state.value = ViewModelState.isInitialised;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_loggingService.successfulDispose(location: runtimeType.runtimeType.toString());
|
||||
}
|
||||
|
||||
late final bool Function() _mounted;
|
||||
void ifMounted(VoidCallback voidCallback) {
|
||||
if (_mounted()) {
|
||||
voidCallback();
|
||||
}
|
||||
}
|
||||
|
||||
final Strings strings = Strings.current;
|
||||
|
||||
double width(BuildContext context) => MediaQuery.of(context).size.width;
|
||||
double height(BuildContext context) => MediaQuery.of(context).size.height;
|
||||
}
|
28
lib/features/core/abstracts/router/app_router.dart
Normal file
28
lib/features/core/abstracts/router/app_router.dart
Normal file
|
@ -0,0 +1,28 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mc_gallery/features/home/views/gallery_view.dart';
|
||||
|
||||
import '../../views/error_page_view.dart';
|
||||
import 'routes.dart';
|
||||
|
||||
class McgRouter {
|
||||
static final _mcgRouter = McgRouter();
|
||||
final router = GoRouter(
|
||||
initialLocation: Routes.home.routePath,
|
||||
debugLogDiagnostics: true,
|
||||
errorPageBuilder: (context, state) => MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: ErrorPageView(error: state.error),
|
||||
),
|
||||
// TODO Add Redirect
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: Routes.home.routePath,
|
||||
name: Routes.home.routeName,
|
||||
builder: (context, _) => const GalleryView(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
static McgRouter get locate => _mcgRouter;
|
||||
}
|
27
lib/features/core/abstracts/router/routes.dart
Normal file
27
lib/features/core/abstracts/router/routes.dart
Normal file
|
@ -0,0 +1,27 @@
|
|||
enum Routes {
|
||||
home(RoutesInfo(
|
||||
routePath: '/gallery',
|
||||
routeName: 'Home',
|
||||
)),
|
||||
imageCarousel(RoutesInfo(
|
||||
routePath: '/image_carousel',
|
||||
routeName: 'Image Carousel',
|
||||
));
|
||||
|
||||
final RoutesInfo _routeInfo;
|
||||
|
||||
String get routePath => _routeInfo.routePath;
|
||||
String get routeName => _routeInfo.routeName;
|
||||
|
||||
const Routes(this._routeInfo);
|
||||
}
|
||||
|
||||
class RoutesInfo {
|
||||
final String routePath;
|
||||
final String routeName;
|
||||
|
||||
const RoutesInfo({
|
||||
required this.routePath,
|
||||
required this.routeName,
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue