Release v2.0.0: Responsive layout with precise tap targets
- Responsive portrait/landscape layout system - Precise tap targets: speed text cycles units, compass area cycles themes - Screen wake lock to prevent dimming during navigation - Custom DIN1451Alt font integration - Updated app icons and Flutter dependencies 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
@@ -427,7 +427,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
@@ -484,7 +484,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 5.4 KiB |
@@ -145,33 +145,33 @@ class _SpeedometerScreenState extends State<SpeedometerScreen> {
|
||||
Widget _buildPortraitLayout(String speedText, ColorTheme currentTheme) {
|
||||
return Column(
|
||||
children: [
|
||||
// Speed area - takes most space
|
||||
// Speed area - takes most space, precise tap targets on text only
|
||||
Expanded(
|
||||
flex: 7,
|
||||
child: GestureDetector(
|
||||
onTap: _cycleUnit,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
color: Colors.transparent,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (_errorMessage.isNotEmpty)
|
||||
Flexible(
|
||||
child: Text(
|
||||
_errorMessage,
|
||||
style: TextStyle(
|
||||
color: currentTheme.speedText,
|
||||
fontSize: 18,
|
||||
fontFamily: 'DIN1451Alt',
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
color: Colors.transparent,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (_errorMessage.isNotEmpty)
|
||||
Flexible(
|
||||
child: Text(
|
||||
_errorMessage,
|
||||
style: TextStyle(
|
||||
color: currentTheme.speedText,
|
||||
fontSize: 18,
|
||||
fontFamily: 'DIN1451Alt',
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
Flexible(
|
||||
flex: 3,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
Flexible(
|
||||
flex: 3,
|
||||
child: GestureDetector(
|
||||
onTap: _cycleUnit,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
@@ -185,8 +185,11 @@ class _SpeedometerScreenState extends State<SpeedometerScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: 1,
|
||||
),
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: GestureDetector(
|
||||
onTap: _cycleUnit,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
@@ -199,13 +202,13 @@ class _SpeedometerScreenState extends State<SpeedometerScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Compass area - compact but tappable
|
||||
// Compass area - compact but fully tappable for theme cycling
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: GestureDetector(
|
||||
@@ -251,33 +254,33 @@ class _SpeedometerScreenState extends State<SpeedometerScreen> {
|
||||
Widget _buildLandscapeLayout(String speedText, ColorTheme currentTheme) {
|
||||
return Row(
|
||||
children: [
|
||||
// Speed area - takes majority of space
|
||||
// Speed area - takes majority of space, precise tap targets on text only
|
||||
Expanded(
|
||||
flex: 65,
|
||||
child: GestureDetector(
|
||||
onTap: _cycleUnit,
|
||||
child: Container(
|
||||
height: double.infinity,
|
||||
color: Colors.transparent,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (_errorMessage.isNotEmpty)
|
||||
Flexible(
|
||||
child: Text(
|
||||
_errorMessage,
|
||||
style: TextStyle(
|
||||
color: currentTheme.speedText,
|
||||
fontSize: 16,
|
||||
fontFamily: 'DIN1451Alt',
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
child: Container(
|
||||
height: double.infinity,
|
||||
color: Colors.transparent,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (_errorMessage.isNotEmpty)
|
||||
Flexible(
|
||||
child: Text(
|
||||
_errorMessage,
|
||||
style: TextStyle(
|
||||
color: currentTheme.speedText,
|
||||
fontSize: 16,
|
||||
fontFamily: 'DIN1451Alt',
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
Flexible(
|
||||
flex: 3,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
Flexible(
|
||||
flex: 3,
|
||||
child: GestureDetector(
|
||||
onTap: _cycleUnit,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
@@ -291,8 +294,11 @@ class _SpeedometerScreenState extends State<SpeedometerScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: 1,
|
||||
),
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: GestureDetector(
|
||||
onTap: _cycleUnit,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
@@ -305,13 +311,13 @@ class _SpeedometerScreenState extends State<SpeedometerScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Compass area - smaller but prominent
|
||||
// Compass area - smaller but fully tappable for theme cycling
|
||||
Expanded(
|
||||
flex: 35,
|
||||
child: GestureDetector(
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.7"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -33,6 +41,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -94,6 +118,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.14.4"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@@ -200,6 +232,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.4"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -344,6 +392,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
posix:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: posix
|
||||
sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.3"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -485,6 +541,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.6.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
flutter: ">=3.24.0"
|
||||
|
||||
@@ -25,6 +25,7 @@ dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^6.0.0
|
||||
flutter_launcher_icons: "^0.14.4"
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
@@ -32,4 +33,9 @@ flutter:
|
||||
fonts:
|
||||
- family: DIN1451Alt
|
||||
fonts:
|
||||
- asset: fonts/din1451alt.ttf
|
||||
- asset: fonts/din1451alt.ttf
|
||||
|
||||
flutter_launcher_icons:
|
||||
android: true
|
||||
ios: true
|
||||
image_path: "icon/speedo.png"
|
||||