This commit is contained in:
Mehul Ahal 2022-12-19 14:03:38 +01:00
commit 8e54cfffc5
91 changed files with 2686 additions and 0 deletions

View 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,
) {};
}

View 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;
}

View 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;
}

View 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,
});
}