go router added
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
typedef OnError<E> = void Function(E error);
|
||||
|
||||
abstract class Either<E, S> {
|
||||
const Either();
|
||||
|
||||
E? getError();
|
||||
|
||||
S? getSuccess();
|
||||
|
||||
bool isError();
|
||||
|
||||
bool isSuccess();
|
||||
|
||||
void when({
|
||||
required OnError<E> error,
|
||||
required void Function(S success) success,
|
||||
});
|
||||
}
|
||||
|
||||
class Success<E, S> extends Either<E, S> {
|
||||
final S _success;
|
||||
|
||||
const Success(this._success);
|
||||
|
||||
@override
|
||||
E? getError() => null;
|
||||
|
||||
@override
|
||||
S? getSuccess() => _success;
|
||||
|
||||
@override
|
||||
bool isError() => false;
|
||||
|
||||
@override
|
||||
bool isSuccess() => true;
|
||||
|
||||
@override
|
||||
void when({
|
||||
required OnError<E> error,
|
||||
required void Function(S success) success,
|
||||
}) {
|
||||
success(_success);
|
||||
}
|
||||
}
|
||||
|
||||
class Error<E, S> extends Either<E, S> {
|
||||
final E _error;
|
||||
|
||||
const Error(this._error);
|
||||
|
||||
@override
|
||||
E? getError() => _error;
|
||||
|
||||
@override
|
||||
S? getSuccess() => null;
|
||||
|
||||
@override
|
||||
bool isError() => true;
|
||||
|
||||
@override
|
||||
bool isSuccess() => false;
|
||||
|
||||
@override
|
||||
void when({
|
||||
required OnError<E> error,
|
||||
required void Function(S success) success,
|
||||
}) {
|
||||
error(_error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
|
||||
/// AppLogger is a singleton class that provides centralized logging functionality
|
||||
/// throughout the application using the logger package.
|
||||
class AppLogger {
|
||||
// Private constructor
|
||||
AppLogger._internal();
|
||||
|
||||
// Singleton instance
|
||||
static final AppLogger _instance = AppLogger._internal();
|
||||
|
||||
// Factory constructor to return the singleton instance
|
||||
factory AppLogger() => _instance;
|
||||
|
||||
// Logger instance
|
||||
late final Logger _logger;
|
||||
|
||||
// Initialize the logger with custom configuration
|
||||
void init({Level? logLevel, bool? stackTraceEnabled}) {
|
||||
_logger = Logger(
|
||||
level: logLevel ?? (kDebugMode ? Level.debug : Level.info),
|
||||
printer: PrettyPrinter(
|
||||
methodCount: stackTraceEnabled ?? false ? 2 : 0,
|
||||
errorMethodCount: 8,
|
||||
lineLength: 120,
|
||||
colors: true,
|
||||
printEmojis: true,
|
||||
dateTimeFormat: DateTimeFormat.onlyTimeAndSinceStart,
|
||||
),
|
||||
output: _CustomConsoleOutput(),
|
||||
filter: _CustomLogFilter(),
|
||||
);
|
||||
}
|
||||
|
||||
// Get the logger instance (for advanced usage)
|
||||
Logger get logger => _logger;
|
||||
|
||||
// Convenient logging methods
|
||||
void debug(dynamic message, {dynamic error, StackTrace? stackTrace}) {
|
||||
_logger.d(message, error: error, stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
void info(dynamic message, {dynamic error, StackTrace? stackTrace}) {
|
||||
_logger.i(message, error: error, stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
void warning(dynamic message, {dynamic error, StackTrace? stackTrace}) {
|
||||
_logger.w(message, error: error, stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
void error(dynamic message, {dynamic error, StackTrace? stackTrace}) {
|
||||
_logger.e(message, error: error, stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
void fatal(dynamic message, {dynamic error, StackTrace? stackTrace}) {
|
||||
_logger.f(message, error: error, stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
// Network logging
|
||||
void logNetwork({
|
||||
required String method,
|
||||
required String url,
|
||||
int? statusCode,
|
||||
dynamic requestBody,
|
||||
dynamic responseBody,
|
||||
dynamic error,
|
||||
}) {
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln('🌐 Network Request:');
|
||||
buffer.writeln(' Method: $method');
|
||||
buffer.writeln(' URL: $url');
|
||||
|
||||
if (statusCode != null) {
|
||||
buffer.writeln(' Status: $statusCode');
|
||||
}
|
||||
|
||||
if (requestBody != null) {
|
||||
buffer.writeln(' Request Body: $requestBody');
|
||||
}
|
||||
|
||||
if (responseBody != null) {
|
||||
buffer.writeln(' Response: $responseBody');
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
buffer.writeln(' Error: $error');
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
_logger.e(buffer.toString());
|
||||
} else if (statusCode != null && statusCode >= 400) {
|
||||
_logger.w(buffer.toString());
|
||||
} else {
|
||||
_logger.i(buffer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Performance logging
|
||||
void logPerformance(String operation, Duration duration) {
|
||||
final milliseconds = duration.inMilliseconds;
|
||||
final message = '⏱️ Performance: $operation took ${milliseconds}ms';
|
||||
|
||||
if (milliseconds > 1000) {
|
||||
_logger.w(message);
|
||||
} else {
|
||||
_logger.d(message);
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation logging
|
||||
void logNavigation(String from, String to) {
|
||||
_logger.i('🧭 Navigation: $from → $to');
|
||||
}
|
||||
|
||||
// Custom log with tag
|
||||
void logWithTag(String tag, dynamic message, {Level? level}) {
|
||||
final taggedMessage = '[$tag] $message';
|
||||
|
||||
switch (level ?? Level.info) {
|
||||
case Level.debug:
|
||||
debug(taggedMessage);
|
||||
break;
|
||||
case Level.info:
|
||||
info(taggedMessage);
|
||||
break;
|
||||
case Level.warning:
|
||||
warning(taggedMessage);
|
||||
break;
|
||||
case Level.error:
|
||||
error(taggedMessage);
|
||||
break;
|
||||
case Level.fatal:
|
||||
fatal(taggedMessage);
|
||||
break;
|
||||
default:
|
||||
info(taggedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the logger (call this in app disposal if needed)
|
||||
void close() {
|
||||
_logger.close();
|
||||
}
|
||||
}
|
||||
|
||||
/// Custom log filter to control which logs are shown
|
||||
class _CustomLogFilter extends LogFilter {
|
||||
@override
|
||||
bool shouldLog(LogEvent event) {
|
||||
// In debug mode, show all logs
|
||||
if (kDebugMode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// In release mode, only show warnings and above
|
||||
return event.level.value >= Level.warning.value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Custom console output for better control over log output
|
||||
class _CustomConsoleOutput extends ConsoleOutput {
|
||||
@override
|
||||
void output(OutputEvent event) {
|
||||
// You can customize how logs are output here
|
||||
// For example, you could write to a file in addition to console
|
||||
super.output(event);
|
||||
|
||||
// Example: Write errors to a file (uncomment if needed)
|
||||
// if (event.level == Level.error || event.level == Level.fatal) {
|
||||
// _writeToFile(event.lines.join('\n'));
|
||||
// }
|
||||
}
|
||||
|
||||
// Example method for writing to file (implement if needed)
|
||||
// Future<void> _writeToFile(String log) async {
|
||||
// // Implementation for file writing
|
||||
// }
|
||||
}
|
||||
|
||||
// Global logger instance for easy access
|
||||
final appLogger = AppLogger();
|
||||
|
||||
// Extension for convenient logging on any object
|
||||
extension LoggerExtension on Object {
|
||||
void logDebug([String? message]) {
|
||||
appLogger.debug(message ?? toString());
|
||||
}
|
||||
|
||||
void logInfo([String? message]) {
|
||||
appLogger.info(message ?? toString());
|
||||
}
|
||||
|
||||
void logWarning([String? message]) {
|
||||
appLogger.warning(message ?? toString());
|
||||
}
|
||||
|
||||
void logError([String? message, dynamic error, StackTrace? stackTrace]) {
|
||||
appLogger.error(
|
||||
message ?? toString(),
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user