Skip to content

Commit

Permalink
Fix the new Material 3 app theme
Browse files Browse the repository at this point in the history
+ Fix Flutter lint issues
  • Loading branch information
TechAurelian committed Apr 17, 2024
1 parent 3990a87 commit 29d071d
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 79 deletions.
4 changes: 2 additions & 2 deletions lib/common/app_strings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class AppStrings {
static const String drawerTitle = appName;
static const String settingsItemTitle = 'Settings';
static const String helpItemTitle = 'Online Help';
static const String rateItemTitle = 'Rate or review';
static const String viewSourceItemTitle = 'View app source';
static const String rateItemTitle = 'Rate App';
static const String viewSourceItemTitle = 'View Source Code';

static const Map<MenuAction, String> menuActions = {
MenuAction.reset: 'Reset counter',
Expand Down
21 changes: 12 additions & 9 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,32 @@ import 'package:flutter/material.dart';

import 'common/app_strings.dart';
import 'screens/home.dart';
import 'utils/utils.dart';

void main() {
runApp(const CountersApp());
}

/// The app widget.
class CountersApp extends StatelessWidget {
const CountersApp({Key? key}) : super(key: key);
const CountersApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: AppStrings.appName,
theme: ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.white.createMaterialColor(),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(foregroundColor: Colors.black),

// A black and white theme to go with the app's colored counters
theme: ThemeData.from(
colorScheme: ColorScheme.light(
primary: Colors.black,
surface: Colors.white,
onSurface: Colors.black,
surfaceTint: Colors.white,
primaryContainer: Colors.white,
onPrimaryContainer: Colors.black,
outlineVariant: Colors.grey.shade200,
),
visualDensity: VisualDensity.adaptivePlatformDensity,
typography: Typography.material2018(),
),
home: const HomeScreen(),
);
Expand Down
21 changes: 3 additions & 18 deletions lib/models/counter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.
// @author TechAurelian <[email protected]> (https://techaurelian.com)

// cSpell:ignore endregion

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'package:shared_preferences/shared_preferences.dart';
Expand All @@ -17,8 +14,6 @@ class Counter {
/// Creates a counter of the specified [type].
Counter(this.type);

//#region Counter value

/// The counter value.
int _value = 0;

Expand Down Expand Up @@ -46,12 +41,8 @@ class Counter {
_setValue(0);
}

//#endregion

//#region Persistent storage

/// Returns the persistent storage key for each counter type.
static String _counterKey(CounterType type) => '${describeEnum(type)}_counter';
static String _counterKey(CounterType type) => '${type.name}_counter';

/// Saves the counter value to persistent storage.
Future<void> _saveValue() async {
Expand All @@ -64,10 +55,6 @@ class Counter {
_value = preferences.getInt(_counterKey(type)) ?? 0;
}

//#endregion

//#region Counter type, color, name

/// The counter type.
final CounterType type;

Expand All @@ -82,8 +69,8 @@ class Counter {

/// Returns the name of the specified counter type (e.g. "Black Counter").
static String nameOf(CounterType type) {
final String name = describeEnum(type);
return '${name.substring(0, 1).toUpperCase()}${name.substring(1).toLowerCase()} Counter';
final String name = type.name;
return '${name[0].toUpperCase()}${name.substring(1).toLowerCase()} Counter';
}

/// A map with the corresponding [Color] value for each counter type.
Expand All @@ -100,8 +87,6 @@ class Counter {
CounterType.orange: Colors.orange,
CounterType.grey: Colors.grey,
};

//#endregion
}

/// Provides a map of counters for each counter type, and keeps a reference to the current counter.
Expand Down
2 changes: 1 addition & 1 deletion lib/screens/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum MenuAction { reset, share }

/// The app home screen widget.
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
const HomeScreen({super.key});

@override
State<HomeScreen> createState() => _HomeScreenState();
Expand Down
4 changes: 2 additions & 2 deletions lib/screens/settings_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import '../common/app_strings.dart';

class SettingsScreen extends StatefulWidget {
const SettingsScreen({
Key? key,
super.key,
required this.appSettings,
}) : super(key: key);
});

final AppSettings appSettings;

Expand Down
42 changes: 13 additions & 29 deletions lib/utils/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// @author TechAurelian <[email protected]> (https://techaurelian.com)

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:url_launcher/url_launcher.dart';

Expand All @@ -16,44 +17,27 @@ String toDecimalString(BuildContext context, int number) {
///
/// Shows an error [SnackBar] if there is no support for launching the URL.
Future<void> launchUrlExternal(BuildContext context, String url) async {
if (!await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication)) {
showSnackBar(context, 'Failed to open $url');
try {
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
} on PlatformException catch (e) {
if (!context.mounted) return;
showSnackBar(context, 'Failed to open $url: ${e.message}');
}
}

/// Shows a [SnackBar] with the specified [text] at the bottom of the specified scaffold.
void showSnackBar(BuildContext context, String text) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(text),
),
);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(text)));
}

/// Utility Color extension methods.
extension ColorX on Color {
/// Returns the contrast color for this color.
Color contrastOf() =>
ThemeData.estimateBrightnessForColor(this) == Brightness.light ? Colors.black : Colors.white;

/// Creates a material color from any ARGB color value.
MaterialColor createMaterialColor() {
List<double> strengths = <double>[.05];
Map<int, Color> swatch = <int, Color>{};
final int r = red, g = green, b = blue;

for (int i = 1; i < 10; i++) {
strengths.add(0.1 * i);
}
for (var strength in strengths) {
final double ds = 0.5 - strength;
swatch[(strength * 1000).round()] = Color.fromRGBO(
r + ((ds < 0 ? r : (255 - r)) * ds).round(),
g + ((ds < 0 ? g : (255 - g)) * ds).round(),
b + ((ds < 0 ? b : (255 - b)) * ds).round(),
1,
);
}
return MaterialColor(value, swatch);
Color contrastOf() {
return ThemeData.estimateBrightnessForColor(this) == Brightness.light
? Colors.black
: Colors.white;
}
}
15 changes: 5 additions & 10 deletions lib/widgets/color_list_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ class ColorListTile extends StatelessWidget {
///
/// The [color] and [title] parameters must not be null.
const ColorListTile({
Key? key,
super.key,
required this.color,
required this.title,
required this.subtitle,
this.selected = false,
this.onTap,
}) : super(key: key);
});

/// The ARGB color value to fill the circular color swatch.
final Color color;
Expand All @@ -43,10 +43,6 @@ class ColorListTile extends StatelessWidget {
color: color,
border: color == Colors.white ? Border.all() : null,
),
// title: Text(
// title,
// style: TextStyle(color: Theme.of(context).textTheme.bodyText1!.color),
// ),
title: Text(title),
subtitle: Text(subtitle),
onTap: onTap,
Expand All @@ -61,12 +57,11 @@ class _ColorFilledCircle extends StatelessWidget {
///
/// The [color] parameter must not be null.
const _ColorFilledCircle({
Key? key,
super.key, // ignore: unused_element
required this.color,
// ignore: unused_element
this.diameter = 40.0,
this.diameter = 40.0, // ignore: unused_element
this.border,
}) : super(key: key);
});

/// The color with which to fill the circle.
final Color color;
Expand Down
9 changes: 5 additions & 4 deletions lib/widgets/counter_display.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import '../utils/utils.dart';
class CounterDisplay extends StatelessWidget {
/// Creates a counter display widget.
const CounterDisplay({
Key? key,
super.key,
required this.value,
required this.color,
this.isPortrait = true,
}) : super(key: key);
});

/// The color with which to fill the counter container.
final Color color;
Expand All @@ -27,8 +27,9 @@ class CounterDisplay extends StatelessWidget {

@override
Widget build(BuildContext context) {
final TextStyle? counterStyle =
isPortrait ? Theme.of(context).textTheme.headline1 : Theme.of(context).textTheme.headline2;
final TextStyle? counterStyle = isPortrait
? Theme.of(context).textTheme.displayLarge
: Theme.of(context).textTheme.displayMedium;

return Container(
alignment: Alignment.center,
Expand Down
8 changes: 4 additions & 4 deletions lib/widgets/counters_drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ enum DrawerExtraActions { settings, help, rate, viewSource }
class CountersDrawer extends StatelessWidget {
/// Creates a counters drawer widget.
const CountersDrawer({
Key? key,
super.key,
required this.title,
required this.counters,
required this.onSelected,
this.onExtraSelected,
}) : super(key: key);
});

/// The title of the drawer displayed in the drawer header.
final String title;
Expand Down Expand Up @@ -63,7 +63,7 @@ class CountersDrawer extends StatelessWidget {
onTap: () => _onExtraActionTap(context, DrawerExtraActions.help),
),
ListTile(
leading: const Icon(Icons.code),
leading: const Icon(Icons.flutter_dash),
title: const Text(AppStrings.viewSourceItemTitle),
onTap: () => _onExtraActionTap(context, DrawerExtraActions.viewSource),
),
Expand All @@ -86,7 +86,7 @@ class CountersDrawer extends StatelessWidget {
child: DrawerHeader(
child: Text(
title,
style: Theme.of(context).textTheme.headline6,
style: Theme.of(context).textTheme.titleLarge,
),
),
);
Expand Down

0 comments on commit 29d071d

Please sign in to comment.