初始化提交
This commit is contained in:
Executable
+32
@@ -0,0 +1,32 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BottomSheetPage extends Page {
|
||||
const BottomSheetPage({
|
||||
super.key,
|
||||
super.name,
|
||||
required this.builder,
|
||||
this.fixed = false,
|
||||
});
|
||||
|
||||
final Widget Function(ScrollController? controller) builder;
|
||||
final bool fixed;
|
||||
|
||||
@override
|
||||
Route<void> createRoute(BuildContext context) {
|
||||
return ModalBottomSheetRoute(
|
||||
settings: this,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
showDragHandle: true,
|
||||
builder: (_) {
|
||||
if (!fixed) {
|
||||
return DraggableScrollableSheet(
|
||||
expand: false,
|
||||
builder: (_, scrollController) => builder(scrollController),
|
||||
);
|
||||
}
|
||||
return builder(null);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class CallbackDebouncer {
|
||||
CallbackDebouncer(this._delay);
|
||||
|
||||
final Duration _delay;
|
||||
Timer? _timer;
|
||||
|
||||
/// Calls the given [callback] after the given duration has passed.
|
||||
void call(VoidCallback callback) {
|
||||
if (_delay == Duration.zero) {
|
||||
callback();
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
_timer = Timer(_delay, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/// Stops any running timers and disposes this instance.
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
}
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
import 'package:loggy/loggy.dart';
|
||||
|
||||
/// application layer logger
|
||||
///
|
||||
/// used in notifiers and controllers
|
||||
mixin AppLogger implements LoggyType {
|
||||
@override
|
||||
Loggy<AppLogger> get loggy => Loggy<AppLogger>('$runtimeType');
|
||||
}
|
||||
|
||||
/// presentation layer logger
|
||||
///
|
||||
/// used in widgets and ui
|
||||
mixin PresLogger implements LoggyType {
|
||||
@override
|
||||
Loggy<PresLogger> get loggy => Loggy<PresLogger>('$runtimeType');
|
||||
}
|
||||
|
||||
/// data layer logger
|
||||
///
|
||||
/// used in Repositories, DAOs, Services
|
||||
mixin InfraLogger implements LoggyType {
|
||||
@override
|
||||
Loggy<InfraLogger> get loggy => Loggy<InfraLogger>('$runtimeType');
|
||||
}
|
||||
|
||||
abstract class LoggerMixin {
|
||||
LoggerMixin(this.loggy);
|
||||
|
||||
final Loggy loggy;
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
// import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
// import 'package:kaer_with_panels/core/model/failures.dart';
|
||||
|
||||
// part 'mutation_state.freezed.dart';
|
||||
|
||||
// // TODO: remove
|
||||
// @freezed
|
||||
// class MutationState<F extends Failure> with _$MutationState<F> {
|
||||
// const MutationState._();
|
||||
|
||||
// const factory MutationState.initial() = MutationInitial<F>;
|
||||
// const factory MutationState.inProgress() = MutationInProgress<F>;
|
||||
// const factory MutationState.failure(Failure failure) = MutationFailure<F>;
|
||||
// const factory MutationState.success() = MutationSuccess<F>;
|
||||
|
||||
// bool get isInProgress => this is MutationInProgress;
|
||||
// }
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
abstract class PlatformUtils {
|
||||
static bool get isDesktop =>
|
||||
Platform.isLinux || Platform.isWindows || Platform.isMacOS;
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
extension RefLifeCycle<T> on AutoDisposeRef<T> {
|
||||
void disposeDelay(Duration duration) {
|
||||
final link = keepAlive();
|
||||
Timer? timer;
|
||||
|
||||
onCancel(() {
|
||||
timer?.cancel();
|
||||
timer = Timer(duration, link.close);
|
||||
});
|
||||
|
||||
onDispose(() {
|
||||
timer?.cancel();
|
||||
});
|
||||
|
||||
onResume(() {
|
||||
timer?.cancel();
|
||||
});
|
||||
}
|
||||
}
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
|
||||
export 'bottom_sheet_page.dart';
|
||||
export 'callback_debouncer.dart';
|
||||
export 'custom_loggers.dart';
|
||||
|
||||
export 'mutation_state.dart';
|
||||
|
||||
export 'platform_utils.dart';
|
||||
|
||||
export 'validators.dart';
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
/// https://gist.github.com/dperini/729294
|
||||
final _urlRegex = RegExp(
|
||||
// r"^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$",
|
||||
r'^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3}|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?#?.*$',
|
||||
);
|
||||
|
||||
/// https://stackoverflow.com/a/12968117
|
||||
final _portRegex = RegExp(
|
||||
r"^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
|
||||
);
|
||||
|
||||
/// https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url/3809435#3809435
|
||||
bool isUrl(String input) {
|
||||
return _urlRegex.hasMatch(input.trim().toLowerCase());
|
||||
}
|
||||
|
||||
bool isPort(String input) {
|
||||
return _portRegex.hasMatch(input);
|
||||
}
|
||||
Reference in New Issue
Block a user