Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions lib/app/bindings/initial_binding.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:get/get.dart';

import 'local_source_bindings.dart';
import 'remote_source_bindings.dart';
import 'repository_bindings.dart';

Expand All @@ -9,6 +8,5 @@ class InitialBinding implements Bindings {
void dependencies() {
RepositoryBindings().dependencies();
RemoteSourceBindings().dependencies();
LocalSourceBindings().dependencies();
}
}
7 changes: 4 additions & 3 deletions lib/app/core/base/base_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'package:logger/logger.dart';

import '/app/core/base/base_controller.dart';
import '/app/core/model/page_state.dart';
import '/app/core/values/app_colors.dart';
import '/app/core/widget/loading.dart';
import '/flavors/build_config.dart';

Expand All @@ -19,6 +18,8 @@ abstract class BaseView<Controller extends BaseController>

final Logger logger = BuildConfig.instance.config.logger;

ThemeData get appTheme => Theme.of(Get.context!);

Widget body(BuildContext context);

PreferredSizeWidget? appBar(BuildContext context);
Expand Down Expand Up @@ -92,11 +93,11 @@ abstract class BaseView<Controller extends BaseController>
}

Color pageBackgroundColor() {
return AppColors.pageBackground;
return appTheme.canvasColor;
}

Color statusBarColor() {
return AppColors.pageBackground;
return appTheme.canvasColor;
}

Widget? floatingActionButton() {
Expand Down
4 changes: 4 additions & 0 deletions lib/app/core/base/base_widget_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import 'package:logger/logger.dart';
import '/flavors/build_config.dart';

mixin BaseWidgetMixin on StatelessWidget {

AppLocalizations get appLocalization => AppLocalizations.of(Get.context!)!;

ThemeData get appTheme => Theme.of(Get.context!);

final Logger logger = BuildConfig.instance.config.logger;

@override
Expand Down
4 changes: 4 additions & 0 deletions lib/app/core/values/app_colors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ abstract class AppColors {
static const Color errorColor = Color(0xFFAB0B0B);
static const Color colorDark = Color(0xFF323232);

// Dark theme colors
static const Color canvasColor = Color(0xFFFAFAFA);
static const Color canvasColorDark = Color(0xFF212121);

static const Color buttonBgColor = colorPrimary;
static const Color disabledButtonBgColor = Color(0xFFBFBFC0);
static const Color defaultRippleColor = Color(0x0338686A);
Expand Down
45 changes: 45 additions & 0 deletions lib/app/core/values/app_themes.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';

import 'app_colors.dart';

class AppThemes {
// light theme configurations

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our code should be self explanatory. don't need to add unnecessary comment.

static ThemeData get lightTheme {
return ThemeData(
primarySwatch: AppColors.colorPrimarySwatch,
visualDensity: VisualDensity.adaptivePlatformDensity,
brightness: Brightness.light,
primaryColor: AppColors.colorPrimary,
canvasColor: AppColors.canvasColor,
cardColor: AppColors.canvasColor,
textTheme: const TextTheme(
button: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
fontFamily: 'Roboto',
);
}

// dark theme configurations

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our code should be self explanatory. don't need to add unnecessary comment.

static ThemeData get darkTheme {
return ThemeData(
primarySwatch: AppColors.colorPrimarySwatch,
visualDensity: VisualDensity.adaptivePlatformDensity,
brightness: Brightness.dark,
primaryColor: AppColors.colorPrimary,
canvasColor: AppColors.canvasColorDark,
cardColor: AppColors.canvasColorDark,
textTheme: const TextTheme(
button: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
fontFamily: 'Roboto',
);
}
}
10 changes: 6 additions & 4 deletions lib/app/modules/settings/controllers/settings_controller.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@

import 'package:flutter_getx_template/app/core/base/base_controller.dart';
import 'package:flutter_getx_template/app/modules/theme/theme_controller.dart';
import 'package:get/get.dart';
import '../../theme/theme_controller.dart';

import '/app/core/base/base_controller.dart';
class SettingsController extends BaseController{

class SettingsController extends BaseController {
final count = 0.obs;
ThemeController themeController = Get.find<ThemeController>();

void increment() => count.value++;
}
70 changes: 70 additions & 0 deletions lib/app/modules/settings/dialogs/theme_changing_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../../core/base/base_widget_mixin.dart';
import '../../theme/theme_controller.dart';
import '../controllers/settings_controller.dart';

// ignore: must_be_immutable
class ThemeChangingDialog extends StatelessWidget with BaseWidgetMixin {
final SettingsController controller;
final ThemeController _themeController;

ThemeChangingDialog({Key? key, required this.controller})
: _themeController = controller.themeController,
super(key: key);

ThemeMode? _selectedMode;

@override
Widget body(BuildContext context) {
return Obx(() {
_selectedMode = _themeController.currentThemeMode.value;

return _selectedMode == null ? _loadingWidget() : _bodyWidget(context);
});
}

Widget _loadingWidget() {
return Center(
child: CircularProgressIndicator(
color: appTheme.primaryColor,
),
);
}

Widget _bodyWidget(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
RadioListTile(
value: ThemeMode.light,
groupValue: _selectedMode,
onChanged: (_) {
_themeController.setLightThemeMode();
Navigator.pop(context);
},
title: Text(appLocalization.lightTheme),
),
RadioListTile(
value: ThemeMode.dark,
groupValue: _selectedMode,
onChanged: (_) {
_themeController.setDarkThemeMode();
Navigator.pop(context);
},
title: Text(appLocalization.darkTheme),
),
RadioListTile(
value: ThemeMode.system,
groupValue: _selectedMode,
onChanged: (_) {
_themeController.setSystemThemeMode();
Navigator.pop(context);
},
title: Text(appLocalization.systemDefault),
),
],
);
}
}
69 changes: 42 additions & 27 deletions lib/app/modules/settings/views/settings_view.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import '/app/modules/settings/widgets/item_settings_widgets.dart';
import 'package:flutter_getx_template/app/modules/settings/dialogs/theme_changing_dialog.dart';
import 'package:flutter_getx_template/app/modules/settings/widgets/item_settings_widgets.dart';
import '/app/core/base/base_view.dart';
import '/app/core/widget/custom_app_bar.dart';
import '/app/modules/settings/controllers/settings_controller.dart';

// ignore: must_be_immutable
class SettingsView extends BaseView<SettingsController> {
SettingsView() {
controller.themeController.getCurrentThemeMode();
}

@override
PreferredSizeWidget? appBar(BuildContext context) {
return CustomAppBar(
Expand All @@ -15,39 +21,48 @@ class SettingsView extends BaseView<SettingsController> {

@override
Widget body(BuildContext context) {
return Column(
children: [
ItemSettings(
title: appLocalization.settingsTheme,
prefixImage: 'ic_theme.png',
suffixImage: 'arrow_forward.svg',
onTap: _onThemeItemClicked,
),
_getHorizontalDivider(),
ItemSettings(
title: appLocalization.settingsLanguage,
prefixImage: 'ic_language.svg',
suffixImage: 'arrow_forward.svg',
onTap: _onLanguageItemClicked,
),
_getHorizontalDivider(),
ItemSettings(
title: appLocalization.settingsFontSize,
prefixImage: 'ic_font_size.svg',
suffixImage: 'arrow_forward.svg',
onTap: _onFontSizeItemClicked,
),
_getHorizontalDivider(),
],
return Scaffold(
body: Column(
children: [
ItemSettings(
title: appLocalization.settingsTheme,
prefixImage: 'ic_theme.png',
suffixImage: 'arrow_forward.svg',
onTap: ()=>_onThemeItemClicked(context),
),
_getHorizontalDivider(),
ItemSettings(
title: appLocalization.settingsLanguage,
prefixImage: 'ic_language.svg',
suffixImage: 'arrow_forward.svg',
onTap: _onLanguageItemClicked,
),
_getHorizontalDivider(),
ItemSettings(
title: appLocalization.settingsFontSize,
prefixImage: 'ic_font_size.svg',
suffixImage: 'arrow_forward.svg',
onTap: _onFontSizeItemClicked,
),
_getHorizontalDivider(),
],
),
);
}

Widget _getHorizontalDivider() {
return const Divider(height: 1);
}

void _onThemeItemClicked() {
showToast('Theme: Development in progress');
void _onThemeItemClicked(BuildContext context) {
showDialog(
context: context,
builder: (ctx){
return AlertDialog(
content: ThemeChangingDialog(controller: controller),
);
},
);
}

void _onLanguageItemClicked() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ItemSettings extends StatelessWidget with BaseWidgetMixin {
fileName: prefixImage,
height: AppValues.iconSize_20,
width: AppValues.iconSize_20,
color: appTheme.primaryColorDark,
),
const SizedBox(width: AppValues.smallPadding),
Text(title, style: settingsItemStyle),
Expand Down
33 changes: 33 additions & 0 deletions lib/app/modules/theme/theme_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../core/base/base_controller.dart';
import 'theme_service.dart';

class ThemeController extends BaseController {
final ThemeService themeService = ThemeService();
final Rx<ThemeMode> currentThemeMode = Rx<ThemeMode>(ThemeMode.system);

ThemeController() {
getCurrentThemeMode();
}

void getCurrentThemeMode() async {
currentThemeMode.value = await themeService.themeMode;
}

void setDarkThemeMode() async {
await themeService.setDarkMode();
getCurrentThemeMode();
}

void setLightThemeMode() async {
await themeService.setLightMode();
getCurrentThemeMode();
}

void setSystemThemeMode() async {
await themeService.setSystemMode();
getCurrentThemeMode();
}
}
44 changes: 44 additions & 0 deletions lib/app/modules/theme/theme_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../data/local/preference/preference_manager.dart';

const String DARK_THEME = "dark_theme";
const String LIGHT_THEME = "light_theme";
const String SYSTEM_THEME = "system_theme";

const Map<String, ThemeMode> themeModesMap = {
DARK_THEME: ThemeMode.dark,
LIGHT_THEME: ThemeMode.light,
SYSTEM_THEME: ThemeMode.system,
};

class ThemeService {
static const THEME_MODE_KEY = 'themeMode';

final PreferenceManager _preferenceManager =
Get.find(tag: (PreferenceManager).toString());

Future<ThemeMode> get themeMode async => await _loadThemeFromSharedPref();

Future<ThemeMode> _loadThemeFromSharedPref() async {
final String savedThemeMode =
await _preferenceManager.getString(THEME_MODE_KEY);

if (savedThemeMode.isEmpty) return ThemeMode.system;

return themeModesMap[savedThemeMode]!;
}

setDarkMode() async {
await _preferenceManager.setString(THEME_MODE_KEY, DARK_THEME);
}

setLightMode() async {
await _preferenceManager.setString(THEME_MODE_KEY, LIGHT_THEME);
}

setSystemMode() async {
await _preferenceManager.setString(THEME_MODE_KEY, SYSTEM_THEME);
}
}
Loading