Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
3c76fc4
Option | extension methods | unwrap
a-givertzman Nov 6, 2024
fc10e49
Option | extension methods | expect, unwrapOr, unwrapOrElse, unwrapOr
a-givertzman Nov 6, 2024
ace72f4
Option | extension methods | extension_extract
a-givertzman Nov 6, 2024
0dd741b
Option | extension methods | extension_extract
a-givertzman Nov 6, 2024
8a34c3e
Option | extension methods | extension_transform
a-givertzman Nov 7, 2024
2f4771f
Package version changed to 2.1.0
a-givertzman Nov 10, 2024
aa2d0b6
Package version changed to 2.1.2
a-givertzman Nov 10, 2024
6b0ca4d
Log | fixes
a-givertzman Nov 11, 2024
079691b
Option | extension methods | extension_querying
a-givertzman Nov 18, 2024
4c0c8e2
Option | extension methods | extension_querying
a-givertzman Nov 18, 2024
5265e9e
Merge branch 'master' into Option-extensions-rename, pull changes for…
nyaneet Nov 29, 2024
223b6c1
Option | rename extensions to avoid conflicts
nyaneet Nov 29, 2024
e856df8
Option | extensions | renamed
a-givertzman Dec 3, 2024
4cfab43
Merge branch 'Option-extension-methods-simplifying-work' into Option-…
nyaneet Dec 3, 2024
b6fab34
Merge pull request #96 from a-givertzman/Option-extensions-rename
a-givertzman Dec 3, 2024
760c265
Log | LogLevel | trace
a-givertzman Dec 11, 2024
0e4c9c9
Log | ConsoleColors fix
a-givertzman Dec 11, 2024
5851c3c
Log | ConsoleColors fix
a-givertzman Dec 11, 2024
d60ba95
Log | LogLevel | fixes
a-givertzman Dec 11, 2024
95e4f9b
Log | LogLevel | fixes
a-givertzman Dec 11, 2024
30fcb8d
Log | LogLevel | fixes
a-givertzman Dec 11, 2024
b31361c
Localizations | add getters
a-givertzman Dec 12, 2024
27bfe65
Merge pull request #99 from a-givertzman/Localizations-|-add-getters
a-givertzman Dec 12, 2024
a28446a
AppSetting | onError
a-givertzman Dec 13, 2024
9ad3f93
AppSetting | onError
a-givertzman Dec 13, 2024
fb9eefa
AppSetting | onError
a-givertzman Dec 13, 2024
4a5ec70
Merge pull request #100 from a-givertzman/AppSetting-nullable-or-opti…
a-givertzman Dec 13, 2024
270b85e
colors | Moved colors to hmi_widgets lib
Minyewoo Feb 3, 2025
b0c2bc9
pubspec | increased version to 2.1.5
Minyewoo Feb 3, 2025
92fb244
Merge branch 'Option-extension-methods-simplifying-work' into colors-…
Minyewoo Feb 3, 2025
4f2652e
Merge pull request #101 from a-givertzman/colors-removal
Minyewoo Feb 3, 2025
87051c2
JsonMap | add .fromTextFiles constructor
nyaneet Apr 17, 2025
feb1ec1
JsonMap | add tests for .fromFile constructor
nyaneet Apr 17, 2025
3b1336c
AppSettings | add writable settings
nyaneet Apr 17, 2025
3f0fe24
Setting | add update method for writable settings
nyaneet Apr 21, 2025
237836a
JsonList | add fromTextFiles constructor
nyaneet Apr 21, 2025
05089b1
JsonMap, JsonList | add tests for each named constructors
nyaneet Apr 21, 2025
385f3d0
AppSettings | add tests for setSetting method
nyaneet Apr 21, 2025
3f879b8
Setting | add tests for update method
nyaneet Apr 21, 2025
76d63e3
pubspec | update package version to 2.1.6
nyaneet Apr 21, 2025
18613e8
AppSettings | rename file parameter
nyaneet Apr 21, 2025
c13800b
AppSettings | fix that non-writable settings initialized from store file
nyaneet Apr 21, 2025
630b0c5
AppSettings | fix logging messages
nyaneet Apr 21, 2025
c6292a4
AppSettings, Setting | add tests for cases with writable settings
nyaneet Apr 22, 2025
7e6b154
AppSettings | refactor logging, naming, and remove backup on update
nyaneet Apr 22, 2025
886b28a
AppSettings | make sure that saved settings are always taken from run…
nyaneet Apr 22, 2025
76fb7a3
Merge pull request #108 from a-givertzman/AppSettings-add-writable-se…
nyaneet Apr 22, 2025
517b5d5
Failure | child
a-givertzman Jun 25, 2025
774e723
Failure | child
a-givertzman Jun 25, 2025
0db849b
Failure | child
a-givertzman Jun 25, 2025
545288b
Failure | child
a-givertzman Jun 25, 2025
c643690
Failure | child
a-givertzman Jun 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions lib/hmi_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ export 'src/core/entities/ds_data_type.dart';
export 'src/core/entities/ds_status.dart';
export 'src/core/entities/ds_timestamp.dart';
export 'src/core/entities/state_constatnts.dart';
export 'src/core/entities/alarm_colors.dart';
export 'src/core/entities/state_colors.dart';
export 'src/core/entities/stacked.dart';
// RelativeValue
export 'src/core/relative_value.dart';
Expand Down
3 changes: 0 additions & 3 deletions lib/hmi_core_alarm_colors.dart

This file was deleted.

2 changes: 0 additions & 2 deletions lib/hmi_core_entities.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,4 @@ export 'src/core/entities/ds_data_type.dart';
export 'src/core/entities/ds_status.dart';
export 'src/core/entities/ds_timestamp.dart';
export 'src/core/entities/state_constatnts.dart';
export 'src/core/entities/alarm_colors.dart';
export 'src/core/entities/state_colors.dart';
export 'src/core/entities/stacked.dart';
5 changes: 4 additions & 1 deletion lib/hmi_core_option.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
library hmi_core_option;

export 'src/core/option/option.dart';
export 'src/core/option/option.dart';
export 'src/core/option/option_extract_extension.dart';
export 'src/core/option/option_transform_extension.dart';
export 'src/core/option/option_querying_extension.dart';
3 changes: 0 additions & 3 deletions lib/hmi_core_state_colors.dart

This file was deleted.

158 changes: 140 additions & 18 deletions lib/src/app_settings/app_settings.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import 'dart:convert';
import 'package:hmi_core/src/core/error/failure.dart';
import 'package:hmi_core/src/core/json/json_map.dart';
import 'package:hmi_core/src/core/log/log.dart';
import 'package:hmi_core/src/core/result/result.dart';
import 'package:hmi_core/hmi_core_text_file.dart';
import 'package:hmi_core/src/core/result/result_transform_extension.dart';
///
/// Stores application settings.
///
/// Settings can be accessed for reading and writing by its keys.
///
/// For key names prefer to use kebab-case notation, with unique prefixes
/// for different groups of settings. E.g. `ui-padding`, `ui-font-size`,
/// `api-host`, `api-port`, etc.
class AppSettings {
static const _log = Log('AppSettings');
static final _map = <String, dynamic>{
static const _log = Log('AppSettings ');
static final _settings = <String, dynamic>{
'displaySizeWidth': 1024,
'displaySizeHeight': 768,
// Place Durations in milliseconds!
Expand All @@ -18,25 +27,138 @@ class AppSettings {
'floatingActionButtonSize': 60.0,
'floatingActionIconSize': 45.0,
};
static final _isWritable = <String, bool>{};
static TextFile _store = const TextFile.path('stored_settings.json');
///
/// Initializes app settings with [readOnly] and [writable] settings.
///
/// [readOnly] settings are accessible for reading only.
///
static Future<void> initialize({JsonMap<dynamic>? jsonMap}) async {
if (jsonMap != null) {
await jsonMap.decoded
.then((result) => switch(result) {
Ok(value: final map) => _map.addAll(map),
Err() => _log.warning('Failed to initialize app settings from file.'),
});
/// [writable] settings are accessible for reading and updating (writing).
///
/// [store] file is used to write and restore [writable] settings.
/// If not passed, file with path `stored_settings.json` will be used
/// by default.
static Future<void> initialize({
JsonMap<dynamic> readOnly = const JsonMap.empty(),
JsonMap<dynamic> writable = const JsonMap.empty(),
TextFile? store,
}) async {
if (store != null) {
_store = store;
}
_log.info('Initializing read-only app settings...');
await _parseSettings(
readOnly,
onSettingParsed: (entry) {
if (_settings.containsKey(entry.key)) {
_log.warning('Setting with key "${entry.key}" will be overwritten.');
}
_settings[entry.key] = entry.value;
_isWritable[entry.key] = false;
_log.info('Added read-only setting "${entry.key}": ${entry.value}.');
},
);
_log.info('Initializing writable app settings...');
await _parseSettings(
writable,
onSettingParsed: (entry) {
if (_settings.containsKey(entry.key)) {
_log.warning('Setting with key "${entry.key}" will be overwritten.');
}
_settings[entry.key] = entry.value;
_isWritable[entry.key] = true;
_log.info('Added writeable setting "${entry.key}": ${entry.value}.');
},
);
_log.info('Restoring writable app settings...');
await _parseSettings(
JsonMap.fromTextFile(_store),
onSettingParsed: (entry) {
if (!_canWriteSetting(entry.key)) {
_log.warning('Writeable setting with key "${entry.key}" does not exist and was ignored.');
} else {
_settings[entry.key] = entry.value;
_log.info('Restored writeable setting "${entry.key}": ${entry.value}.');
}
},
);
}
//
static Future<void> _parseSettings(
JsonMap<dynamic> settings, {
void Function(MapEntry<String, dynamic>)? onSettingParsed,
}) async {
final decodedResult = await settings.decoded;
decodedResult
.inspect((map) {
for (final entry in map.entries) {
onSettingParsed?.call(entry);
}
}).inspectErr((error) {
_log.warning('Failed to initialize app settings, ${error.message}.');
});
}
//
static bool _canWriteSetting(String key) {
return _settings.containsKey(key) && _isWritable.containsKey(key) && (_isWritable[key] ?? false);
}
///
static dynamic getSetting(String settingName) {
final setting = _map[settingName];
if (setting == null) {
throw Failure(
message: 'Ошибка в методе $AppSettings.getSetting(): Не найдена настройка "$settingName"',
stackTrace: StackTrace.current,
);
/// Returns value of app setting by [key].
///
/// Calls [onError] that can return other value based on passed [Failure].
static dynamic getSetting(
String key, {
dynamic Function(Failure err)? onError,
}) {
if (!_settings.containsKey(key)) {
final err = Failure('$AppSettings.getSetting | Not found key "$key"');
if (onError != null) {
return onError(err);
}
throw err;
}
return _settings[key];
}
///
/// Updates app setting with key [key] to new [value]
/// and save it asynchronously to file.
///
/// Calls [onSuccess] or [onError] when setting will be updated
/// and saved successfully or with error.
static Future<void> setSetting(
String key,
dynamic value, {
void Function(Failure error)? onError,
void Function()? onSuccess,
}) async {
if (!_canWriteSetting(key)) {
final failure = Failure('AppSettings.setSetting | Setting "$key" - is not writable, can\'t be updated');
onError?.call(failure);
} else {
final writableSettings = _getWritableSettings();
writableSettings[key] = value;
await _store
.write(json.encode(writableSettings)).then(
(_) {
_settings[key] = value;
onSuccess?.call();
},
).catchError(
(error, stackTrace) {
final failure = Failure('AppSettings.setSetting | Failed to save setting "$key", $error.');
_log.warning(failure);
onError?.call(failure);
},
);
}
return setting;
}
//
static Map<String, dynamic> _getWritableSettings() {
return Map.fromEntries(
_settings.entries.where(
(entry) => _canWriteSetting(entry.key),
),
);
}
}
78 changes: 57 additions & 21 deletions lib/src/app_settings/setting.dart
Original file line number Diff line number Diff line change
@@ -1,48 +1,72 @@
import 'app_settings.dart';

import 'package:hmi_core/src/core/error/failure.dart';
///
/// Holds setting value stored in AppSettings by it name
/// - value can be returned in int, double or string represantation
/// Holds setting value stored in [AppSettings] by it name.
///
/// Value can be returned in int, double or string representation.
class Setting {
final String _name;
final double _factor;
final dynamic Function(Failure err)? _onError;
///
/// Holds setting value stored in [AppSettings] by it [name].
///
/// Value can be returned in int, double or string representation.
/// [int] and [double] values are multiplied by [factor] before returning.
///
/// - [name] - the name of value stored in AppSettings
/// - [factor] - returned value int or double will by multiplied by factor
/// Calls [onError] if getting value from [AppSettings] will fail.
const Setting(
String name, {
double factor = 1.0,
}) :
_name = name,
_factor = factor;
dynamic Function(Failure err)? onError,
}) : _name = name,
_factor = factor,
_onError = onError;
///
///
/// Returns [Setting] new instance containing a [value]
const factory Setting.from(dynamic value) = _SettingValue;
///
/// Returns setting value in int represantation
///
/// Returns setting value in [int] representation
int get toInt {
final value = AppSettings.getSetting(_name);
final value = AppSettings.getSetting(_name, onError: _onError);
if (value is int) {
return _factor == 1 ? value : (value * _factor).toInt();
}
return (double.parse('$value') * _factor).toInt();
}
///
/// Returns setting value in double represantation
///
/// Returns setting value in [double] representation
double get toDouble {
final value = AppSettings.getSetting(_name);
final value = AppSettings.getSetting(_name, onError: _onError);
if (value is double) {
return value * _factor;
}
return double.parse('$value') * _factor;
}
///
/// Returns setting value in string represantation
///
/// Updates app setting to new [value] and save it asynchronously to file.
///
/// Calls [onSuccess] or [onError] when setting will be updated
/// and saved successfully or with error.
Future<void> update(
dynamic value, {
void Function(Failure error)? onError,
void Function()? onSuccess,
}) async {
await AppSettings.setSetting(
_name,
value,
onError: onError,
onSuccess: onSuccess,
);
}
///
/// Returns setting value in [String] representation
@override
String toString() => '${AppSettings.getSetting(_name)}';
String toString() => '${AppSettings.getSetting(_name, onError: _onError)}';
}


///
///
class _SettingValue implements Setting {
final dynamic _value;
//
Expand All @@ -55,6 +79,9 @@ class _SettingValue implements Setting {
String get _name => throw UnimplementedError();
//
@override
dynamic Function(Failure err)? get _onError => throw UnimplementedError();
//
@override
double get toDouble {
final value = _value;
if (value is double) {
Expand All @@ -73,5 +100,14 @@ class _SettingValue implements Setting {
}
//
@override
Future<void> update(
dynamic value, {
void Function(Failure error)? onError,
void Function()? onSuccess,
}) async {
onError?.call(Failure('$runtimeType.update | Cannot update setting created during app runtime'));
}
//
@override
String toString() => '$_value';
}
}
18 changes: 0 additions & 18 deletions lib/src/core/entities/alarm_colors.dart

This file was deleted.

5 changes: 2 additions & 3 deletions lib/src/core/entities/ds_data_class.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import 'package:hmi_core/src/core/error/failure.dart';

///
Expand Down Expand Up @@ -33,9 +33,8 @@
factory DsDataClass.fromString(String value) {
final dataClass = _valueMapping[value];
if (dataClass == null) {
throw Failure.connection(
message: 'Ошибка в методе $DsDataClass.fromString: неизвестный класс комманды "$value"',
stackTrace: StackTrace.current,
throw Failure(
'Ошибка в методе $DsDataClass.fromString: неизвестный класс комманды "$value"',
);
}
return dataClass;
Expand Down
6 changes: 1 addition & 5 deletions lib/src/core/entities/ds_data_point.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import 'dart:convert';
import 'package:hmi_core/src/core/entities/ds_cot.dart';
import 'package:hmi_core/src/core/entities/ds_data_type.dart';
Expand Down Expand Up @@ -76,11 +76,7 @@
DsCot.reqCon ||
DsCot.actCon => Ok(this),
DsCot.reqErr || DsCot.actErr => Err(
Failure(
message: value,
stackTrace:
StackTrace.current,
),
Failure(value),
)
};
}
5 changes: 2 additions & 3 deletions lib/src/core/entities/ds_data_type.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import 'package:hmi_core/src/core/error/failure.dart';

enum DsDataType {
Expand Down Expand Up @@ -41,9 +41,8 @@
final lvalue = value.toLowerCase();
final dataType = _valueMapping[lvalue];
if (dataType == null) {
throw Failure.connection(
message: 'Ошибка в методе $DsDataType._extract: неизвестный тип данных $value',
stackTrace: StackTrace.current,
throw Failure(
'Ошибка в методе $DsDataType._extract: неизвестный тип данных $value',
);
}
return dataType;
Expand Down
Loading
Loading