From 0cda6f9a484927b9a0b013438c529f0d26383db2 Mon Sep 17 00:00:00 2001 From: NaggaDIM Date: Sun, 22 Dec 2024 16:39:43 +0300 Subject: [PATCH] RuStore Remote Config --- android/app/build.gradle | 2 +- assets/schedule.json | 10 +- lib/application.dart | 4 - .../calendar_schedule_controller.dart | 24 +- .../controllers/schedule_controller.dart | 3 +- lib/application/dto/direction.dart | 25 ++ lib/application/dto/rule.dart | 15 + lib/application/dto/rule.g.dart | 21 ++ lib/application/dto/schedule.dart | 41 +++ lib/application/dto/schedule.g.dart | 34 ++ .../services/remote_config/parameters.dart | 5 + .../services/remote_config/service.dart | 131 +++++++ lib/application/services/schedule.dart | 105 ++---- lib/configuration.dart | 3 + lib/enums/direction.dart | 11 - lib/enums/schedule.dart | 67 ---- lib/main.dart | 2 + lib/pages/home_page.dart | 18 - .../components/schedule_item_component.dart | 12 +- lib/ui/screens/calendar_screen.dart | 9 +- lib/ui/screens/home_screen.dart | 14 +- lib/utils/scheduler.dart | 36 -- lib/widgets/loader_widget.dart | 16 - lib/widgets/schedule_element_widget.dart | 79 ----- lib/widgets/schedule_widget.dart | 45 --- pubspec.lock | 335 +++++++++++++++++- pubspec.yaml | 6 +- 27 files changed, 693 insertions(+), 380 deletions(-) create mode 100644 lib/application/dto/direction.dart create mode 100644 lib/application/dto/rule.dart create mode 100644 lib/application/dto/rule.g.dart create mode 100644 lib/application/dto/schedule.dart create mode 100644 lib/application/dto/schedule.g.dart create mode 100644 lib/application/services/remote_config/parameters.dart create mode 100644 lib/application/services/remote_config/service.dart create mode 100644 lib/configuration.dart delete mode 100644 lib/enums/direction.dart delete mode 100644 lib/enums/schedule.dart delete mode 100644 lib/pages/home_page.dart delete mode 100644 lib/utils/scheduler.dart delete mode 100644 lib/widgets/loader_widget.dart delete mode 100644 lib/widgets/schedule_element_widget.dart delete mode 100644 lib/widgets/schedule_widget.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 23a8d9d..a7bee10 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -51,7 +51,7 @@ android { applicationId "ru.naggadim.reverse_nn.reverse_nn" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 23 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/assets/schedule.json b/assets/schedule.json index d37deb6..8226c8d 100644 --- a/assets/schedule.json +++ b/assets/schedule.json @@ -2,7 +2,7 @@ "rules": [ { "after": "2024-08-01T00:00:00.000", - "before": "2024-12-16T03:59:99.999", + "before": "2024-12-16T03:59:59.999999", "dataset": { "monday": "daily-1", "tuesday": "daily-1", @@ -10,13 +10,7 @@ "thursday": "daily-1", "friday": "friday-1", "saturday": "saturday-1", - "sunday": "sunday-1", - - "2024-11-01": "daily-1", - "2024-11-02": "friday-1", - "2024-11-03": "saturday-1", - "2024-11-04": "sunday-1", - "2024-11-05": "daily-1" + "sunday": "sunday-1" } }, { diff --git a/lib/application.dart b/lib/application.dart index 49628ce..01821b1 100644 --- a/lib/application.dart +++ b/lib/application.dart @@ -1,11 +1,7 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get/get.dart'; -import 'package:get_storage/get_storage.dart'; import 'package:reverse_nn/application/controllers/application_controller.dart'; -import 'package:reverse_nn/pages/home_page.dart'; import 'package:reverse_nn/ui/screens/home_screen.dart'; class ReversNNApplication extends StatelessWidget { diff --git a/lib/application/controllers/calendar_schedule_controller.dart b/lib/application/controllers/calendar_schedule_controller.dart index 30ad306..aa3fcbc 100644 --- a/lib/application/controllers/calendar_schedule_controller.dart +++ b/lib/application/controllers/calendar_schedule_controller.dart @@ -1,11 +1,13 @@ import 'package:get/get.dart'; +import 'package:reverse_nn/application/dto/schedule.dart'; +import 'package:reverse_nn/application/services/remote_config/service.dart'; import 'package:reverse_nn/application/services/schedule.dart'; import 'package:reverse_nn/ui/screens/calendar_screen.dart'; class CalendarScheduleController extends GetxController { Rx date = DateTime.now().copyWith(hour: 12, minute: 00).obs; RxBool loading = false.obs; - Rx>?> schedule = null.obs; + Rx?> schedule = null.obs; @override void onReady() { super.onReady(); @@ -26,14 +28,26 @@ class CalendarScheduleController extends GetxController { } void goToPrevDay() async { - if(date.value.isBefore(DateTime(2024, 8, 1, 23, 59))) return; - date = (date.value.copyWith().subtract(const Duration(days: 1)).copyWith(hour: 12, minute: 0)).obs; + final newDate = date.value + .copyWith(hour: 12, minute: 0, second: 0, microsecond: 0, millisecond: 0) + .subtract(const Duration(days: 1)); + final dateStart = await ReverseNNRuStoreRemoteConfig().getStartScheduleDate(); + + if(newDate.isBefore(dateStart)) return; + + date = newDate.obs; loadSchedule(date.value); } void goToNextDay() async { - if(date.value.isAfter(DateTime(2025, 12, 31))) return; - date = (date.value.copyWith().add(const Duration(days: 1)).copyWith(hour: 12, minute: 0)).obs; + final newDate = date.value + .copyWith(hour: 12, minute: 0, second: 0, microsecond: 0, millisecond: 0) + .add(const Duration(days: 1)); + final dateEnd = await ReverseNNRuStoreRemoteConfig().getEndScheduleDate(); + + if(newDate.isAfter(dateEnd)) return; + + date = newDate.obs; loadSchedule(date.value); } } \ No newline at end of file diff --git a/lib/application/controllers/schedule_controller.dart b/lib/application/controllers/schedule_controller.dart index e5472f6..598eb5b 100644 --- a/lib/application/controllers/schedule_controller.dart +++ b/lib/application/controllers/schedule_controller.dart @@ -2,10 +2,11 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; +import 'package:reverse_nn/application/dto/schedule.dart'; import 'package:reverse_nn/application/services/schedule.dart'; class ScheduleController extends GetxController { - Rx?> currentSchedule = null.obs; + Rx currentSchedule = null.obs; @override void onReady() { super.onReady(); diff --git a/lib/application/dto/direction.dart b/lib/application/dto/direction.dart new file mode 100644 index 0000000..48e3ff6 --- /dev/null +++ b/lib/application/dto/direction.dart @@ -0,0 +1,25 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:json_annotation/json_annotation.dart'; + +enum Direction { + @JsonValue('in_city') inCity, + @JsonValue('change') change, + @JsonValue('out_city') outCity; + + String displayName() { + switch(this) { + case Direction.inCity: return 'В город'; + case Direction.change: return 'Переключение'; + case Direction.outCity: return 'Из города'; + } + } + + IconData icon() { + switch(this) { + case Direction.inCity: return Icons.input_outlined; + case Direction.change: return Icons.change_circle_outlined; + case Direction.outCity: return Icons.output_outlined; + } + } +} \ No newline at end of file diff --git a/lib/application/dto/rule.dart b/lib/application/dto/rule.dart new file mode 100644 index 0000000..a12af8a --- /dev/null +++ b/lib/application/dto/rule.dart @@ -0,0 +1,15 @@ +import "package:json_annotation/json_annotation.dart" show FieldRename, JsonSerializable; + +part 'rule.g.dart'; + +@JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true) +class Rule { + final DateTime after; + final DateTime? before; + final Map dataset; + + Rule({required this.after, required this.before, required this.dataset}); + + factory Rule.fromJson(Map json) => _$RuleFromJson(json); + Map toJson() => _$RuleToJson(this); +} \ No newline at end of file diff --git a/lib/application/dto/rule.g.dart b/lib/application/dto/rule.g.dart new file mode 100644 index 0000000..d5b3cf5 --- /dev/null +++ b/lib/application/dto/rule.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'rule.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Rule _$RuleFromJson(Map json) => Rule( + after: DateTime.parse(json['after'] as String), + before: json['before'] == null + ? null + : DateTime.parse(json['before'] as String), + dataset: Map.from(json['dataset'] as Map), + ); + +Map _$RuleToJson(Rule instance) => { + 'after': instance.after.toIso8601String(), + 'before': instance.before?.toIso8601String(), + 'dataset': instance.dataset, + }; diff --git a/lib/application/dto/schedule.dart b/lib/application/dto/schedule.dart new file mode 100644 index 0000000..e38ff06 --- /dev/null +++ b/lib/application/dto/schedule.dart @@ -0,0 +1,41 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:reverse_nn/application/dto/direction.dart'; + +part 'schedule.g.dart'; + +@JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true) +class ScheduleItem { + final int duration; + final Direction direction; + + final DateTime? start; + final DateTime? end; + final bool? showStartDate; + final bool? showEndDate; + + ScheduleItem({ + required this.duration, + required this.direction, + this.start, + this.end, + this.showStartDate, + this.showEndDate + }); + + factory ScheduleItem.fromJson(Map json) => _$ScheduleItemFromJson(json); + Map toJson() => _$ScheduleItemToJson(this); + + ScheduleItem fillAdditional({ + required DateTime start, + required DateTime end, + required bool showStartDate, + required bool showEndDate + }) => ScheduleItem( + duration: duration, + direction: direction, + start: start, + end: end, + showStartDate: showStartDate, + showEndDate: showEndDate, + ); +} \ No newline at end of file diff --git a/lib/application/dto/schedule.g.dart b/lib/application/dto/schedule.g.dart new file mode 100644 index 0000000..c927c2b --- /dev/null +++ b/lib/application/dto/schedule.g.dart @@ -0,0 +1,34 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'schedule.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ScheduleItem _$ScheduleItemFromJson(Map json) => ScheduleItem( + duration: (json['duration'] as num).toInt(), + direction: $enumDecode(_$DirectionEnumMap, json['direction']), + start: json['start'] == null + ? null + : DateTime.parse(json['start'] as String), + end: json['end'] == null ? null : DateTime.parse(json['end'] as String), + showStartDate: json['show_start_date'] as bool?, + showEndDate: json['show_end_date'] as bool?, + ); + +Map _$ScheduleItemToJson(ScheduleItem instance) => + { + 'duration': instance.duration, + 'direction': _$DirectionEnumMap[instance.direction]!, + 'start': instance.start?.toIso8601String(), + 'end': instance.end?.toIso8601String(), + 'show_start_date': instance.showStartDate, + 'show_end_date': instance.showEndDate, + }; + +const _$DirectionEnumMap = { + Direction.inCity: 'in_city', + Direction.change: 'change', + Direction.outCity: 'out_city', +}; diff --git a/lib/application/services/remote_config/parameters.dart b/lib/application/services/remote_config/parameters.dart new file mode 100644 index 0000000..1573b51 --- /dev/null +++ b/lib/application/services/remote_config/parameters.dart @@ -0,0 +1,5 @@ +import 'package:flutter_rustore_remoteconfig/rustore_remote_config.dart'; + +class ReverseNNRemoteConfigParameters extends StaticParameters { + +} \ No newline at end of file diff --git a/lib/application/services/remote_config/service.dart b/lib/application/services/remote_config/service.dart new file mode 100644 index 0000000..291c0c7 --- /dev/null +++ b/lib/application/services/remote_config/service.dart @@ -0,0 +1,131 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_rustore_remoteconfig/flutter_rustore_remoteconfig.dart'; +import 'package:flutter_rustore_remoteconfig/rustore_remote_config.dart'; +import 'package:reverse_nn/application/dto/rule.dart'; +import 'package:reverse_nn/application/dto/schedule.dart'; +import 'package:reverse_nn/configuration.dart'; +import 'package:reverse_nn/application/services/remote_config/parameters.dart'; + +class ReverseNNRuStoreRemoteConfig { + void create() { + FlutterRustoreRemoteconfig.create( + Configuration.ruStoreRemoteConfigAppID, + PluginUpdateBehavior.defaultBehavior, + 15, + ReverseNNRemoteConfigParameters(), + onInitComplete: () { + if(kDebugMode) { log('RuStore Remote Config - onInitComplete'); } + }, + onFirstLoadComplete: () { + if(kDebugMode) { log('RuStore Remote Config - onFirstLoadComplete'); } + }, + onMemoryCacheUpdated: () { + if(kDebugMode) { log('RuStore Remote Config - onMemoryCacheUpdated'); } + } + ); + } + + Future getStartScheduleDate() async { + try { + FlutterRustoreRemoteconfig.init(); + final remoteConfig = await FlutterRustoreRemoteconfig.getRemoteConfig(); + final startScheduleDate = remoteConfig.getString('startScheduleDate'); + + return startScheduleDate != null + ? DateTime.parse(startScheduleDate) + : DateTime(2024, 8, 1); + } + catch (error) { + if(kDebugMode) { + log('ReverseNNRuStoreRemoteConfig.getStartScheduleDate - error - ${error.toString()}'); + } + return DateTime(2024, 8, 1); + } + } + + Future getEndScheduleDate() async { + try { + FlutterRustoreRemoteconfig.init(); + final remoteConfig = await FlutterRustoreRemoteconfig.getRemoteConfig(); + final endScheduleDate = remoteConfig.getString('endScheduleDate'); + + return endScheduleDate != null + ? DateTime.parse(endScheduleDate) + : DateTime(2025, 12, 31, 23, 59, 59, 999, 999); + } + catch (error) { + if(kDebugMode) { + log('ReverseNNRuStoreRemoteConfig.getEndScheduleDate - error - ${error.toString()}'); + } + return DateTime(2025, 12, 31, 23, 59, 59, 999, 999); + } + } + + Future?> getRules() async { + try { + FlutterRustoreRemoteconfig.init(); + final remoteConfig = await FlutterRustoreRemoteconfig.getRemoteConfig(); + final rules = remoteConfig.getString('scheduleRules'); + + return rules != null + ? (jsonDecode(rules) as List).map((el) => Rule.fromJson(el)).toList() + : await _getRulesFromStorage(); + } + catch(error) { + if(kDebugMode) { + log('ReverseNNRuStoreRemoteConfig.getRules - error - ${error.toString()}'); + } + return await _getRulesFromStorage(); + } + } + + Future?> _getRulesFromStorage() async { + final Map? schema = await _getSchemaFromStorage(); + if(schema == null || !schema.containsKey('rules')) return null; + + return (schema['rules'] as List) + .map((el) => Rule.fromJson(el)) + .toList(); + } + + Future?> getScheduleByKey(String key) async { + try { + FlutterRustoreRemoteconfig.init(); + final remoteConfig = await FlutterRustoreRemoteconfig.getRemoteConfig(); + final schedule = remoteConfig.getString('schedules-$key'); + + return schedule != null + ? (jsonDecode(schedule) as List) + .map((el) => ScheduleItem.fromJson(el)) + .toList() + : await _getScheduleByKeyFromStorage(key); + } + catch(error) { + if(kDebugMode) { + log('ReverseNNRuStoreRemoteConfig.getScheduleByKey($key) - error - ${error.toString()}'); + } + return await _getScheduleByKeyFromStorage(key); + } + } + + Future?> _getScheduleByKeyFromStorage(String key) async { + final Map? schema = await _getSchemaFromStorage(); + if( + schema == null + || !schema.containsKey('schedules') + || !(schema['schedules'] as Map).containsKey(key) + ) return null; + + return (schema['schedules'][key] as List) + .map((el) => ScheduleItem.fromJson(el)) + .toList(); + } + + Future?> _getSchemaFromStorage() async { + return jsonDecode(await rootBundle.loadString('assets/schedule.json')); + } +} \ No newline at end of file diff --git a/lib/application/services/schedule.dart b/lib/application/services/schedule.dart index 8cff9c6..3c163d2 100644 --- a/lib/application/services/schedule.dart +++ b/lib/application/services/schedule.dart @@ -5,43 +5,25 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart' show DateFormat; import 'package:flutter/services.dart'; +import 'package:reverse_nn/application/dto/rule.dart'; +import 'package:reverse_nn/application/dto/schedule.dart'; +import 'package:reverse_nn/application/services/remote_config/service.dart'; class ScheduleService { static const Duration dayOffset = Duration(hours: 4); - Future> getSchema() async { - final source = await rootBundle - .loadString('assets/schedule.json'); - return jsonDecode(source); - } + Future getRuleByDate(DateTime date) async { + final List? rules = await ReverseNNRuStoreRemoteConfig().getRules(); + if(rules == null) return null; - Future?> getRule(DateTime day) async { - final Map schema = await getSchema(); - if(!schema.containsKey('rules')) return null; - - for(final Map rule in (schema['rules'] as List)) { - final DateTime after = DateTime.parse(rule['after']); - final DateTime? before = rule['before'] != null - ? DateTime.parse(rule['before']) - : null; - - if(day.isAfter(after) && (before == null || day.isBefore(before))) + for(final Rule rule in rules) { + if(date.isAfter(rule.after) && (rule.before == null || date.isBefore(rule.before!))) { return rule; } } return null; } - Future?> getDataset(DateTime day) async { - final Map? rule = await getRule(day); - - if(rule == null || !rule.containsKey('dataset')) return null; - - return (rule['dataset'] as Map).map((key, value) { - return MapEntry(key, value.toString()); - }); - } - String datetimeWeekdayToDatasetKey(int weekday) { switch(weekday){ case DateTime.monday: return 'monday'; @@ -56,17 +38,7 @@ class ScheduleService { return 'monday'; } - Future>?> getScheduleByKey(String key) async { - final Map schema = await getSchema(); - if(!schema.containsKey('schedules')) return null; - if(!(schema['schedules'] as Map).containsKey(key)) return null; - - return (schema['schedules'][key] as List).map((element) { - return element as Map; - }).toList(); - } - - Future>?> getScheduleByDate(DateTime datetime, {bool force = false}) async { + Future?> getScheduleByDate(DateTime datetime, {bool force = false}) async { final dateStart = datetime.copyWith(hour: 0, minute: 0, second: 0, microsecond: 0, millisecond: 0); final dateEnd = datetime.copyWith(hour: 23, minute: 59, second: 59, microsecond: 999, millisecond: 999); final datetimeStartWithOffset = dateStart.copyWith().add(dayOffset); @@ -75,7 +47,7 @@ class ScheduleService { ? datetime : datetime.copyWith().subtract(const Duration(days: 1)); - final Map? dataset = await getDataset(usedScheduleDatetime); + final Map? dataset = (await getRuleByDate(usedScheduleDatetime))?.dataset; if(dataset == null) return null; final String dayKey = DateFormat('y-M-d').format(usedScheduleDatetime); @@ -87,74 +59,55 @@ class ScheduleService { if(scheduleKey == null) return null; - List>? schedule = await getScheduleByKey(scheduleKey); + List? schedule = await ReverseNNRuStoreRemoteConfig().getScheduleByKey(scheduleKey); if(schedule == null) return null; int durationOffset = 0; for (var i = 0; i < schedule.length; i++) { - final scheduleItem = schedule[i]; - final int duration = (scheduleItem['duration'] as int); + final ScheduleItem scheduleItem = schedule[i]; DateTime start = datetimeStartWithOffset.copyWith().add(Duration(minutes: durationOffset)); - DateTime end = datetimeStartWithOffset.copyWith().add(Duration(minutes: durationOffset + duration)); - durationOffset += duration; + DateTime end = datetimeStartWithOffset.copyWith().add(Duration(minutes: durationOffset + scheduleItem.duration)); + durationOffset += scheduleItem.duration; if(!force) { if(i == 0) { final schedulePrevDay = await getScheduleByDate(datetime.copyWith().subtract(const Duration(days: 1)), force: true); final lastScheduleElement = schedulePrevDay?.last; - if(lastScheduleElement != null && (lastScheduleElement['direction'] as String) == (scheduleItem['direction'] as String)) { - start = start.subtract(Duration(minutes: lastScheduleElement['duration'] as int)); + if(lastScheduleElement != null && lastScheduleElement.direction == scheduleItem.direction) { + start = start.subtract(Duration(minutes: lastScheduleElement.duration)); } } if(i == (schedule.length -1)) { final scheduleNextDay = await getScheduleByDate(datetime.copyWith().add(const Duration(days: 1)), force: true); final firstScheduleElement = scheduleNextDay?.first; - if(firstScheduleElement != null && (firstScheduleElement['direction'] as String) == (scheduleItem['direction'] as String)) { - end = end.add(Duration(minutes: firstScheduleElement['duration'] as int)); + if(firstScheduleElement != null && firstScheduleElement.direction == scheduleItem.direction) { + end = end.add(Duration(minutes: firstScheduleElement.duration)); } } } - schedule[i]['start'] = start; - schedule[i]['show_start_date'] = !(start.isAfter(dateStart) && start.isBefore(dateEnd)); - schedule[i]['end'] = end; - schedule[i]['show_end_date'] = !(end.isAfter(dateStart) && end.isBefore(dateEnd)); + schedule[i] = scheduleItem.fillAdditional( + start: start, + end: end, + showStartDate: !(start.isAfter(dateStart) && start.isBefore(dateEnd)), + showEndDate: !(end.isAfter(dateStart) && end.isBefore(dateEnd)) + ); } return schedule; } - Future?> getCurrentStatus() async { + Future getCurrentStatus() async { final DateTime now = DateTime.now(); - final List>? schedule = await getScheduleByDate(now); + final List? schedule = await getScheduleByDate(now); if(schedule == null) return null; - for(var i = 0; i < schedule.length; i++) { - final start = schedule[i]['start']; - final end = schedule[i]['end']; - - if(now.isAfter(start) && now.isBefore(end)) { - return schedule[i]; - } + for(final ScheduleItem item in schedule) { + if(item.start == null || item.end == null) continue; + if(now.isAfter(item.start!) && now.isBefore(item.end!)) return item; } return null; } - - static String formatDirection(String direction) { - switch(direction) { - case 'in_city': return 'В город'; - case 'out_city': return 'Из города'; - default: return 'Переключение'; - } - } - - static IconData getIconByDirection(String? direction) { - switch(direction) { - case 'in_city': return Icons.input_outlined; - case 'out_city': return Icons.output_outlined; - default: return Icons.change_circle_outlined; - } - } } \ No newline at end of file diff --git a/lib/configuration.dart b/lib/configuration.dart new file mode 100644 index 0000000..b350e47 --- /dev/null +++ b/lib/configuration.dart @@ -0,0 +1,3 @@ +class Configuration { + static const String ruStoreRemoteConfigAppID = '12cbda1f-4601-4f6d-924d-64a210005e96'; +} \ No newline at end of file diff --git a/lib/enums/direction.dart b/lib/enums/direction.dart deleted file mode 100644 index 185158d..0000000 --- a/lib/enums/direction.dart +++ /dev/null @@ -1,11 +0,0 @@ -enum Direction { - inCity(displayName: 'В город'), - change(displayName: 'Переключение'), - outCity(displayName: 'Из города'); - - const Direction({ - required this.displayName - }); - - final String displayName; -} \ No newline at end of file diff --git a/lib/enums/schedule.dart b/lib/enums/schedule.dart deleted file mode 100644 index 5bfb4f7..0000000 --- a/lib/enums/schedule.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:reverse_nn/enums/direction.dart'; -import 'package:sprintf/sprintf.dart'; - -enum Schedule { - daily(elements: [ - ScheduleElement(startHours: 4, startMinutes: 0, duration: 415, direction: Direction.inCity), - ScheduleElement(startHours: 10, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 11, startMinutes: 0, duration: 115, direction: Direction.outCity), - ScheduleElement(startHours: 12, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 13, startMinutes: 0, duration: 145, direction: Direction.inCity), - ScheduleElement(startHours: 15, startMinutes: 25, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 15, startMinutes: 30, duration: 205, direction: Direction.outCity), - ScheduleElement(startHours: 18, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 19, startMinutes: 0, duration: 55, direction: Direction.inCity), - ScheduleElement(startHours: 19, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 20, startMinutes: 0, duration: 475, direction: Direction.outCity), - ScheduleElement(startHours: 3, startMinutes: 55, duration: 5, direction: Direction.change), - ]), - friday(elements: [ - ScheduleElement(startHours: 4, startMinutes: 0, duration: 415, direction: Direction.inCity), - ScheduleElement(startHours: 10, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 11, startMinutes: 0, duration: 115, direction: Direction.outCity), - ScheduleElement(startHours: 12, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 13, startMinutes: 0, duration: 55, direction: Direction.inCity), - ScheduleElement(startHours: 13, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 14, startMinutes: 0, duration: 840, direction: Direction.outCity), - ]), - saturday(elements: [ - ScheduleElement(startHours: 4, startMinutes: 0, duration: 655, direction: Direction.outCity), - ScheduleElement(startHours: 14, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 15, startMinutes: 0, duration: 175, direction: Direction.inCity), - ScheduleElement(startHours: 17, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 18, startMinutes: 0, duration: 115, direction: Direction.outCity), - ScheduleElement(startHours: 19, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 20, startMinutes: 0, duration: 115, direction: Direction.inCity), - ScheduleElement(startHours: 21, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 22, startMinutes: 0, duration: 355, direction: Direction.outCity), - ScheduleElement(startHours: 3, startMinutes: 55, duration: 5, direction: Direction.change), - ]), - sunday(elements: [ - ScheduleElement(startHours: 4, startMinutes: 0, duration: 235, direction: Direction.inCity), - ScheduleElement(startHours: 7, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 8, startMinutes: 0, duration: 175, direction: Direction.outCity), - ScheduleElement(startHours: 10, startMinutes: 55, duration: 5, direction: Direction.change), - ScheduleElement(startHours: 11, startMinutes: 0, duration: 1020, direction: Direction.inCity), - ]); - - const Schedule({required this.elements}); - - final List elements; -} - -class ScheduleElement { - final int startHours; - final int startMinutes; - - final int duration; - final Direction direction; - - const ScheduleElement({required this.startHours, required this.startMinutes, required this.duration, required this.direction}); - - String getStartedTimeString() { return sprintf('%02i:%02i', [startHours, startMinutes]); } - String getEndedTimeString() { - DateTime e = DateTime(2024, 8, 1, startHours, startMinutes).add(Duration(minutes: duration)).subtract(const Duration(microseconds: 1)); - return sprintf('%02i:%02i', [e.hour, e.minute]); - } -} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index a66286f..03aace8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:get_storage/get_storage.dart'; import 'package:reverse_nn/application.dart'; +import 'package:reverse_nn/application/services/remote_config/service.dart'; void main() async { await GetStorage.init(); + ReverseNNRuStoreRemoteConfig().create(); runApp(const ReversNNApplication()); } diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart deleted file mode 100644 index 2dc1661..0000000 --- a/lib/pages/home_page.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:reverse_nn/widgets/schedule_widget.dart'; - -class HomePage extends StatelessWidget { - const HomePage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: const Text('Реверс НН'), - ), - body: const ScheduleWidget() - ); - } - -} \ No newline at end of file diff --git a/lib/ui/components/schedule_item_component.dart b/lib/ui/components/schedule_item_component.dart index 19a4400..db8b07a 100644 --- a/lib/ui/components/schedule_item_component.dart +++ b/lib/ui/components/schedule_item_component.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart' show DateFormat; -import 'package:reverse_nn/application/services/schedule.dart'; +import 'package:reverse_nn/application/dto/schedule.dart'; class ScheduleItemComponent extends StatelessWidget { - final Map item; + final ScheduleItem item; const ScheduleItemComponent({super.key, required this.item}); @override @@ -20,7 +20,7 @@ class ScheduleItemComponent extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(ScheduleService.getIconByDirection(item['direction'] as String), size: 56), + Icon(item.direction.icon(), size: 56), const SizedBox(width: 16), Expanded(child: Column( mainAxisAlignment: MainAxisAlignment.start, @@ -41,17 +41,17 @@ class ScheduleItemComponent extends StatelessWidget { } Widget _directionText(BuildContext context) => Text( - ScheduleService.formatDirection(item['direction'] ?? ''), + item.direction.displayName(), style: Theme.of(context).textTheme.headlineLarge ); Widget _startText(BuildContext context) => Text( - 'C\t\t\t\t${formatDate(item['start'], showDate: item['show_start_date'] ?? false)}', + 'C\t\t\t\t${formatDate(item.start!, showDate: item.showStartDate ?? false)}', style: Theme.of(context).textTheme.titleLarge ); Widget _endText(BuildContext context) => Text( - 'До\t${formatDate(item['end'], showDate: item['show_end_date'] ?? false)}', + 'До\t${formatDate(item.end!, showDate: item.showEndDate ?? false)}', style: Theme.of(context).textTheme.titleLarge ); } diff --git a/lib/ui/screens/calendar_screen.dart b/lib/ui/screens/calendar_screen.dart index 878fe6c..d7fb375 100644 --- a/lib/ui/screens/calendar_screen.dart +++ b/lib/ui/screens/calendar_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:reverse_nn/application/controllers/calendar_schedule_controller.dart'; -import 'package:reverse_nn/application/services/schedule.dart'; +import 'package:reverse_nn/application/services/remote_config/service.dart'; import 'package:reverse_nn/ui/components/schedule_item_component.dart'; import 'package:reverse_nn/ui/layouts/application_layout.dart'; import 'package:intl/intl.dart' show DateFormat; @@ -114,11 +114,14 @@ class _SelectedDateWidget extends StatelessWidget { void _openCalendar(BuildContext context) async { DateTime now = DateTime.now(); + DateTime firstDate = await ReverseNNRuStoreRemoteConfig().getStartScheduleDate(); + DateTime lastDate = await ReverseNNRuStoreRemoteConfig().getEndScheduleDate(); + DateTime? picked = await showDatePicker( context: context, initialDate: now, - firstDate: DateTime(2024, 8, 1, 12), - lastDate: DateTime(2025, 12, 31, 12), + firstDate: firstDate, + lastDate: lastDate, locale: const Locale('ru') ); diff --git a/lib/ui/screens/home_screen.dart b/lib/ui/screens/home_screen.dart index 367bd1e..2817e7e 100644 --- a/lib/ui/screens/home_screen.dart +++ b/lib/ui/screens/home_screen.dart @@ -1,6 +1,8 @@ import 'dart:developer'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_rustore_remoteconfig/flutter_rustore_remoteconfig.dart'; import 'package:get/get.dart'; import 'package:reverse_nn/application/controllers/calendar_schedule_controller.dart'; import 'package:reverse_nn/application/controllers/home_controller.dart'; @@ -8,6 +10,7 @@ import 'package:reverse_nn/application/services/schedule.dart'; import 'package:reverse_nn/ui/components/current_status_component.dart'; import 'package:reverse_nn/ui/components/grid_menu_item.dart'; import 'package:reverse_nn/ui/layouts/application_layout.dart'; +import 'package:reverse_nn/application/services/remote_config/service.dart'; class HomeScreen extends GetWidget { const HomeScreen({super.key}); @@ -29,8 +32,9 @@ class HomeScreen extends GetWidget { mainAxisSpacing: 10, crossAxisSpacing: 10, ), - children: const [ - GridMenuItem(icon: Icons.calendar_month, label: 'Расписание', onTap: CalendarScheduleController.openScreen), + children: [ + const GridMenuItem(icon: Icons.calendar_month, label: 'Расписание', onTap: CalendarScheduleController.openScreen), + if(kDebugMode) GridMenuItem(icon: Icons.android, label: 'DEBUG', onTap: _debugRuStore), // const GridMenuItem(icon: Icons.monetization_on, label: 'Поддержать автора'), // GridMenuItem(), // GridMenuItem(), @@ -41,4 +45,10 @@ class HomeScreen extends GetWidget { ), )); } + + void _debugRuStore() async { + ReverseNNRuStoreRemoteConfig().getEndScheduleDate().then((value) { + log(value.toIso8601String()); + }); + } } \ No newline at end of file diff --git a/lib/utils/scheduler.dart b/lib/utils/scheduler.dart deleted file mode 100644 index 502e126..0000000 --- a/lib/utils/scheduler.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:reverse_nn/enums/schedule.dart'; - -class Scheduler { - static Schedule getSchedule(DateTime date) { - switch(date.weekday) { - case DateTime.friday: return Schedule.friday; - case DateTime.saturday: return Schedule.saturday; - case DateTime.sunday: return Schedule.sunday; - - default: return Schedule.daily; - } - } - - static List getScheduleList() { - List result = List.empty(growable: true); - - DateTime now = DateTime.now(); - DateTime startSchedule = now.hour < 4 ? now.subtract(const Duration(days: 1)) : now; - - bool currentReached = false; - for (ScheduleElement element in [...Scheduler.getSchedule(startSchedule).elements, ...Scheduler.getSchedule(startSchedule.add(const Duration(days: 1))).elements]) { - if(!currentReached) { - DateTime s = DateTime(now.year, now.month, now.day, element.startHours, element.startMinutes, 0); - if(now.compareTo(startSchedule) != 0 && element.startHours >= 4) { s = s.subtract(const Duration(days: 1)); } - DateTime e = s.add(Duration(minutes: element.duration)).subtract(const Duration(microseconds: 1)); - - if(now.isAfter(s) && now.isBefore(e)) { currentReached = true; } - else { continue; } - } - - result.add(element); - } - - return result; - } -} \ No newline at end of file diff --git a/lib/widgets/loader_widget.dart b/lib/widgets/loader_widget.dart deleted file mode 100644 index 1311b4b..0000000 --- a/lib/widgets/loader_widget.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:flutter/material.dart'; - -class LoaderWidget extends StatelessWidget { - const LoaderWidget({super.key}); - - @override - Widget build(BuildContext context) { - return const Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CircularProgressIndicator() - ], - ); - } -} \ No newline at end of file diff --git a/lib/widgets/schedule_element_widget.dart b/lib/widgets/schedule_element_widget.dart deleted file mode 100644 index aca4cff..0000000 --- a/lib/widgets/schedule_element_widget.dart +++ /dev/null @@ -1,79 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:reverse_nn/enums/direction.dart'; -import 'package:reverse_nn/enums/schedule.dart'; -import 'package:sprintf/sprintf.dart'; - -class CurrentReversWidget extends StatelessWidget { - const CurrentReversWidget({super.key, required this.scheduleElement}); - - final ScheduleElement scheduleElement; - - IconData _getIconData() { - switch(scheduleElement.direction) { - case Direction.inCity: return Icons.arrow_upward; - case Direction.outCity: return Icons.arrow_downward; - case Direction.change: return Icons.cancel_outlined; - } - } - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16.0), - - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(8.0)), - color: Theme.of(context).colorScheme.primaryContainer - ), - - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - - children: [ - Icon(_getIconData(), size: 56.0), - const SizedBox(width: 10), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Реверс: ${scheduleElement.direction.displayName}', style: const TextStyle(fontSize: 20)), - Text('${scheduleElement.getStartedTimeString()} - ${scheduleElement.getEndedTimeString()}', style: const TextStyle(fontSize: 36)), - ], - ) - ], - ), - ); - } -} - -class ScheduledReversWidget extends StatelessWidget { - const ScheduledReversWidget({super.key, required this.scheduleElement}); - - final ScheduleElement scheduleElement; - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(8), - margin: const EdgeInsets.symmetric(horizontal: 8), - - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(8.0)), - color: Theme.of(context).colorScheme.secondaryContainer - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text(sprintf('Следующий статус в %02i:%02i - %s', [ - scheduleElement.startHours, - scheduleElement.startMinutes, - scheduleElement.direction.displayName - ])), - ], - ), - ); - } - -} \ No newline at end of file diff --git a/lib/widgets/schedule_widget.dart b/lib/widgets/schedule_widget.dart deleted file mode 100644 index fb51c48..0000000 --- a/lib/widgets/schedule_widget.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:reverse_nn/enums/schedule.dart'; -import 'package:reverse_nn/utils/scheduler.dart'; -import 'package:reverse_nn/widgets/loader_widget.dart'; -import 'package:reverse_nn/widgets/schedule_element_widget.dart'; - -class ScheduleWidget extends StatefulWidget { - const ScheduleWidget({super.key}); - - @override - State createState() => _ScheduleWidgetState(); -} - -class _ScheduleWidgetState extends State { - bool _loading = true; - List _schedule = List.empty(); - - void loadScheduleData() async { - setState(() { _loading = true; }); - setState(() { _schedule = Scheduler.getScheduleList(); }); - setState(() { _loading = false; }); - } - - @override - Widget build(BuildContext context) { - loadScheduleData(); - - Future.delayed(const Duration(seconds: 15), () => loadScheduleData()); - - return _loading && _schedule.isNotEmpty ? const LoaderWidget() : ListView.separated( - scrollDirection: Axis.vertical, - shrinkWrap: true, - padding: const EdgeInsets.all(10), - separatorBuilder: (BuildContext context, int index) { - return SizedBox(height: index == 0 ? 10 : 4); - }, - itemCount: _schedule.length, - itemBuilder: (ctx, i) { - if(i == 0) { return CurrentReversWidget(scheduleElement: _schedule[i]); } - return ScheduledReversWidget(scheduleElement: _schedule[i]); - }, - ); - } -} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 3d9c286..8e2102c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,27 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 + url: "https://pub.dev" + source: hosted + version: "72.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.2" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 + url: "https://pub.dev" + source: hosted + version: "6.7.0" archive: dependency: transitive description: @@ -33,6 +54,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2" + url: "https://pub.dev" + source: hosted + version: "8.9.3" characters: dependency: transitive description: @@ -65,6 +150,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" collection: dependency: transitive description: @@ -73,6 +166,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" crypto: dependency: transitive description: @@ -89,6 +190,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.7" fake_async: dependency: transitive description: @@ -105,6 +214,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -131,11 +256,27 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_rustore_remoteconfig: + dependency: "direct main" + description: + name: flutter_rustore_remoteconfig + sha256: f5dfccc3f4270bcd3fdadccc2c79514cd0db9b56103f92b0f7af19a79acab5b8 + url: "https://pub.dev" + source: hosted + version: "7.0.0" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" get: dependency: "direct main" description: @@ -152,6 +293,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" image: dependency: transitive description: @@ -168,14 +341,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.19.0" - json_annotation: + io: dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: "direct main" description: name: json_annotation sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" url: "https://pub.dev" source: hosted version: "4.9.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c + url: "https://pub.dev" + source: hosted + version: "6.9.0" leak_tracker: dependency: transitive description: @@ -208,6 +405,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + macros: + dependency: transitive + description: + name: macros + sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" + url: "https://pub.dev" + source: hosted + version: "0.1.2-main.4" matcher: dependency: transitive description: @@ -232,6 +445,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67" + url: "https://pub.dev" + source: hosted + version: "2.1.1" path: dependency: transitive description: @@ -312,11 +541,67 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 + url: "https://pub.dev" + source: hosted + version: "2.0.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" + url: "https://pub.dev" + source: hosted + version: "1.3.5" source_span: dependency: transitive description: @@ -349,6 +634,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" string_scanner: dependency: transitive description: @@ -373,6 +666,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.2" + timing: + dependency: transitive + description: + name: timing + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" + url: "https://pub.dev" + source: hosted + version: "1.0.2" typed_data: dependency: transitive description: @@ -397,6 +698,38 @@ packages: url: "https://pub.dev" source: hosted version: "14.2.5" + watcher: + dependency: transitive + description: + name: watcher + sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + url: "https://pub.dev" + source: hosted + version: "3.0.1" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 467ddc9..e79a188 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.1.0+3 +version: 1.1.1+4 environment: sdk: '>=3.3.3 <4.0.0' @@ -41,6 +41,8 @@ dependencies: get: ^4.6.6 get_storage: ^2.1.1 sprintf: "^7.0.0" + flutter_rustore_remoteconfig: ^7.0.0 + json_annotation: ^4.9.0 dev_dependencies: flutter_test: @@ -53,6 +55,8 @@ dev_dependencies: # rules and activating additional ones. flutter_lints: ^3.0.0 flutter_launcher_icons: "^0.13.1" + json_serializable: ^6.9.0 + build_runner: ^2.4.13 flutter_launcher_icons: android: "launcher_icon"