initial commit

This commit is contained in:
2025-11-28 23:58:41 +03:00
commit 013690061c
77 changed files with 2337 additions and 0 deletions

32
lib/app.dart Normal file
View File

@@ -0,0 +1,32 @@
import 'package:base_project/core/app/app_manager.dart';
import 'package:base_project/router/router.dart';
import 'package:base_project/theme/theme_manager.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class App extends StatelessWidget {
const App._();
static Widget create() {
return MultiProvider(
providers: [
ListenableProvider(create: ( context ) => ThemeManager(), lazy: false )
],
child: ChangeNotifierProvider(
create: ( context ) => AppManager(),
child: const App._(),
),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Base Project',
debugShowCheckedModeBanner: false,
routerConfig: AppRouter.router,
);
}
}

View File

@@ -0,0 +1,3 @@
import 'package:flutter/material.dart';
class AppManager extends ChangeNotifier {}

View File

@@ -0,0 +1,5 @@
class Config {
Config._();
}

View File

@@ -0,0 +1,28 @@
import 'package:base_project/theme/theme_manager.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
final theme = ThemeManager.getTheme(context);
return Scaffold(
appBar: AppBar(
title: const Text('Home Screen'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
}
),
body: const Center(
child: Text('Hello World!'),
),
);
}
}

20
lib/main.dart Normal file
View File

@@ -0,0 +1,20 @@
import 'package:base_project/app.dart';
import 'package:base_project/storage/storage_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await StorageService.init();
// Фиксируем ориентацию приложения
await SystemChrome.setPreferredOrientations(
[
DeviceOrientation.portraitUp
]
);
runApp( App.create() );
}

View File

@@ -0,0 +1,7 @@
class RouteList {
RouteList._();
static const String homeScreen = '/homeScreen';
}

18
lib/router/router.dart Normal file
View File

@@ -0,0 +1,18 @@
import 'package:base_project/features/home/home_screen.dart';
import 'package:base_project/router/route_list.dart';
import 'package:go_router/go_router.dart';
class AppRouter {
static final router = GoRouter(
initialLocation: RouteList.homeScreen,
routes: [
GoRoute(
path: RouteList.homeScreen,
name: RouteList.homeScreen,
builder: ( context, state ) => const HomeScreen()
)
]
);
}

View File

@@ -0,0 +1,7 @@
class StorageKeys {
StorageKeys._();
static const String theme = 'theme';
}

View File

@@ -0,0 +1,54 @@
import 'package:shared_preferences/shared_preferences.dart';
enum StorageServiceValueType {
string,
stringList,
boolean,
}
class StorageService {
StorageService._();
static late SharedPreferences _preferences;
static Future<void> init() async {
_preferences = await SharedPreferences.getInstance();
}
static T? getValue<T>( StorageServiceValueType valueType, String key ){
Map<StorageServiceValueType, Function( String key ) > data = {
StorageServiceValueType.string: _preferences.getString,
StorageServiceValueType.stringList: _preferences.getStringList,
StorageServiceValueType.boolean: _preferences.getBool,
};
final Function( String key )? function = data[valueType];
if( function == null ) throw Exception('Unimplemented value type');
return function(key) as T?;
}
static Future<bool> setValue( StorageServiceValueType valueType, String key, dynamic value ) async {
switch( valueType ) {
case .string:
return _preferences.setString(key, value);
case.stringList:
return _preferences.setStringList(key, value);
case .boolean:
return _preferences.setBool(key, value);
}
throw Exception('Unimplemented value type');
}
static Future<bool> removeValue( String key ) async {
return await _preferences.remove(key);
}
}

34
lib/theme/theme_data.dart Normal file
View File

@@ -0,0 +1,34 @@
import 'package:base_project/theme/theme_schema.dart';
import 'package:flutter/material.dart';
class LightTheme extends ThemeSchema {
LightTheme() : super(
brightness: Brightness.light,
textTheme: TextThemeSchema(
title: const TextStyle(),
body: const TextStyle()
),
colorTheme: ColorThemeSchema(
primary: Colors.black,
secondary: Colors.white
)
);
}
class DarkTheme extends ThemeSchema {
DarkTheme() : super(
brightness: Brightness.dark,
textTheme: TextThemeSchema(
title: const TextStyle(),
body: const TextStyle()
),
colorTheme: ColorThemeSchema(
primary: Colors.white,
secondary: Colors.black
)
);
}

View File

@@ -0,0 +1,100 @@
import 'dart:ui';
import 'package:base_project/storage/storage_keys.dart';
import 'package:base_project/storage/storage_service.dart';
import 'package:base_project/theme/theme_data.dart';
import 'package:base_project/theme/theme_schema.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
class ThemeManager extends ChangeNotifier {
late ThemeSchema theme;
late ThemeMode themeMode;
PlatformDispatcher dispatcher = SchedulerBinding.instance.platformDispatcher;
ThemeManager(){
init();
}
void init(){
themeMode = ThemeModeUtils.fromString(
StorageService.getValue( StorageServiceValueType.string, StorageKeys.theme) ?? ThemeMode.system.toRawString()
);
dispatcher.onPlatformBrightnessChanged = _onBrightnessChanged;
_setCurrentTheme();
}
void changeThemeMode( ThemeMode themeMode ){
StorageService.setValue(StorageServiceValueType.string, StorageKeys.theme, themeMode.toRawString());
this.themeMode = themeMode;
_setCurrentTheme();
notifyListeners();
}
void _onBrightnessChanged (){
if( themeMode != ThemeMode.system ) return;
if( dispatcher.platformBrightness == Brightness.light ){
theme = LightTheme();
}else{
theme = DarkTheme();
}
notifyListeners();
}
void _setCurrentTheme(){
if( themeMode == ThemeMode.system ){
theme = dispatcher.platformBrightness == Brightness.light ? LightTheme() : DarkTheme();
}else {
theme = themeMode == ThemeMode.light ? LightTheme() : DarkTheme();
}
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: theme.brightness == Brightness.light ? Brightness.dark : Brightness.light
)
);
}
static ThemeSchema getTheme( BuildContext context, { bool listen = true } ){
return listen ? context.watch<ThemeManager>().theme : context.read<ThemeManager>().theme;
}
}
class ThemeModeUtils {
ThemeModeUtils._();
static ThemeMode fromString( String themeModeString ){
Map<String, ThemeMode> data = {
'light': ThemeMode.light,
'dark': ThemeMode.dark,
'system': ThemeMode.system
};
return data[themeModeString]!;
}
}
extension ThemeModeExtention on ThemeMode {
String toRawString(){
return toString().split('.').last;
}
}

View File

@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
class ThemeSchema {
Brightness brightness;
TextThemeSchema textTheme;
ColorThemeSchema colorTheme;
ThemeSchema({
required this.brightness,
required this.textTheme,
required this.colorTheme,
});
}
class TextThemeSchema {
TextStyle title;
TextStyle body;
TextThemeSchema({
required this.title,
required this.body,
});
}
class ColorThemeSchema {
Color primary;
Color secondary;
ColorThemeSchema({
required this.primary,
required this.secondary,
});
}