initial commit (migrated)

This commit is contained in:
fiatcode 2025-10-20 16:43:59 +07:00
commit b594facb51
143 changed files with 11057 additions and 0 deletions

View file

@ -0,0 +1,21 @@
// ignore_for_file: public_member_api_docs, strict_raw_type
import 'dart:developer' as dev;
import 'package:flutter_bloc/flutter_bloc.dart';
class AppBlocObserver extends BlocObserver {
@override
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
dev.log("[bloc_error] $bloc\nerror: $error\nstacktrace: $stackTrace");
super.onError(bloc, error, stackTrace);
}
@override
void onChange(BlocBase bloc, Change change) {
dev.log(
"[${bloc.runtimeType}] ${DateTime.now().toIso8601String()}\nFrom: ${change.currentState}\nNext: ${change.nextState}",
);
super.onChange(bloc, change);
}
}

View file

@ -0,0 +1,24 @@
import 'package:kuwot/core/data/local/config.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
/// Theme mode cubit for theme mode management
class ThemeModeCubit extends Cubit<ThemeMode> {
/// Default [ThemeMode] is [ThemeMode.system]
ThemeModeCubit({
required this.themeModeConfig,
required this.initialThemeMode,
}) : super(initialThemeMode);
/// Theme mode config
final Config<ThemeMode> themeModeConfig;
/// Initial theme mode
final ThemeMode initialThemeMode;
/// Set theme mode
void setThemeMode(ThemeMode themeMode) {
themeModeConfig.set(themeMode);
emit(themeMode);
}
}

View file

@ -0,0 +1,18 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:kuwot/core/data/local/config.dart';
import 'package:kuwot/core/data/local/translation_target_config.dart';
class TranslationTargetCubit extends Cubit<TranslationTarget> {
TranslationTargetCubit({
required this.translationTargetConfig,
required this.initialTranslationTarget,
}) : super(initialTranslationTarget);
final Config<TranslationTarget> translationTargetConfig;
final TranslationTarget initialTranslationTarget;
void set(TranslationTarget translationTarget) {
translationTargetConfig.set(translationTarget);
emit(translationTarget);
}
}

View file

@ -0,0 +1,6 @@
abstract class ErrorState {
final String message;
final Exception? cause;
const ErrorState({required this.message, this.cause});
}

View file

@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
class ErrorRetrySnackbar {
final BuildContext context;
final String errorMessage;
final VoidCallback onRetry;
const ErrorRetrySnackbar(
this.context, {
required this.errorMessage,
required this.onRetry,
});
SnackBar _build() {
return SnackBar(
behavior: SnackBarBehavior.floating,
duration: const Duration(days: 1),
backgroundColor: Colors.red[600],
content: Text(errorMessage),
action: SnackBarAction(
textColor: Colors.white,
label: 'RETRY',
onPressed: () {
onRetry();
ScaffoldMessenger.of(context).hideCurrentSnackBar();
},
),
);
}
static void show(
BuildContext context, {
required String errorMessage,
required VoidCallback onRetry,
}) {
ScaffoldMessenger.of(context).showSnackBar(
ErrorRetrySnackbar(
context,
errorMessage: errorMessage,
onRetry: onRetry,
)._build(),
);
}
}

View file

@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
/// App light theme
ThemeData lightTheme = ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF343A40)),
useMaterial3: true,
fontFamily: GoogleFonts.dmSans().fontFamily,
);
/// App dark theme
ThemeData darkTheme = ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF212529),
brightness: Brightness.dark,
),
useMaterial3: true,
fontFamily: GoogleFonts.dmSans().fontFamily,
);