RuStore Remote Config
This commit is contained in:
@@ -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<DateTime> date = DateTime.now().copyWith(hour: 12, minute: 00).obs;
|
||||
RxBool loading = false.obs;
|
||||
Rx<List<Map<String, dynamic>>?> schedule = null.obs;
|
||||
Rx<List<ScheduleItem>?> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<Map<String, dynamic>?> currentSchedule = null.obs;
|
||||
Rx<ScheduleItem?> currentSchedule = null.obs;
|
||||
|
||||
@override void onReady() {
|
||||
super.onReady();
|
||||
|
||||
25
lib/application/dto/direction.dart
Normal file
25
lib/application/dto/direction.dart
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
lib/application/dto/rule.dart
Normal file
15
lib/application/dto/rule.dart
Normal file
@@ -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<String, String> dataset;
|
||||
|
||||
Rule({required this.after, required this.before, required this.dataset});
|
||||
|
||||
factory Rule.fromJson(Map<String, dynamic> json) => _$RuleFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$RuleToJson(this);
|
||||
}
|
||||
21
lib/application/dto/rule.g.dart
Normal file
21
lib/application/dto/rule.g.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'rule.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Rule _$RuleFromJson(Map<String, dynamic> json) => Rule(
|
||||
after: DateTime.parse(json['after'] as String),
|
||||
before: json['before'] == null
|
||||
? null
|
||||
: DateTime.parse(json['before'] as String),
|
||||
dataset: Map<String, String>.from(json['dataset'] as Map),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$RuleToJson(Rule instance) => <String, dynamic>{
|
||||
'after': instance.after.toIso8601String(),
|
||||
'before': instance.before?.toIso8601String(),
|
||||
'dataset': instance.dataset,
|
||||
};
|
||||
41
lib/application/dto/schedule.dart
Normal file
41
lib/application/dto/schedule.dart
Normal file
@@ -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<String, dynamic> json) => _$ScheduleItemFromJson(json);
|
||||
Map<String, dynamic> 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,
|
||||
);
|
||||
}
|
||||
34
lib/application/dto/schedule.g.dart
Normal file
34
lib/application/dto/schedule.g.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'schedule.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ScheduleItem _$ScheduleItemFromJson(Map<String, dynamic> 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<String, dynamic> _$ScheduleItemToJson(ScheduleItem instance) =>
|
||||
<String, dynamic>{
|
||||
'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',
|
||||
};
|
||||
5
lib/application/services/remote_config/parameters.dart
Normal file
5
lib/application/services/remote_config/parameters.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
import 'package:flutter_rustore_remoteconfig/rustore_remote_config.dart';
|
||||
|
||||
class ReverseNNRemoteConfigParameters extends StaticParameters {
|
||||
|
||||
}
|
||||
131
lib/application/services/remote_config/service.dart
Normal file
131
lib/application/services/remote_config/service.dart
Normal file
@@ -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<DateTime> 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<DateTime> 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<List<Rule>?> getRules() async {
|
||||
try {
|
||||
FlutterRustoreRemoteconfig.init();
|
||||
final remoteConfig = await FlutterRustoreRemoteconfig.getRemoteConfig();
|
||||
final rules = remoteConfig.getString('scheduleRules');
|
||||
|
||||
return rules != null
|
||||
? (jsonDecode(rules) as List<dynamic>).map((el) => Rule.fromJson(el)).toList()
|
||||
: await _getRulesFromStorage();
|
||||
}
|
||||
catch(error) {
|
||||
if(kDebugMode) {
|
||||
log('ReverseNNRuStoreRemoteConfig.getRules - error - ${error.toString()}');
|
||||
}
|
||||
return await _getRulesFromStorage();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Rule>?> _getRulesFromStorage() async {
|
||||
final Map<String, dynamic>? schema = await _getSchemaFromStorage();
|
||||
if(schema == null || !schema.containsKey('rules')) return null;
|
||||
|
||||
return (schema['rules'] as List<dynamic>)
|
||||
.map((el) => Rule.fromJson(el))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<List<ScheduleItem>?> 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<dynamic>)
|
||||
.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<List<ScheduleItem>?> _getScheduleByKeyFromStorage(String key) async {
|
||||
final Map<String, dynamic>? schema = await _getSchemaFromStorage();
|
||||
if(
|
||||
schema == null
|
||||
|| !schema.containsKey('schedules')
|
||||
|| !(schema['schedules'] as Map<String, dynamic>).containsKey(key)
|
||||
) return null;
|
||||
|
||||
return (schema['schedules'][key] as List<dynamic>)
|
||||
.map((el) => ScheduleItem.fromJson(el))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>?> _getSchemaFromStorage() async {
|
||||
return jsonDecode(await rootBundle.loadString('assets/schedule.json'));
|
||||
}
|
||||
}
|
||||
@@ -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<Map<String, dynamic>> getSchema() async {
|
||||
final source = await rootBundle
|
||||
.loadString('assets/schedule.json');
|
||||
return jsonDecode(source);
|
||||
}
|
||||
Future<Rule?> getRuleByDate(DateTime date) async {
|
||||
final List<Rule>? rules = await ReverseNNRuStoreRemoteConfig().getRules();
|
||||
if(rules == null) return null;
|
||||
|
||||
Future<Map<String, dynamic>?> getRule(DateTime day) async {
|
||||
final Map<String, dynamic> schema = await getSchema();
|
||||
if(!schema.containsKey('rules')) return null;
|
||||
|
||||
for(final Map<String, dynamic> rule in (schema['rules'] as List<dynamic>)) {
|
||||
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<Map<String, String>?> getDataset(DateTime day) async {
|
||||
final Map<String, dynamic>? rule = await getRule(day);
|
||||
|
||||
if(rule == null || !rule.containsKey('dataset')) return null;
|
||||
|
||||
return (rule['dataset'] as Map<String, dynamic>).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<List<Map<String, dynamic>>?> getScheduleByKey(String key) async {
|
||||
final Map<String, dynamic> schema = await getSchema();
|
||||
if(!schema.containsKey('schedules')) return null;
|
||||
if(!(schema['schedules'] as Map<String, dynamic>).containsKey(key)) return null;
|
||||
|
||||
return (schema['schedules'][key] as List<dynamic>).map((element) {
|
||||
return element as Map<String, dynamic>;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>?> getScheduleByDate(DateTime datetime, {bool force = false}) async {
|
||||
Future<List<ScheduleItem>?> 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<String, String>? dataset = await getDataset(usedScheduleDatetime);
|
||||
final Map<String, String>? 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<Map<String, dynamic>>? schedule = await getScheduleByKey(scheduleKey);
|
||||
List<ScheduleItem>? 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<Map<String, dynamic>?> getCurrentStatus() async {
|
||||
Future<ScheduleItem?> getCurrentStatus() async {
|
||||
final DateTime now = DateTime.now();
|
||||
final List<Map<String, dynamic>>? schedule = await getScheduleByDate(now);
|
||||
final List<ScheduleItem>? 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user