This commit is contained in:
2024-10-19 14:17:37 +02:00
parent 9f98189983
commit ec76a028cb
53 changed files with 495 additions and 607 deletions

View File

@@ -1,14 +1,16 @@
# IFR Buddy
# ifrbuddy
**IFR Buddy** is a Flutter-based web application designed to help pilots and aviation enthusiasts easily record Instrument Flight Rules (IFR) clearances without the need for a pen. Featuring seamless navigation between input fields, dark mode, and a user-friendly interface, IFR Buddy simplifies the process of entering essential IFR details such as Clearance Limit, Route/SID, Altitude, Squawk Code, and Departure Frequency.
A new Flutter project.
## Features
## Getting Started
- **Seamless Navigation:** Move between input fields using keyboard buttons.
- **Dark Mode:** Toggle between light and dark themes for comfortable usage in any lighting condition.
- **Efficient Data Entry:** Quickly input and manage Clearance Limit, Route/SID, Altitude, Squawk Code, and Departure Frequency.
This project is a starting point for a Flutter application.
## License
A few resources to get you started if this is your first Flutter project:
This project is licensed under the MIT License.
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View File

@@ -2,7 +2,7 @@
<application
android:label="ifrbuddy"
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon">
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -539,7 +539,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@@ -596,7 +596,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";

View File

@@ -1 +1,122 @@
{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 509 B

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 798 B

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -12,7 +12,8 @@ class ComparisonPage extends StatefulWidget {
final bool isDarkMode;
final Function toggleDarkMode;
const ComparisonPage({super.key,
const ComparisonPage({
super.key,
required this.expectedClearanceLimit,
required this.expectedRoute,
required this.expectedAltitude,
@@ -159,8 +160,8 @@ class ComparisonPageState extends State<ComparisonPage> {
);
}
@override
Widget build(BuildContext context) {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('IFR Buddy'), // Global title
@@ -183,7 +184,7 @@ Widget build(BuildContext context) {
child: Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'Use this Page while receiving your clearance. The arrow button copies the excpected value. Same if left empty.',
'Use this Page while receiving your clearance. The arrow button copies the expected value. Same if left empty.',
style: TextStyle(fontSize: 16),
textAlign: TextAlign.center,
),
@@ -212,8 +213,8 @@ Widget build(BuildContext context) {
buildExpectedClearanceField('Clearance Limit', widget.expectedClearanceLimit),
buildExpectedClearanceField('Route', widget.expectedRoute),
buildExpectedClearanceField('Altitude', widget.expectedAltitude),
buildExpectedClearanceField('Transponder (Squawk)', widget.expectedSquawk),
buildExpectedClearanceField('Frequency', widget.expectedFrequency),
buildExpectedClearanceField('Transponder (Squawk)', widget.expectedSquawk),
],
),
),
@@ -251,6 +252,12 @@ Widget build(BuildContext context) {
widget.expectedAltitude,
focusNode: _actualAltitudeFocusNode,
),
buildActualClearanceField(
'Frequency',
_actualFrequencyController,
widget.expectedFrequency,
formatterList: [FrequencyInputFormatter()],
),
buildActualClearanceField(
'Transponder (Squawk)',
_actualSquawkController,
@@ -260,12 +267,6 @@ Widget build(BuildContext context) {
LengthLimitingTextInputFormatter(4),
],
),
buildActualClearanceField(
'Frequency',
_actualFrequencyController,
widget.expectedFrequency,
formatterList: [FrequencyInputFormatter()],
),
],
),
),
@@ -284,5 +285,5 @@ Widget build(BuildContext context) {
),
),
);
}
}
}

View File

@@ -1,9 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:keyboard_actions/keyboard_actions.dart'; // Correct package import
import 'comparison_page.dart';
import 'final_clearance_page.dart'; // Import final clearance page
import '../utils/frequency_input_formatter.dart';
import '../utils/frequency_input_formatter.dart'; // Ensure this path is correct
class ExpectationInputPage extends StatefulWidget {
final bool isDarkMode;
@@ -32,7 +31,7 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
final TextEditingController _expectedFrequencyController =
TextEditingController();
// Reintroduce FocusNodes
// FocusNodes for each field
final FocusNode _clearanceLimitFocusNode = FocusNode();
final FocusNode _routeFocusNode = FocusNode();
final FocusNode _altitudeFocusNode = FocusNode();
@@ -93,7 +92,7 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
}
}
// Updated method to build a text field with optional input
// Method to build a text field with optional input and standard keyboard
Widget buildTextField({
required String label,
required TextEditingController controller,
@@ -120,20 +119,15 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
enableIMEPersonalizedLearning: enableIMEPersonalizedLearning,
onFieldSubmitted: (_) {
if (isLastField) {
// If it's the last field, unfocus to close the keyboard
// If it's the last field, unfocus to close the keyboard and submit
currentFocus.unfocus();
// Optionally, you can trigger form submission here
// _navigateToComparisonPage();
_navigateToComparisonPage();
} else if (nextFocus != null) {
FocusScope.of(context).requestFocus(nextFocus);
}
},
// Updated validator to allow empty inputs
// Validator allows empty inputs but validates if input is present
validator: (value) {
// If you want to perform validation only when input is not empty,
// you can add conditional checks here.
// Example: Validate numerical fields if they are not empty
if (value != null && value.isNotEmpty) {
if (keyboardType == TextInputType.number ||
keyboardType == const TextInputType.numberWithOptions(decimal: true)) {
@@ -144,7 +138,7 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
// Add more specific validations if needed
}
// Example: Validate Transponder (Squawk) field
// Validate Transponder (Squawk) field
if (label == 'Transponder (Squawk)') {
if (!RegExp(r'^[0-7]{1,4}$').hasMatch(value)) {
return 'Squawk must be 1-4 digits between 0 and 7';
@@ -165,105 +159,6 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
);
}
// Configure KeyboardActions
KeyboardActionsConfig _buildConfig(BuildContext context) {
return KeyboardActionsConfig(
keyboardSeparatorColor: Colors.grey, // Optional: Customize the separator color
nextFocus: true, // Automatically handle next focus
actions: [
// Define actions for each FocusNode
KeyboardActionsItem(
focusNode: _clearanceLimitFocusNode,
toolbarButtons: [
(node) {
return GestureDetector(
onTap: () => node.nextFocus(),
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
"Next",
style: TextStyle(color: Colors.blue, fontSize: 16),
),
),
);
}
],
),
KeyboardActionsItem(
focusNode: _routeFocusNode,
toolbarButtons: [
(node) {
return GestureDetector(
onTap: () => node.nextFocus(),
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
"Next",
style: TextStyle(color: Colors.blue, fontSize: 16),
),
),
);
}
],
),
KeyboardActionsItem(
focusNode: _altitudeFocusNode,
toolbarButtons: [
(node) {
return GestureDetector(
onTap: () => node.nextFocus(),
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
"Next",
style: TextStyle(color: Colors.blue, fontSize: 16),
),
),
);
}
],
),
KeyboardActionsItem(
focusNode: _squawkFocusNode,
toolbarButtons: [
(node) {
return GestureDetector(
onTap: () => node.nextFocus(),
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
"Next",
style: TextStyle(color: Colors.blue, fontSize: 16),
),
),
);
}
],
),
KeyboardActionsItem(
focusNode: _frequencyFocusNode,
toolbarButtons: [
(node) {
return GestureDetector(
onTap: () {
node.unfocus(); // Dismiss the keyboard
_navigateToComparisonPage(); // Optionally, submit the form
},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
"Done",
style: TextStyle(color: Colors.blue, fontSize: 16),
),
),
);
}
],
),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -282,8 +177,6 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
body: GestureDetector(
// Dismiss the keyboard when tapping outside
onTap: () => FocusScope.of(context).unfocus(),
child: KeyboardActions(
config: _buildConfig(context), // Apply KeyboardActionsConfig
child: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
@@ -341,6 +234,12 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
controller: _expectedClearanceLimitController,
currentFocus: _clearanceLimitFocusNode,
nextFocus: _routeFocusNode,
keyboardType: TextInputType.text, // Standard keyboard
inputFormatters: [
// Allow letters, numbers, spaces, and hyphens
FilteringTextInputFormatter.allow(
RegExp(r'[A-Za-z0-9\s\-]')),
],
enableAutocorrect: false, // Disable autocorrect
enableSuggestions: false, // Disable suggestions
enableIMEPersonalizedLearning:
@@ -351,6 +250,12 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
controller: _expectedRouteController,
currentFocus: _routeFocusNode,
nextFocus: _altitudeFocusNode,
keyboardType: TextInputType.text, // Standard keyboard
inputFormatters: [
// Allow letters, numbers, spaces, and hyphens
FilteringTextInputFormatter.allow(
RegExp(r'[A-Za-z0-9\s\-]')),
],
enableAutocorrect: false, // Disable autocorrect
enableSuggestions: false, // Disable suggestions
enableIMEPersonalizedLearning:
@@ -361,10 +266,8 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
controller: _expectedAltitudeController,
currentFocus: _altitudeFocusNode,
nextFocus: _squawkFocusNode,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly
],
keyboardType: TextInputType.text, // Standard keyboard
inputFormatters: null, // No restrictions
enableAutocorrect: false, // Disable autocorrect
enableSuggestions: false, // Disable suggestions
enableIMEPersonalizedLearning:
@@ -375,8 +278,9 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
controller: _expectedSquawkController,
currentFocus: _squawkFocusNode,
nextFocus: _frequencyFocusNode,
keyboardType: TextInputType.number,
keyboardType: TextInputType.text, // Standard keyboard
inputFormatters: [
// Allow only digits 0-7 and limit to 4 characters
FilteringTextInputFormatter.allow(
RegExp(r'[0-7]')),
LengthLimitingTextInputFormatter(4),
@@ -391,9 +295,10 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
controller: _expectedFrequencyController,
currentFocus: _frequencyFocusNode,
isLastField: true,
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
inputFormatters: [FrequencyInputFormatter()],
keyboardType: TextInputType.text, // Standard keyboard
inputFormatters: [
FrequencyInputFormatter(), // Handles decimal inputs
],
enableAutocorrect: false, // Disable autocorrect
enableSuggestions: false, // Disable suggestions
enableIMEPersonalizedLearning:
@@ -401,13 +306,13 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _skipReadback,
child: const Text('Skip to Readback'),
onPressed: _navigateToComparisonPage,
child: const Text('Next'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: _navigateToComparisonPage,
child: const Text('Navigate to Comparison Page'),
TextButton(
onPressed: _skipReadback,
child: const Text('Skip to end'),
),
],
),
@@ -420,7 +325,6 @@ class ExpectationInputPageState extends State<ExpectationInputPage> {
),
),
),
),
);
}
}

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'expectation_input_page.dart';
import 'edit_clearance_page.dart'; // Import the edit clearance page
// Import the edit clearance page
import '../widgets/clearance_field.dart';
class FinalClearanceDisplay extends StatefulWidget {
@@ -44,33 +44,6 @@ class FinalClearanceDisplayState extends State<FinalClearanceDisplay> {
}
// Navigate to Edit Clearance Page and handle returned data
Future<void> _navigateToEditClearance() async {
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditClearancePage(
clearanceLimit: clearanceLimit,
route: route,
altitude: altitude,
squawk: squawk,
frequency: frequency,
isDarkMode: widget.isDarkMode,
toggleDarkMode: widget.toggleDarkMode,
),
),
);
// If the result contains updated data, update the state with the new values
if (result != null && mounted) {
setState(() {
clearanceLimit = result['clearanceLimit'];
route = result['route'];
altitude = result['altitude'];
squawk = result['squawk'];
frequency = result['frequency'];
});
}
}
// Navigate back to the first page (ExpectationInputPage)
void _navigateHome(BuildContext context) {
@@ -97,18 +70,7 @@ class FinalClearanceDisplayState extends State<FinalClearanceDisplay> {
_navigateHome(context);
},
),
actions: [
IconButton(
icon: const Icon(Icons.edit), // Edit button
onPressed: _navigateToEditClearance,
),
IconButton(
icon: Icon(widget.isDarkMode ? Icons.dark_mode : Icons.light_mode),
onPressed: () {
widget.toggleDarkMode();
},
),
],
actions: const [],
),
body: Center(
child: SingleChildScrollView(

View File

@@ -1,68 +1,68 @@
{
"info": {
"version": 1,
"author": "xcode"
},
"images": [
"images" : [
{
"size": "16x16",
"idiom": "mac",
"filename": "app_icon_16.png",
"scale": "1x"
"size" : "16x16",
"idiom" : "mac",
"filename" : "app_icon_16.png",
"scale" : "1x"
},
{
"size": "16x16",
"idiom": "mac",
"filename": "app_icon_32.png",
"scale": "2x"
"size" : "16x16",
"idiom" : "mac",
"filename" : "app_icon_32.png",
"scale" : "2x"
},
{
"size": "32x32",
"idiom": "mac",
"filename": "app_icon_32.png",
"scale": "1x"
"size" : "32x32",
"idiom" : "mac",
"filename" : "app_icon_32.png",
"scale" : "1x"
},
{
"size": "32x32",
"idiom": "mac",
"filename": "app_icon_64.png",
"scale": "2x"
"size" : "32x32",
"idiom" : "mac",
"filename" : "app_icon_64.png",
"scale" : "2x"
},
{
"size": "128x128",
"idiom": "mac",
"filename": "app_icon_128.png",
"scale": "1x"
"size" : "128x128",
"idiom" : "mac",
"filename" : "app_icon_128.png",
"scale" : "1x"
},
{
"size": "128x128",
"idiom": "mac",
"filename": "app_icon_256.png",
"scale": "2x"
"size" : "128x128",
"idiom" : "mac",
"filename" : "app_icon_256.png",
"scale" : "2x"
},
{
"size": "256x256",
"idiom": "mac",
"filename": "app_icon_256.png",
"scale": "1x"
"size" : "256x256",
"idiom" : "mac",
"filename" : "app_icon_256.png",
"scale" : "1x"
},
{
"size": "256x256",
"idiom": "mac",
"filename": "app_icon_512.png",
"scale": "2x"
"size" : "256x256",
"idiom" : "mac",
"filename" : "app_icon_512.png",
"scale" : "2x"
},
{
"size": "512x512",
"idiom": "mac",
"filename": "app_icon_512.png",
"scale": "1x"
"size" : "512x512",
"idiom" : "mac",
"filename" : "app_icon_512.png",
"scale" : "1x"
},
{
"size": "512x512",
"idiom": "mac",
"filename": "app_icon_1024.png",
"scale": "2x"
"size" : "512x512",
"idiom" : "mac",
"filename" : "app_icon_1024.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 B

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,22 +1,6 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
url: "https://pub.dev"
source: hosted
version: "3.6.1"
args:
dependency: transitive
description:
name: args
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
url: "https://pub.dev"
source: hosted
version: "2.6.0"
async:
dependency: transitive
description:
@@ -41,22 +25,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev"
source: hosted
version: "2.0.3"
cli_util:
dependency: transitive
description:
name: cli_util
sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19
url: "https://pub.dev"
source: hosted
version: "0.4.1"
clock:
dependency: transitive
description:
@@ -73,14 +41,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.18.0"
crypto:
dependency: transitive
description:
name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
cupertino_icons:
dependency: "direct main"
description:
@@ -118,14 +78,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_launcher_icons:
dependency: "direct main"
description:
name: flutter_launcher_icons
sha256: "619817c4b65b322b5104b6bb6dfe6cda62d9729bd7ad4303ecc8b4e690a67a77"
url: "https://pub.dev"
source: hosted
version: "0.14.1"
flutter_lints:
dependency: "direct dev"
description:
@@ -160,46 +112,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
image:
dependency: transitive
description:
name: image
sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d
url: "https://pub.dev"
source: hosted
version: "4.3.0"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.9.0"
keyboard_actions:
dependency: "direct main"
description:
name: keyboard_actions
sha256: "31e0ab2a706ac8f58887efa60efc1f19aecdf37d8ab0f665a0f156d1fbeab650"
url: "https://pub.dev"
source: hosted
version: "4.2.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev"
source: hosted
version: "10.0.4"
version: "10.0.5"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev"
source: hosted
version: "3.0.3"
version: "3.0.5"
leak_tracker_testing:
dependency: transitive
description:
@@ -228,18 +156,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.8.0"
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.12.0"
version: "1.15.0"
path:
dependency: transitive
description:
@@ -272,14 +200,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.0"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform:
dependency: transitive
description:
@@ -401,10 +321,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
version: "0.7.2"
typed_data:
dependency: transitive
description:
@@ -425,10 +345,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.1"
version: "14.2.5"
web:
dependency: transitive
description:
@@ -445,22 +365,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.0"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.4.3 <4.0.0"
flutter: ">=3.22.0"

View File

@@ -36,9 +36,6 @@ dependencies:
cupertino_icons: ^1.0.6
http: ^1.2.2
shared_preferences: ^2.3.2
keyboard_actions: ^4.2.0
flutter_launcher_icons: ^0.14.1
dev_dependencies:
flutter_test:
sdk: flutter

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 B

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 B

View File

@@ -18,7 +18,7 @@
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<meta name="description" content="Write down IFR Clearances easily">
<!-- No cache tag -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
@@ -29,7 +29,7 @@
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="ifrbuddy">
<meta name="apple-mobile-web-app-title" content="IFR Buddy">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->

View File

@@ -1,11 +1,11 @@
{
"name": "ifrbuddy",
"short_name": "ifrbuddy",
"name": "IFR Buddy",
"short_name": "IFR Buddy",
"start_url": ".",
"display": "standalone",
"background_color": "#hexcode",
"theme_color": "#hexcode",
"description": "A new Flutter project.",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "Write down IFR Clearances easily",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 33 KiB