initial commit
This commit is contained in:
32
lib/app.dart
Normal file
32
lib/app.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
3
lib/core/app/app_manager.dart
Normal file
3
lib/core/app/app_manager.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppManager extends ChangeNotifier {}
|
||||
5
lib/core/config/config.dart
Normal file
5
lib/core/config/config.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
class Config {
|
||||
|
||||
Config._();
|
||||
|
||||
}
|
||||
28
lib/features/home/home_screen.dart
Normal file
28
lib/features/home/home_screen.dart
Normal 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
20
lib/main.dart
Normal 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() );
|
||||
}
|
||||
7
lib/router/route_list.dart
Normal file
7
lib/router/route_list.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
class RouteList {
|
||||
|
||||
RouteList._();
|
||||
|
||||
static const String homeScreen = '/homeScreen';
|
||||
|
||||
}
|
||||
18
lib/router/router.dart
Normal file
18
lib/router/router.dart
Normal 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()
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
7
lib/storage/storage_keys.dart
Normal file
7
lib/storage/storage_keys.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
class StorageKeys {
|
||||
|
||||
StorageKeys._();
|
||||
|
||||
static const String theme = 'theme';
|
||||
|
||||
}
|
||||
54
lib/storage/storage_service.dart
Normal file
54
lib/storage/storage_service.dart
Normal 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
34
lib/theme/theme_data.dart
Normal 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
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
100
lib/theme/theme_manager.dart
Normal file
100
lib/theme/theme_manager.dart
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
39
lib/theme/theme_schema.dart
Normal file
39
lib/theme/theme_schema.dart
Normal 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,
|
||||
});
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user