初始化提交

This commit is contained in:
2025-09-23 16:23:15 +08:00
commit 877b18a70f
590 changed files with 53617 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
import 'dart:io';
typedef Directories = ({
Directory baseDir,
Directory workingDir,
Directory tempDir
});
+73
View File
@@ -0,0 +1,73 @@
// import 'package:dio/dio.dart';
// import 'package:kaer_with_panels/app/localization/translations.g.dart';
// typedef PresentableError = ({String type, String? message});
// mixin Failure {
// ({String type, String? message}) present(TranslationsEn t);
// }
// /// failures that are not expected to happen but depending on [error] type might not be relevant (eg network errors)
// mixin UnexpectedFailure {
// Object? get error;
// StackTrace? get stackTrace;
// }
// /// failures that are expected to happen and should be handled by the app
// /// and should be logged, eg missing permissions
// mixin ExpectedMeasuredFailure {}
// /// failures ignored by analytics service etc.
// mixin ExpectedFailure {}
// extension ErrorPresenter on TranslationsEn {
// PresentableError errorToPair(Object error) => switch (error) {
// UnexpectedFailure(error: final nestedErr?) => errorToPair(nestedErr),
// Failure() => error.present(this),
// DioException() => error.present(this),
// _ => (type: failure.unexpected, message: error.toString()),
// };
// PresentableError presentError(
// Object error, {
// String? action,
// }) {
// final pair = errorToPair(error);
// if (action == null) return pair;
// return (
// type: action,
// message: pair.type + (pair.message == null ? "" : "\n${pair.message!}"),
// );
// }
// String presentShortError(
// Object error, {
// String? action,
// }) {
// final pair = errorToPair(error);
// if (action == null) return pair.type;
// return "$action: ${pair.type}";
// }
// }
// extension DioExceptionPresenter on DioException {
// PresentableError present(TranslationsEn t) => switch (type) {
// DioExceptionType.connectionTimeout ||
// DioExceptionType.sendTimeout ||
// DioExceptionType.receiveTimeout =>
// (type: t.failure.connection.timeout, message: null),
// DioExceptionType.badCertificate => (
// type: t.failure.connection.badCertificate,
// message: message,
// ),
// DioExceptionType.badResponse => (
// type: t.failure.connection.badResponse,
// message: message,
// ),
// DioExceptionType.connectionError => (
// type: t.failure.connection.connectionError,
// message: message,
// ),
// _ => (type: t.failure.connection.unexpected, message: message),
// };
// }
+56
View File
@@ -0,0 +1,56 @@
import 'package:dart_mappable/dart_mappable.dart';
import 'package:dartx/dartx.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
// import 'package:kaer_with_panels/core/localization/translations.dart';
part 'optional_range.mapper.dart';
@MappableClass()
class OptionalRange with OptionalRangeMappable {
const OptionalRange({this.min, this.max});
final int? min;
final int? max;
String format() => [min, max].whereNotNull().join("-");
// String present(TranslationsEn t) =>
// format().isEmpty ? t.general.notSet : format();
factory OptionalRange.parse(
String input, {
bool allowEmpty = false,
}) =>
switch (input.split("-")) {
[final String val] when val.isEmpty && allowEmpty =>
const OptionalRange(),
[final String min] => OptionalRange(min: int.parse(min)),
[final String min, final String max] => OptionalRange(
min: int.parse(min),
max: int.parse(max),
),
_ => throw Exception("Invalid range: $input"),
};
static OptionalRange? tryParse(
String input, {
bool allowEmpty = false,
}) {
try {
return OptionalRange.parse(input, allowEmpty: allowEmpty);
} catch (_) {
return null;
}
}
}
class OptionalRangeJsonConverter
implements JsonConverter<OptionalRange, String> {
const OptionalRangeJsonConverter();
@override
OptionalRange fromJson(String json) =>
OptionalRange.parse(json, allowEmpty: true);
@override
String toJson(OptionalRange object) => object.format();
}