better linting
This commit is contained in:
parent
c7324a6b19
commit
aa31a79d20
26 changed files with 163 additions and 131 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
include: package:very_good_analysis/analysis_options.3.1.0.yaml
|
||||||
|
|
||||||
analyzer:
|
analyzer:
|
||||||
strong-mode:
|
strong-mode:
|
||||||
implicit-dynamic: true
|
implicit-dynamic: true
|
||||||
|
|
|
@ -25,7 +25,7 @@ class McgRouter {
|
||||||
path: Routes.imageCarousel.routePath,
|
path: Routes.imageCarousel.routePath,
|
||||||
name: Routes.imageCarousel.routeName,
|
name: Routes.imageCarousel.routeName,
|
||||||
builder: (context, state) => ImageCarouselView(
|
builder: (context, state) => ImageCarouselView(
|
||||||
imageCarouselViewArguments: state.extra as ImageCarouselViewArguments,
|
imageCarouselViewArguments: state.extra! as ImageCarouselViewArguments,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -17,11 +17,11 @@ enum Routes {
|
||||||
}
|
}
|
||||||
|
|
||||||
class RoutesInfo {
|
class RoutesInfo {
|
||||||
final String routePath;
|
|
||||||
final String routeName;
|
|
||||||
|
|
||||||
const RoutesInfo({
|
const RoutesInfo({
|
||||||
required this.routePath,
|
required this.routePath,
|
||||||
required this.routeName,
|
required this.routeName,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final String routePath;
|
||||||
|
final String routeName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
abstract class ConstColours {
|
abstract class ConstColours {
|
||||||
/// Smoke Gray => a neutral grey with neutral warmth/cold
|
/// Smoke Gray => a neutral grey with neutral warmth/cold
|
||||||
static const galleryBackgroundColour = Color.fromRGBO(127, 127, 125, 1.0);
|
static const galleryBackgroundColour = Color.fromRGBO(127, 127, 125, 1);
|
||||||
static const red = Colors.red;
|
static const red = Colors.red;
|
||||||
|
|
||||||
static const white = Colors.white;
|
static const white = Colors.white;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
extension ResponseExtensions on Response {
|
/// Extensions on [Dio]'s [Response].
|
||||||
|
extension ResponseExtensions<T> on Response<T> {
|
||||||
/// Shorthand for getting response's successful state.
|
/// Shorthand for getting response's successful state.
|
||||||
bool get isSuccessful => (data as Map)['response'];
|
bool get isSuccessful => (data! as Map<String, dynamic>)['response'] as bool;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/// String extensions
|
||||||
extension StringExtensions on String {
|
extension StringExtensions on String {
|
||||||
/// Returns true if given word contains atleast all the characters in [targetChars], and `false` otherwise
|
/// Returns true if given word contains atleast all the characters in [targetChars], and `false` otherwise
|
||||||
///
|
///
|
||||||
|
@ -6,9 +7,9 @@ extension StringExtensions on String {
|
||||||
required String targetChars,
|
required String targetChars,
|
||||||
bool ignoreCase = true,
|
bool ignoreCase = true,
|
||||||
}) {
|
}) {
|
||||||
final Set<String> characterSet = ignoreCase
|
final characterSet = ignoreCase
|
||||||
? Set.from(targetChars.toLowerCase().split(''))
|
? Set<String>.from(targetChars.toLowerCase().split(''))
|
||||||
: Set.from(targetChars.split(''));
|
: Set<String>.from(targetChars.split(''));
|
||||||
for (final testChar in ignoreCase ? toLowerCase().split('') : split('')) {
|
for (final testChar in ignoreCase ? toLowerCase().split('') : split('')) {
|
||||||
characterSet.remove(testChar);
|
characterSet.remove(testChar);
|
||||||
if (characterSet.isEmpty) return true;
|
if (characterSet.isEmpty) return true;
|
||||||
|
|
|
@ -25,7 +25,7 @@ class AppLifecycleService with WidgetsBindingObserver {
|
||||||
|
|
||||||
late final StreamController<AppLifecycleState> _lifecycleStateStreamController =
|
late final StreamController<AppLifecycleState> _lifecycleStateStreamController =
|
||||||
StreamController.broadcast();
|
StreamController.broadcast();
|
||||||
final Map<String, StreamSubscription> _appLifecycleSubscriptions = {};
|
final Map<String, StreamSubscription<dynamic>> _appLifecycleSubscriptions = {};
|
||||||
|
|
||||||
AppLifecycleState? _appLifeCycleState;
|
AppLifecycleState? _appLifeCycleState;
|
||||||
AppLifecycleState? get appLifeCycleState => _appLifeCycleState;
|
AppLifecycleState? get appLifeCycleState => _appLifeCycleState;
|
||||||
|
|
|
@ -64,7 +64,7 @@ class ConnectionsService {
|
||||||
static ConnectionsService get locate => Locator.locate();
|
static ConnectionsService get locate => Locator.locate();
|
||||||
}
|
}
|
||||||
|
|
||||||
extension _connectionStatusEmojiExtension on InternetConnectionStatus {
|
extension _ConnectionStatusEmojiExtension on InternetConnectionStatus {
|
||||||
String get nameWithIcon {
|
String get nameWithIcon {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case InternetConnectionStatus.connected:
|
case InternetConnectionStatus.connected:
|
||||||
|
@ -75,7 +75,7 @@ extension _connectionStatusEmojiExtension on InternetConnectionStatus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension _connectivityEmojiExtension on ConnectivityResult {
|
extension _ConnectivityEmojiExtension on ConnectivityResult {
|
||||||
String get nameWithIcon {
|
String get nameWithIcon {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case ConnectivityResult.bluetooth:
|
case ConnectivityResult.bluetooth:
|
||||||
|
|
|
@ -29,7 +29,7 @@ class LocalStorageService {
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateFavourite({
|
void updateFavourite({
|
||||||
required index,
|
required int index,
|
||||||
required bool newValue,
|
required bool newValue,
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -15,8 +15,8 @@ class LoggingService {
|
||||||
useHistory: false,
|
useHistory: false,
|
||||||
),
|
),
|
||||||
logger: TalkerLogger(
|
logger: TalkerLogger(
|
||||||
formater:
|
formater: !Platform.isIOS ? const ColoredLoggerFormatter() : const ExtendedLoggerFormatter(),
|
||||||
!Platform.isIOS ? const ColoredLoggerFormatter() : const ExtendedLoggerFormatter()),
|
),
|
||||||
loggerSettings: TalkerLoggerSettings(
|
loggerSettings: TalkerLoggerSettings(
|
||||||
enableColors: !Platform.isIOS,
|
enableColors: !Platform.isIOS,
|
||||||
),
|
),
|
||||||
|
@ -49,11 +49,10 @@ class LoggingService {
|
||||||
TalkerDioLogger(
|
TalkerDioLogger(
|
||||||
talker: Talker(
|
talker: Talker(
|
||||||
logger: TalkerLogger(
|
logger: TalkerLogger(
|
||||||
formater: !Platform.isIOS
|
formater:
|
||||||
? const ColoredLoggerFormatter()
|
!Platform.isIOS ? const ColoredLoggerFormatter() : const ExtendedLoggerFormatter(),
|
||||||
: const ExtendedLoggerFormatter()),
|
),
|
||||||
settings: TalkerSettings(
|
settings: TalkerSettings(
|
||||||
useConsoleLogs: true,
|
|
||||||
useHistory: false,
|
useHistory: false,
|
||||||
),
|
),
|
||||||
loggerSettings: TalkerLoggerSettings(
|
loggerSettings: TalkerLoggerSettings(
|
||||||
|
@ -63,7 +62,6 @@ class LoggingService {
|
||||||
settings: const TalkerDioLoggerSettings(
|
settings: const TalkerDioLoggerSettings(
|
||||||
printRequestHeaders: true,
|
printRequestHeaders: true,
|
||||||
printResponseHeaders: true,
|
printResponseHeaders: true,
|
||||||
printResponseMessage: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -24,8 +24,9 @@ class OverlayService {
|
||||||
//todo(mehul): Fix and not ignore Overlay building while Widget building error.
|
//todo(mehul): Fix and not ignore Overlay building while Widget building error.
|
||||||
} on FlutterError catch (_) {}
|
} on FlutterError catch (_) {}
|
||||||
_loggingService.info('Overlay inserted with tag: $tag');
|
_loggingService.info('Overlay inserted with tag: $tag');
|
||||||
} else
|
} else {
|
||||||
_loggingService.info('Overlay with tag: $tag, NOT inserted');
|
_loggingService.info('Overlay with tag: $tag, NOT inserted');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeOverlayEntry({
|
void removeOverlayEntry({
|
||||||
|
@ -37,10 +38,12 @@ class OverlayService {
|
||||||
_overlayEntryMap[tag.hashCode]?.remove();
|
_overlayEntryMap[tag.hashCode]?.remove();
|
||||||
_overlayEntryMap.remove(tag.hashCode);
|
_overlayEntryMap.remove(tag.hashCode);
|
||||||
_loggingService.info('Overlay removed with tag: $tag');
|
_loggingService.info('Overlay removed with tag: $tag');
|
||||||
} else
|
} else {
|
||||||
_loggingService.info('Overlay with tag: $tag already mounted OR not found. Skipped');
|
_loggingService.info('Overlay with tag: $tag already mounted OR not found. Skipped');
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
_loggingService.info('Overlay with tag: $tag already exists. Skipped');
|
_loggingService.info('Overlay with tag: $tag already exists. Skipped');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|
|
@ -4,19 +4,19 @@ import 'dart:ui';
|
||||||
|
|
||||||
/// A simple Mutex implementation using a [Completer].
|
/// A simple Mutex implementation using a [Completer].
|
||||||
class Mutex {
|
class Mutex {
|
||||||
final _completerQueue = Queue<Completer>();
|
final _completerQueue = Queue<Completer<void>>();
|
||||||
|
|
||||||
/// Runs the given [run] function-block in a thread-safe/blocked zone. A convenient `unlock()`
|
/// Runs the given [run] function-block in a thread-safe/blocked zone. A convenient `unlock()`
|
||||||
/// is provided, which can be called anywhere to signal re-entry.
|
/// is provided, which can be called anywhere to signal re-entry.
|
||||||
FutureOr<T> lockAndRun<T>({
|
FutureOr<T> lockAndRun<T>({
|
||||||
required FutureOr<T> Function(VoidCallback unlock) run,
|
required FutureOr<T> Function(VoidCallback unlock) run,
|
||||||
}) async {
|
}) async {
|
||||||
final completer = Completer();
|
final completer = Completer<void>();
|
||||||
_completerQueue.add(completer);
|
_completerQueue.add(completer);
|
||||||
if (_completerQueue.first != completer) {
|
if (_completerQueue.first != completer) {
|
||||||
await _completerQueue.removeFirst().future;
|
await _completerQueue.removeFirst().future;
|
||||||
}
|
}
|
||||||
final value = await run(() => completer.complete());
|
final value = await run(completer.complete);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ class ErrorPageView extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(Strings.current.errorPageMessage),
|
Text(Strings.current.errorPageMessage),
|
||||||
const Gap(16),
|
Gap.size16,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
/// Const evenly-sized gap.
|
||||||
class Gap extends LeafRenderObjectWidget {
|
class Gap extends LeafRenderObjectWidget {
|
||||||
const Gap(this.size, {Key? key}) : super(key: key);
|
const Gap(
|
||||||
|
this.size, {
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final double size;
|
final double size;
|
||||||
|
|
||||||
|
@ -58,13 +62,14 @@ class RenderGap extends RenderBox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Animates [Gap] insertion.
|
||||||
class AnimatedGap extends StatefulWidget {
|
class AnimatedGap extends StatefulWidget {
|
||||||
const AnimatedGap(
|
const AnimatedGap(
|
||||||
this.gap, {
|
this.gap, {
|
||||||
Key? key,
|
|
||||||
this.duration = const Duration(milliseconds: 200),
|
this.duration = const Duration(milliseconds: 200),
|
||||||
this.curve = Curves.easeInOut,
|
this.curve = Curves.easeInOut,
|
||||||
}) : super(key: key);
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final Duration duration;
|
final Duration duration;
|
||||||
final double gap;
|
final double gap;
|
||||||
|
@ -107,10 +112,10 @@ class _AnimatedGapState extends State<AnimatedGap> with SingleTickerProviderStat
|
||||||
class AnimatedSliverGap extends StatefulWidget {
|
class AnimatedSliverGap extends StatefulWidget {
|
||||||
const AnimatedSliverGap(
|
const AnimatedSliverGap(
|
||||||
this.gap, {
|
this.gap, {
|
||||||
Key? key,
|
|
||||||
this.duration = const Duration(milliseconds: 200),
|
this.duration = const Duration(milliseconds: 200),
|
||||||
this.curve = Curves.easeInOut,
|
this.curve = Curves.easeInOut,
|
||||||
}) : super(key: key);
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final Duration duration;
|
final Duration duration;
|
||||||
final double gap;
|
final double gap;
|
||||||
|
|
|
@ -8,10 +8,13 @@ class MultiValueListenableBuilder extends StatelessWidget {
|
||||||
required this.builder,
|
required this.builder,
|
||||||
this.child,
|
this.child,
|
||||||
super.key,
|
super.key,
|
||||||
}) : assert(valueListenables.length != 0);
|
}) : assert(
|
||||||
|
valueListenables.length != 0,
|
||||||
|
'Attached valueListenables must not be empty',
|
||||||
|
);
|
||||||
|
|
||||||
/// List of [ValueListenable]s to be listened to.
|
/// List of [ValueListenable]s to be listened to.
|
||||||
final List<ValueListenable> valueListenables;
|
final List<ValueListenable<dynamic>> valueListenables;
|
||||||
|
|
||||||
/// The builder function to be called when value of any of the [ValueListenable] changes.
|
/// The builder function to be called when value of any of the [ValueListenable] changes.
|
||||||
/// The order of values list will be same as [valueListenables] list.
|
/// The order of values list will be same as [valueListenables] list.
|
||||||
|
|
|
@ -9,16 +9,19 @@ import '../abstracts/images_api.dart';
|
||||||
import '../data/dtos/image_model_dto.dart';
|
import '../data/dtos/image_model_dto.dart';
|
||||||
|
|
||||||
class UnsplashImagesApi extends ImagesApi {
|
class UnsplashImagesApi extends ImagesApi {
|
||||||
|
UnsplashImagesApi({required super.token});
|
||||||
|
|
||||||
//final LoggingService _loggingService = LoggingService.locate;
|
//final LoggingService _loggingService = LoggingService.locate;
|
||||||
final random = Random();
|
final random = Random();
|
||||||
|
|
||||||
UnsplashImagesApi({required super.token});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<Iterable<ImageModelDTO>> fetchImageUri() async {
|
FutureOr<Iterable<ImageModelDTO>> fetchImageUri() async {
|
||||||
// Dummy fetching delay emulation
|
// Dummy fetching delay emulation
|
||||||
await Future.delayed(const Duration(
|
await Future<void>.delayed(
|
||||||
milliseconds: ConstValues.defaultEmulatedLatencyMillis * ConstValues.numberOfImages));
|
const Duration(
|
||||||
|
milliseconds: ConstValues.defaultEmulatedLatencyMillis * ConstValues.numberOfImages,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
final Iterable<Map<String, dynamic>> fetchedImageModelDtos;
|
final Iterable<Map<String, dynamic>> fetchedImageModelDtos;
|
||||||
try {
|
try {
|
||||||
|
@ -48,8 +51,7 @@ class UnsplashImagesApi extends ImagesApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emulating deserialization
|
// Emulating deserialization
|
||||||
return fetchedImageModelDtos
|
return fetchedImageModelDtos.map(ImageModelDTO.fromJson);
|
||||||
.map((final emulatedModelSerialized) => ImageModelDTO.fromJson(emulatedModelSerialized));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -59,8 +61,11 @@ class UnsplashImagesApi extends ImagesApi {
|
||||||
final numberOfResults = random.nextIntInRange(min: 0, max: ConstValues.numberOfImages);
|
final numberOfResults = random.nextIntInRange(min: 0, max: ConstValues.numberOfImages);
|
||||||
|
|
||||||
// Dummy fetching delay emulation
|
// Dummy fetching delay emulation
|
||||||
await Future.delayed(
|
await Future<void>.delayed(
|
||||||
Duration(milliseconds: ConstValues.defaultEmulatedLatencyMillis * numberOfResults));
|
Duration(
|
||||||
|
milliseconds: ConstValues.defaultEmulatedLatencyMillis * numberOfResults,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
final Iterable<Map<String, dynamic>> searchImageModelDtos;
|
final Iterable<Map<String, dynamic>> searchImageModelDtos;
|
||||||
try {
|
try {
|
||||||
|
@ -87,8 +92,7 @@ class UnsplashImagesApi extends ImagesApi {
|
||||||
return List.empty();
|
return List.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
return searchImageModelDtos
|
return searchImageModelDtos.map(ImageModelDTO.fromJson);
|
||||||
.map((final emulatedModelSerialized) => ImageModelDTO.fromJson(emulatedModelSerialized));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri _imageUrlGenerator({required int imageSide}) => Uri(
|
Uri _imageUrlGenerator({required int imageSide}) => Uri(
|
||||||
|
|
|
@ -2,13 +2,24 @@ import '../dtos/image_model_dto.dart';
|
||||||
|
|
||||||
/// Represents an Image, that would be displayed in the gallery.
|
/// Represents an Image, that would be displayed in the gallery.
|
||||||
class ImageModel {
|
class ImageModel {
|
||||||
const ImageModel({
|
const ImageModel._({
|
||||||
required this.uri,
|
required this.uri,
|
||||||
required this.imageIndex,
|
required this.imageIndex,
|
||||||
required this.imageName,
|
required this.imageName,
|
||||||
required this.isFavourite,
|
required this.isFavourite,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
factory ImageModel.fromDto({
|
||||||
|
required ImageModelDTO imageModelDto,
|
||||||
|
required bool isFavourite,
|
||||||
|
}) =>
|
||||||
|
ImageModel._(
|
||||||
|
uri: imageModelDto.uri,
|
||||||
|
imageIndex: imageModelDto.imageIndex,
|
||||||
|
imageName: imageModelDto.imageName,
|
||||||
|
isFavourite: isFavourite,
|
||||||
|
);
|
||||||
|
|
||||||
/// An image's target [Uri].
|
/// An image's target [Uri].
|
||||||
///
|
///
|
||||||
/// Storing an image's [ByteData] is more expensive, memory-wise.
|
/// Storing an image's [ByteData] is more expensive, memory-wise.
|
||||||
|
@ -23,24 +34,13 @@ class ImageModel {
|
||||||
/// Whether the image was 'Starred' ot not.
|
/// Whether the image was 'Starred' ot not.
|
||||||
final bool isFavourite;
|
final bool isFavourite;
|
||||||
|
|
||||||
factory ImageModel.fromDto({
|
|
||||||
required ImageModelDTO imageModelDto,
|
|
||||||
required bool isFavourite,
|
|
||||||
}) =>
|
|
||||||
ImageModel(
|
|
||||||
uri: imageModelDto.uri,
|
|
||||||
imageIndex: imageModelDto.imageIndex,
|
|
||||||
imageName: imageModelDto.imageName,
|
|
||||||
isFavourite: isFavourite,
|
|
||||||
);
|
|
||||||
|
|
||||||
ImageModel copyWith({
|
ImageModel copyWith({
|
||||||
Uri? uri,
|
Uri? uri,
|
||||||
int? imageIndex,
|
int? imageIndex,
|
||||||
String? imageName,
|
String? imageName,
|
||||||
bool? isFavourite,
|
bool? isFavourite,
|
||||||
}) {
|
}) {
|
||||||
return ImageModel(
|
return ImageModel._(
|
||||||
uri: uri ?? this.uri,
|
uri: uri ?? this.uri,
|
||||||
imageIndex: imageIndex ?? this.imageIndex,
|
imageIndex: imageIndex ?? this.imageIndex,
|
||||||
imageName: imageName ?? this.imageName,
|
imageName: imageName ?? this.imageName,
|
||||||
|
|
|
@ -22,7 +22,7 @@ class ImageCacheManagerService {
|
||||||
final LoggingService _loggingService = LoggingService.locate;
|
final LoggingService _loggingService = LoggingService.locate;
|
||||||
final _cacheManager = DefaultCacheManager();
|
final _cacheManager = DefaultCacheManager();
|
||||||
|
|
||||||
Future<void> emptyCache() async => await _cacheManager.emptyCache();
|
void emptyCache() => _cacheManager.emptyCache();
|
||||||
|
|
||||||
Future<void> _init() async {
|
Future<void> _init() async {
|
||||||
_appLifecycleService.addListener(
|
_appLifecycleService.addListener(
|
||||||
|
|
|
@ -54,19 +54,25 @@ class ImagesService {
|
||||||
|
|
||||||
// Prefill from stored values
|
// Prefill from stored values
|
||||||
if (favouritesStatuses.isNotEmpty) {
|
if (favouritesStatuses.isNotEmpty) {
|
||||||
_loggingService.good('Found favourites statuses on device -> Prefilling');
|
_loggingService.fine('Found favourites statuses on device -> Prefilling');
|
||||||
assert(fetchedImageModelDtos.length == favouritesStatuses.length);
|
assert(
|
||||||
|
fetchedImageModelDtos.length == favouritesStatuses.length,
|
||||||
|
'Downloaded images must be the same number as the statuses stored on device',
|
||||||
|
);
|
||||||
|
|
||||||
_imageModels = LinkedHashMap.of({
|
_imageModels = LinkedHashMap.of({
|
||||||
for (final pair in IterableZip([fetchedImageModelDtos, favouritesStatuses]))
|
for (final zippedDtosAndFavourites
|
||||||
(pair[0] as ImageModelDTO).imageName: ImageModel.fromDto(
|
in IterableZip([fetchedImageModelDtos, favouritesStatuses]))
|
||||||
imageModelDto: pair[0] as ImageModelDTO,
|
(zippedDtosAndFavourites[0] as ImageModelDTO).imageName: ImageModel.fromDto(
|
||||||
isFavourite: pair[1] as bool,
|
imageModelDto: zippedDtosAndFavourites[0] as ImageModelDTO,
|
||||||
|
isFavourite: zippedDtosAndFavourites[1] as bool,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set to false and create the stored values
|
// Set to false and create the stored values
|
||||||
} else {
|
} else {
|
||||||
_loggingService.good('NO favourites statuses found -> creating new');
|
_loggingService.good('NO favourites statuses found -> creating new');
|
||||||
|
|
||||||
_imageModels = LinkedHashMap.of({
|
_imageModels = LinkedHashMap.of({
|
||||||
for (final fetchedImageModelDto in fetchedImageModelDtos)
|
for (final fetchedImageModelDto in fetchedImageModelDtos)
|
||||||
fetchedImageModelDto.imageName: ImageModel.fromDto(
|
fetchedImageModelDto.imageName: ImageModel.fromDto(
|
||||||
|
@ -119,8 +125,10 @@ class ImagesService {
|
||||||
: imageName.containsAllCharacters(targetChars: imageNamePart))
|
: imageName.containsAllCharacters(targetChars: imageNamePart))
|
||||||
.toList(growable: false)
|
.toList(growable: false)
|
||||||
// Sorting by the highest similarity first
|
// Sorting by the highest similarity first
|
||||||
..sort((final a, final b) =>
|
..sort(
|
||||||
ConstSorters.stringsSimilarityTarget(targetWord: imageNamePart, a, b))
|
(final a, final b) =>
|
||||||
|
ConstSorters.stringsSimilarityTarget(targetWord: imageNamePart, a, b),
|
||||||
|
)
|
||||||
..reversed;
|
..reversed;
|
||||||
|
|
||||||
return _imageModels.valuesByKeys(keys: rankedKeys).toList(growable: false);
|
return _imageModels.valuesByKeys(keys: rankedKeys).toList(growable: false);
|
||||||
|
|
|
@ -150,8 +150,8 @@ class _SearchBox extends StatelessWidget {
|
||||||
items: [
|
items: [
|
||||||
for (final searchOption in SearchOption.values)
|
for (final searchOption in SearchOption.values)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
child: Center(child: Text(searchOption.name)),
|
|
||||||
value: searchOption,
|
value: searchOption,
|
||||||
|
child: Center(child: Text(searchOption.name)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
value: searchOption,
|
value: searchOption,
|
||||||
|
|
|
@ -42,7 +42,7 @@ class GalleryViewModel extends BaseViewModel {
|
||||||
ValueListenable<bool> get isViewingFavouriteListenable => _isViewingFavouriteNotifier;
|
ValueListenable<bool> get isViewingFavouriteListenable => _isViewingFavouriteNotifier;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> initialise(bool Function() mounted, [arguments]) async {
|
Future<void> initialise(bool Function() mounted, [Object? arguments]) async {
|
||||||
super.initialise(mounted, arguments);
|
super.initialise(mounted, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ class ImageCarouselView extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8),
|
||||||
child: Card(
|
child: Card(
|
||||||
elevation: 8,
|
elevation: 8,
|
||||||
surfaceTintColor: ConstColours.transparent,
|
surfaceTintColor: ConstColours.transparent,
|
||||||
|
@ -110,7 +110,7 @@ class ImageCarouselView extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Gap(24),
|
Gap.size24,
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
// Assuming that this data is coming from an external CRM, if it is coming with the
|
// Assuming that this data is coming from an external CRM, if it is coming with the
|
||||||
|
|
|
@ -21,9 +21,11 @@ class ImageCarouselViewModel extends BaseViewModel {
|
||||||
final CarouselController carouselController = CarouselController();
|
final CarouselController carouselController = CarouselController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> initialise(bool Function() mounted, [arguments]) async {
|
Future<void> initialise(bool Function() mounted, [Object? arguments]) async {
|
||||||
_currentImageModelNotifier = ValueNotifier(_imagesService.imageModels
|
_currentImageModelNotifier = ValueNotifier(
|
||||||
.elementAt((arguments as ImageCarouselViewArguments).imageIndexKey));
|
_imagesService.imageModels
|
||||||
|
.elementAt((arguments! as ImageCarouselViewArguments).imageIndexKey),
|
||||||
|
);
|
||||||
log.info('Initialized with image: ${_currentImageModelNotifier.value.imageIndex}');
|
log.info('Initialized with image: ${_currentImageModelNotifier.value.imageIndex}');
|
||||||
|
|
||||||
super.initialise(mounted, arguments);
|
super.initialise(mounted, arguments);
|
||||||
|
|
100
lib/locator.dart
100
lib/locator.dart
|
@ -58,61 +58,59 @@ class Locator {
|
||||||
}
|
}
|
||||||
|
|
||||||
static FutureOr<void> _registerServices(GetIt it) async {
|
static FutureOr<void> _registerServices(GetIt it) async {
|
||||||
it.registerLazySingleton(
|
it
|
||||||
() => NavigationService(
|
..registerLazySingleton(
|
||||||
mcgRouter: McgRouter.locate,
|
() => NavigationService(
|
||||||
),
|
mcgRouter: McgRouter.locate,
|
||||||
);
|
),
|
||||||
|
)
|
||||||
it.registerFactory(
|
..registerFactory(
|
||||||
() => LoggingService(),
|
LoggingService.new,
|
||||||
);
|
)
|
||||||
|
..registerSingleton<ConnectionsService>(
|
||||||
it.registerSingleton<ConnectionsService>(
|
ConnectionsService(
|
||||||
ConnectionsService(
|
connectivity: Connectivity(),
|
||||||
connectivity: Connectivity(),
|
internetConnectionChecker: InternetConnectionChecker(),
|
||||||
internetConnectionChecker: InternetConnectionChecker(),
|
loggingService: LoggingService.locate,
|
||||||
loggingService: LoggingService.locate,
|
),
|
||||||
),
|
signalsReady: true,
|
||||||
signalsReady: true,
|
dispose: (final param) async => param.dispose(),
|
||||||
dispose: (final param) async => await param.dispose(),
|
);
|
||||||
);
|
|
||||||
await it.isReady<ConnectionsService>();
|
await it.isReady<ConnectionsService>();
|
||||||
|
|
||||||
it.registerLazySingleton(
|
it
|
||||||
() => OverlayService(
|
..registerLazySingleton(
|
||||||
loggingService: LoggingService.locate,
|
() => OverlayService(
|
||||||
),
|
loggingService: LoggingService.locate,
|
||||||
dispose: (param) => param.dispose(),
|
),
|
||||||
);
|
dispose: (param) => param.dispose(),
|
||||||
|
)
|
||||||
it.registerSingleton<AppLifecycleService>(
|
..registerSingleton<AppLifecycleService>(
|
||||||
AppLifecycleService(
|
AppLifecycleService(
|
||||||
loggingService: LoggingService.locate,
|
loggingService: LoggingService.locate,
|
||||||
),
|
),
|
||||||
dispose: (final param) async => await param.dispose(),
|
dispose: (final param) async => param.dispose(),
|
||||||
);
|
)
|
||||||
|
..registerSingleton<LocalStorageService>(
|
||||||
it.registerSingleton<LocalStorageService>(
|
LocalStorageService(),
|
||||||
LocalStorageService(),
|
signalsReady: true,
|
||||||
signalsReady: true,
|
);
|
||||||
);
|
|
||||||
await it.isReady<LocalStorageService>();
|
await it.isReady<LocalStorageService>();
|
||||||
|
|
||||||
it.registerSingleton<ImagesService>(
|
it
|
||||||
ImagesService(
|
..registerSingleton<ImagesService>(
|
||||||
imagesApi: UnsplashImagesApi.locate,
|
ImagesService(
|
||||||
localStorageService: LocalStorageService.locate,
|
imagesApi: UnsplashImagesApi.locate,
|
||||||
loggingService: LoggingService.locate,
|
localStorageService: LocalStorageService.locate,
|
||||||
),
|
loggingService: LoggingService.locate,
|
||||||
);
|
),
|
||||||
|
)
|
||||||
it.registerSingleton(
|
..registerSingleton(
|
||||||
ImageCacheManagerService(
|
ImageCacheManagerService(
|
||||||
appLifecycleService: AppLifecycleService.locate,
|
appLifecycleService: AppLifecycleService.locate,
|
||||||
localStorageService: LocalStorageService.locate,
|
localStorageService: LocalStorageService.locate,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FutureOr<void> _registerRepos(GetIt locator) {}
|
static FutureOr<void> _registerRepos(GetIt locator) {}
|
||||||
|
|
|
@ -437,7 +437,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.4"
|
version: "0.6.4"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: "direct dev"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: json_annotation
|
name: json_annotation
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
|
@ -833,6 +833,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
|
very_good_analysis:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: very_good_analysis
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.0"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -36,19 +36,19 @@ dependencies:
|
||||||
intl_utils: ^2.8.1
|
intl_utils: ^2.8.1
|
||||||
connectivity_plus: ^3.0.2
|
connectivity_plus: ^3.0.2
|
||||||
internet_connection_checker: ^1.0.0+1
|
internet_connection_checker: ^1.0.0+1
|
||||||
|
json_annotation: ^4.7.0
|
||||||
string_similarity: ^2.0.0
|
string_similarity: ^2.0.0
|
||||||
|
|
||||||
# Util frontend
|
# Util frontend
|
||||||
flutter_markdown: ^0.6.13
|
flutter_markdown: ^0.6.13
|
||||||
auto_size_text: ^3.0.0
|
auto_size_text: ^3.0.0
|
||||||
|
flutter_svg: ^1.1.6
|
||||||
carousel_slider: ^4.2.1
|
carousel_slider: ^4.2.1
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
talker: ^2.2.0
|
talker: ^2.2.0
|
||||||
talker_dio_logger: ^1.0.0
|
talker_dio_logger: ^1.0.0
|
||||||
|
|
||||||
# Assets
|
|
||||||
flutter_svg: ^1.1.6
|
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
@ -63,8 +63,8 @@ dev_dependencies:
|
||||||
hive_generator: ^2.0.0
|
hive_generator: ^2.0.0
|
||||||
envied_generator: ^0.3.0
|
envied_generator: ^0.3.0
|
||||||
|
|
||||||
# Annotations
|
# Linters
|
||||||
json_annotation: ^4.7.0
|
very_good_analysis: ^3.1.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
Loading…
Reference in a new issue