Compare commits

..

No commits in common. "main" and "auto-claude/001-normalize-code-update-packages-widgetify-component" have entirely different histories.

118 changed files with 2771 additions and 26151 deletions

View File

@ -1,15 +1,15 @@
{ {
"active": true, "active": true,
"spec": "002-migrate-api-routes-from-http-to-grpc", "spec": "001-normalize-code-update-packages-widgetify-component",
"state": "building", "state": "building",
"subtasks": { "subtasks": {
"completed": 10, "completed": 11,
"total": 13, "total": 14,
"in_progress": 1, "in_progress": 1,
"failed": 0 "failed": 0
}, },
"phase": { "phase": {
"current": "Provider Integration", "current": "Cleanup and Verification",
"id": null, "id": null,
"total": 3 "total": 3
}, },
@ -18,8 +18,8 @@
"max": 1 "max": 1
}, },
"session": { "session": {
"number": 11, "number": 12,
"started_at": "2026-01-20T12:45:59.858836" "started_at": "2026-01-20T11:20:56.182893"
}, },
"last_update": "2026-01-20T13:09:16.962328" "last_update": "2026-01-20T11:47:55.069999"
} }

View File

@ -11,14 +11,14 @@
"Edit(./**)", "Edit(./**)",
"Glob(./**)", "Glob(./**)",
"Grep(./**)", "Grep(./**)",
"Read(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/002-migrate-api-routes-from-http-to-grpc/**)", "Read(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/001-normalize-code-update-packages-widgetify-component/**)",
"Write(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/002-migrate-api-routes-from-http-to-grpc/**)", "Write(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/001-normalize-code-update-packages-widgetify-component/**)",
"Edit(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/002-migrate-api-routes-from-http-to-grpc/**)", "Edit(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/001-normalize-code-update-packages-widgetify-component/**)",
"Glob(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/002-migrate-api-routes-from-http-to-grpc/**)", "Glob(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/001-normalize-code-update-packages-widgetify-component/**)",
"Grep(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/002-migrate-api-routes-from-http-to-grpc/**)", "Grep(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/001-normalize-code-update-packages-widgetify-component/**)",
"Read(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/002-migrate-api-routes-from-http-to-grpc/.auto-claude/specs/002-migrate-api-routes-from-http-to-grpc/**)", "Read(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/001-normalize-code-update-packages-widgetify-component/.auto-claude/specs/001-normalize-code-update-packages-widgetify-component/**)",
"Write(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/002-migrate-api-routes-from-http-to-grpc/.auto-claude/specs/002-migrate-api-routes-from-http-to-grpc/**)", "Write(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/001-normalize-code-update-packages-widgetify-component/.auto-claude/specs/001-normalize-code-update-packages-widgetify-component/**)",
"Edit(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/002-migrate-api-routes-from-http-to-grpc/.auto-claude/specs/002-migrate-api-routes-from-http-to-grpc/**)", "Edit(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/worktrees/tasks/001-normalize-code-update-packages-widgetify-component/.auto-claude/specs/001-normalize-code-update-packages-widgetify-component/**)",
"Read(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/**)", "Read(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/**)",
"Write(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/**)", "Write(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/**)",
"Edit(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/**)", "Edit(/Users/mathias/Documents/workspaces/plan-b/ionic-planb-logistic-app-flutter/.auto-claude/**)",

8
.gitignore vendored
View File

@ -46,11 +46,3 @@ app.*.map.json
# Auto Claude data directory # Auto Claude data directory
.auto-claude/ .auto-claude/
# Auto Claude generated files
.auto-claude-security.json
.auto-claude-status
.claude_settings.json
.worktrees/
.security-key
logs/security/

View File

@ -78,27 +78,19 @@ lib/
### Design System (Svrnty) ### Design System (Svrnty)
**Primary Colors:** **Primary Colors:**
- Primary (Crimson): #C91F37 (light) / #FF5A6D (dark) - Primary (Crimson): #C44D58
- Secondary (Slate Blue): #2D3843 (light) / #A5B6C8 (dark) - Secondary (Slate Blue): #475C6C
- Tertiary (Green): #16803D (light) / #5EE890 (dark) - Error: #BA1A1A
- Error: #D32F2F (light) / #FF8A80 (dark)
**Typography:** **Typography:**
- Primary Font: Montserrat (all weights 300-700) - Primary Font: Montserrat (all weights 300-700)
- Monospace Font: IBMPlexMono - Monospace Font: IBMPlexMono
- Material Design 3 text styles with explicit color assignments - Material Design 3 text styles
**Theme System:** **Theme Files:**
- **2 Theme Variants:** Light and Dark (forest green background) - `lib/theme.dart` - Complete Material 3 theme configuration
- **WCAG AAA Compliant:** All text meets 7:1 contrast minimum - Light and dark themes with high-contrast variants
- **Dark Theme Background:** Forest Green (#0C1410) - unique branding - All colors defined in ColorScheme
- **No Hardcoded Colors:** All components use ColorScheme properties
- **Theme Files:**
- `lib/theme.dart` - Material 3 theme with 2 ColorScheme variants
- `lib/theme/color_system.dart` - Svrnty color constants
- `lib/theme/status_colors.dart` - Status color utilities
- `lib/theme/component_themes.dart` - Component-specific themes
- `lib/theme/README.md` - Complete theme documentation
## Core Patterns & Standards ## Core Patterns & Standards
@ -238,60 +230,6 @@ void completeDelivery(int id) { ... } // Done
void completeDelivery(int id) { ... } void completeDelivery(int id) { ... }
``` ```
### 8. Theme System (MANDATORY)
**Standard Color Access Pattern (use everywhere):**
```dart
final colorScheme = Theme.of(context).colorScheme;
// Primary UI
color: colorScheme.primary // Primary brand color
color: colorScheme.onPrimary // Text on primary
// Text colors
color: colorScheme.onSurface // Primary text
color: colorScheme.onSurfaceVariant // Secondary text
// Backgrounds
color: colorScheme.surface // Page background
color: colorScheme.surfaceContainer // Card background
// Shadows
color: colorScheme.scrim.withValues(alpha: 0.2)
```
**FORBIDDEN Patterns:**
```dart
// NEVER use these in component files:
color: Colors.white // FORBIDDEN
color: Colors.black // FORBIDDEN
color: Color(0xFFXXXXXX) // FORBIDDEN (except in theme files)
color: SvrntyColors.crimsonRed // FORBIDDEN - use colorScheme.primary
```
**Dark Theme:**
The app uses a **forest green dark theme** (#0C1410) for unique branding.
All text colors automatically adapt with WCAG AAA compliance (7:1 minimum contrast).
**Status Colors:**
```dart
import '../theme/status_colors.dart';
// Theme-aware status colors (preferred)
StatusColorScheme.getStatusColorFromTheme('completed', colorScheme)
// Hardcoded status colors (fallback)
StatusColorScheme.getStatusColor('completed')
```
**Modifying Theme:**
To change brand colors, edit `/lib/theme.dart`:
- `lightScheme()` - Light theme ColorScheme
- `darkScheme()` - Dark theme ColorScheme
**Documentation:**
See `/lib/theme/README.md` for complete theme system documentation.
## API Integration ## API Integration
### Base URLs ### Base URLs

14
android/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks

View File

@ -0,0 +1,57 @@
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.goutezplanb.planb_logistic"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.goutezplanb.planb_logistic"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion // Required for Google Navigation Flutter
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
// OAuth redirect scheme for flutter_appauth
manifestPlaceholders["appAuthRedirectScheme"] = "com.goutezplanb.delivery"
}
packagingOptions {
// Enable desugaring for Java NIO support required by Google Navigation SDK
exclude("META-INF/proguard/androidx-*.pro")
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
dependencies {
// Desugaring for Java NIO support required by Google Navigation SDK
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs_nio:2.0.4")
}
flutter {
source = "../.."
}

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -0,0 +1,53 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="planb_logistic"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCuYzbusLkVrHcy10bJ8STF6gyOexQWjuk" />
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- Disable Impeller (Vulkan) rendering for better GPU compatibility -->
<!-- Use OpenGL rendering instead, which works better with Mali GPUs -->
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@ -0,0 +1,5 @@
package com.goutezplanb.planb_logistic
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity()

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

24
android/build.gradle.kts Normal file
View File

@ -0,0 +1,24 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
val newBuildDir: Directory =
rootProject.layout.buildDirectory
.dir("../../build")
.get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}

View File

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip

View File

@ -0,0 +1,26 @@
pluginManagement {
val flutterSdkPath =
run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.9.1" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
}
include(":app")

View File

@ -13,12 +13,12 @@ PODS:
- Flutter - Flutter
- google_navigation_flutter (0.0.1): - google_navigation_flutter (0.0.1):
- Flutter - Flutter
- GoogleNavigation (= 10.7.0) - GoogleNavigation (= 10.0.0)
- GoogleMaps (10.7.0): - GoogleMaps (10.0.0):
- GoogleMaps/Maps (= 10.7.0) - GoogleMaps/Maps (= 10.0.0)
- GoogleMaps/Maps (10.7.0) - GoogleMaps/Maps (10.0.0)
- GoogleNavigation (10.7.0): - GoogleNavigation (10.0.0):
- GoogleMaps (= 10.7.0) - GoogleMaps (= 10.0.0)
- image_picker_ios (0.0.1): - image_picker_ios (0.0.1):
- Flutter - Flutter
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
@ -74,9 +74,9 @@ SPEC CHECKSUMS:
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_appauth: d4abcf54856e5d8ba82ed7646ffc83245d4aa448 flutter_appauth: d4abcf54856e5d8ba82ed7646ffc83245d4aa448
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
google_navigation_flutter: d3daf840117efbfd2d70e0f70c933cffb62b3ad1 google_navigation_flutter: aff5e273b19113b8964780ff4e899f6f2e07f6dc
GoogleMaps: 5db81729b4f6defd40820d46b49a350273ec1d28 GoogleMaps: 9ce9c898074e96655acaf1ba5d6f85991ecee7a3
GoogleNavigation: ed62063d8f141a8a134703ea8246778ec3d8da01 GoogleNavigation: 963899162709d245f07a65cd68c3115292ee2bdb
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326 image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d

View File

@ -472,7 +472,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -603,7 +603,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -654,7 +654,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;

View File

@ -1,313 +0,0 @@
import 'dart:async';
import 'package:fixnum/fixnum.dart';
import 'package:grpc/grpc.dart';
import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart' as $timestamp;
import '../generated/cqrs_services.pb.dart' as $pb;
import '../generated/cqrs_services.pbgrpc.dart';
import '../models/delivery.dart';
import '../models/delivery_address.dart';
import '../models/delivery_contact.dart';
import '../models/delivery_order.dart';
import '../models/delivery_route.dart';
import '../models/user_info.dart';
import '../services/auth_service.dart';
import 'grpc_config.dart';
import 'types.dart';
/// gRPC-based CQRS API client for Plan B Logistics.
class GrpcCqrsApiClient {
final GrpcConfig config;
final AuthService? authService;
ClientChannel? _channel;
DynamicQueryServiceClient? _queryClient;
CommandServiceClient? _commandClient;
GrpcCqrsApiClient({
required this.config,
this.authService,
});
ClientChannel get channel {
if (_channel == null) {
final ChannelCredentials credentials;
if (!config.useTls) {
credentials = const ChannelCredentials.insecure();
} else if (config.allowSelfSignedCertificate) {
credentials = ChannelCredentials.secure(
onBadCertificate: (certificate, host) => true,
);
} else {
credentials = const ChannelCredentials.secure();
}
_channel = ClientChannel(
config.host,
port: config.port,
options: ChannelOptions(
credentials: credentials,
connectionTimeout: config.timeout,
idleTimeout: const Duration(minutes: 5),
),
);
}
return _channel!;
}
DynamicQueryServiceClient get queryClient {
_queryClient ??= DynamicQueryServiceClient(channel);
return _queryClient!;
}
CommandServiceClient get commandClient {
_commandClient ??= CommandServiceClient(channel);
return _commandClient!;
}
Future<CallOptions> _buildCallOptions() async {
final metadata = <String, String>{};
if (authService != null) {
final token = await authService!.ensureValidToken();
if (token != null) {
metadata['authorization'] = 'Bearer $token';
}
}
return CallOptions(
metadata: metadata,
timeout: config.timeout,
);
}
ApiError _mapGrpcError(GrpcError error) {
switch (error.code) {
case StatusCode.unauthenticated:
return ApiError.http(
statusCode: 401,
message: error.message ?? 'Authentication required',
);
case StatusCode.permissionDenied:
return ApiError.http(
statusCode: 403,
message: error.message ?? 'Permission denied',
);
case StatusCode.notFound:
return ApiError.http(
statusCode: 404,
message: error.message ?? 'Resource not found',
);
case StatusCode.invalidArgument:
return ApiError.validation(
error.message ?? 'Invalid request',
null,
);
case StatusCode.deadlineExceeded:
return ApiError.timeout();
case StatusCode.unavailable:
return ApiError.network('Service unavailable');
default:
return ApiError.unknown(
error.message ?? 'Unknown error',
exception: error,
);
}
}
Future<Result<List<DeliveryRoute>>> getDeliveryRoutes() async {
try {
final options = await _buildCallOptions();
final request = DynamicQuerySimpleDeliveryRouteQueryItemsRequest();
final response = await queryClient.querySimpleDeliveryRouteQueryItems(
request,
options: options,
);
final routes = response.data.map((item) => DeliveryRoute(
id: item.id.toInt(),
routeId: item.routeId.toInt(),
name: item.name,
routeName: item.routeName,
deliveriesCount: item.deliveriesCount,
deliveredCount: item.deliveredCount,
completed: item.completed,
createdAt: item.createdAt.toDateTime().toIso8601String(),
)).toList();
return Result.success(routes);
} on GrpcError catch (e) {
return Result.error(_mapGrpcError(e));
} catch (e) {
return Result.error(ApiError.unknown(e.toString(), exception: Exception(e.toString())));
}
}
Future<Result<List<Delivery>>> getDeliveries({required int routeFragmentId}) async {
try {
final options = await _buildCallOptions();
final request = DynamicQuerySimpleDeliveriesQueryItemsRequest(
filters: [
DynamicQueryFilter(
path: 'RouteFragmentId',
type: 0, // Equal
value: routeFragmentId.toString(),
),
],
);
final response = await queryClient.querySimpleDeliveriesQueryItems(
request,
options: options,
);
final deliveries = response.data.map((item) {
final address = item.hasDeliveryAddress()
? DeliveryAddress(
id: item.deliveryAddress.id.toInt(),
line1: item.deliveryAddress.line1,
line2: item.deliveryAddress.line2.isNotEmpty ? item.deliveryAddress.line2 : null,
postalCode: item.deliveryAddress.postalCode.isNotEmpty ? item.deliveryAddress.postalCode : null,
city: item.deliveryAddress.city,
subdivision: item.deliveryAddress.subdivision.isNotEmpty ? item.deliveryAddress.subdivision : null,
countryCode: item.deliveryAddress.countryCode,
latitude: item.deliveryAddress.latitude,
longitude: item.deliveryAddress.longitude,
formattedAddress: item.deliveryAddress.formattedAddress,
)
: null;
final orders = item.orders.map((orderProto) {
final contacts = orderProto.contacts.map((contactProto) => DeliveryContact(
firstName: contactProto.firstName,
lastName: contactProto.lastName,
phoneNumber: contactProto.phoneNumber.isNotEmpty ? contactProto.phoneNumber : null,
fullName: contactProto.fullName,
)).toList();
return DeliveryOrder(
id: orderProto.id.toInt(),
isNewCustomer: orderProto.isNewCustomer,
note: orderProto.note.isNotEmpty ? orderProto.note : null,
totalAmount: double.tryParse(orderProto.totalAmount) ?? 0.0,
totalPaid: orderProto.totalPaid.isNotEmpty ? double.tryParse(orderProto.totalPaid) : null,
totalItems: orderProto.totalItems,
contacts: contacts,
contact: orderProto.hasContact()
? DeliveryContact(
firstName: orderProto.contact.firstName,
lastName: orderProto.contact.lastName,
phoneNumber: orderProto.contact.phoneNumber.isNotEmpty ? orderProto.contact.phoneNumber : null,
fullName: orderProto.contact.fullName,
)
: null,
);
}).toList();
final deliveredBy = item.hasDeliveredBy()
? UserInfo(
id: item.deliveredBy.id.toInt(),
firstName: item.deliveredBy.firstName,
lastName: item.deliveredBy.lastName,
fullName: item.deliveredBy.fullName,
)
: null;
return Delivery(
id: item.id.toInt(),
routeFragmentId: item.routeFragmentId.toInt(),
deliveryIndex: item.deliveryIndex,
orders: orders,
deliveredBy: deliveredBy,
deliveryAddress: address,
deliveredAt: item.hasDeliveredAt() ? item.deliveredAt.toDateTime().toIso8601String() : null,
skippedAt: item.hasSkippedAt() ? item.skippedAt.toDateTime().toIso8601String() : null,
createdAt: item.createdAt.toDateTime().toIso8601String(),
updatedAt: item.hasUpdatedAt() ? item.updatedAt.toDateTime().toIso8601String() : null,
delivered: item.delivered,
hasBeenSkipped: item.hasBeenSkipped,
isSkipped: item.isSkipped,
name: item.name,
);
}).toList();
return Result.success(deliveries);
} on GrpcError catch (e) {
return Result.error(_mapGrpcError(e));
} catch (e) {
return Result.error(ApiError.unknown(e.toString(), exception: Exception(e.toString())));
}
}
Future<Result<void>> completeDelivery({required int deliveryId}) async {
try {
final options = await _buildCallOptions();
final request = CompleteDeliveryCommandRequest(
deliveryId: Int64(deliveryId),
deliveredAt: DateTime.now().toUtc().toProto3Timestamp(),
);
await commandClient.completeDelivery(request, options: options);
return Result.success(null);
} on GrpcError catch (e) {
return Result.error(_mapGrpcError(e));
} catch (e) {
return Result.error(ApiError.unknown(e.toString(), exception: Exception(e.toString())));
}
}
Future<Result<void>> markDeliveryAsUncompleted({required int deliveryId}) async {
try {
final options = await _buildCallOptions();
final request = MarkDeliveryAsUncompletedCommandRequest(
deliveryId: Int64(deliveryId),
);
await commandClient.markDeliveryAsUncompleted(request, options: options);
return Result.success(null);
} on GrpcError catch (e) {
return Result.error(_mapGrpcError(e));
} catch (e) {
return Result.error(ApiError.unknown(e.toString(), exception: Exception(e.toString())));
}
}
Future<Result<void>> skipDelivery({
required int deliveryId,
required String description,
}) async {
try {
final options = await _buildCallOptions();
final request = SkipDeliveryCommandRequest(
deliveryId: Int64(deliveryId),
description: description,
skippedAt: DateTime.now().toUtc().toProto3Timestamp(),
);
await commandClient.skipDelivery(request, options: options);
return Result.success(null);
} on GrpcError catch (e) {
return Result.error(_mapGrpcError(e));
} catch (e) {
return Result.error(ApiError.unknown(e.toString(), exception: Exception(e.toString())));
}
}
void shutdown() {
_channel?.shutdown();
_channel = null;
_queryClient = null;
_commandClient = null;
}
}
// Extension to convert DateTime to protobuf Timestamp
extension DateTimeToProto on DateTime {
$timestamp.Timestamp toProto3Timestamp() {
return $timestamp.Timestamp()
..seconds = Int64(millisecondsSinceEpoch ~/ 1000)
..nanos = ((millisecondsSinceEpoch % 1000) * 1000000).toInt();
}
}

View File

@ -1,59 +0,0 @@
/// Configuration for gRPC client connections.
///
/// Provides separate configurations for development and production environments
/// with appropriate security settings for each.
class GrpcConfig {
/// The gRPC server host address.
final String host;
/// The gRPC server port.
final int port;
/// Connection timeout duration.
final Duration timeout;
/// Whether to use TLS for secure connections.
///
/// When false, uses insecure (plaintext) credentials suitable only for
/// development environments.
final bool useTls;
/// Whether to allow self-signed certificates.
///
/// Only applicable when [useTls] is true. Useful for development
/// environments with self-signed certificates.
final bool allowSelfSignedCertificate;
const GrpcConfig({
required this.host,
required this.port,
this.timeout = const Duration(seconds: 30),
this.useTls = true,
this.allowSelfSignedCertificate = false,
});
/// Development configuration pointing to local/development gRPC server.
///
/// Uses TLS with self-signed certificate support for local HTTPS.
static const GrpcConfig development = GrpcConfig(
host: 'localhost',
port: 5011,
timeout: Duration(seconds: 30),
useTls: true,
allowSelfSignedCertificate: true,
);
/// Production configuration for the Plan B Logistics gRPC server.
///
/// Uses TLS for secure communication.
static const GrpcConfig production = GrpcConfig(
host: 'grpc-route.goutezplanb.com',
port: 443,
timeout: Duration(seconds: 30),
useTls: true,
allowSelfSignedCertificate: false,
);
/// Returns the full address string in the format "host:port".
String get address => '$host:$port';
}

View File

@ -1,352 +0,0 @@
import 'dart:async';
import 'package:grpc/grpc.dart';
import 'grpc_config.dart';
import '../generated/reflection.pbgrpc.dart';
import '../generated/descriptor.pb.dart';
/// Exception types for gRPC discovery operations.
abstract class GrpcDiscoveryException implements Exception {
final String message;
GrpcDiscoveryException(this.message);
@override
String toString() => '$runtimeType: $message';
}
/// Thrown when the gRPC reflection service returns an error.
class ReflectionException extends GrpcDiscoveryException {
final int errorCode;
ReflectionException(super.message, this.errorCode);
@override
String toString() => 'ReflectionException: $message (code: $errorCode)';
}
/// Thrown when connection to the server fails.
class ConnectionException extends GrpcDiscoveryException {
ConnectionException(super.message);
}
/// Represents a discovered gRPC service with its methods.
class DiscoveredService {
final String name;
final List<DiscoveredMethod> methods;
const DiscoveredService({
required this.name,
required this.methods,
});
@override
String toString() => 'DiscoveredService($name, methods: ${methods.length})';
}
/// Represents a method within a discovered gRPC service.
class DiscoveredMethod {
final String name;
final String inputType;
final String outputType;
final bool clientStreaming;
final bool serverStreaming;
const DiscoveredMethod({
required this.name,
required this.inputType,
required this.outputType,
required this.clientStreaming,
required this.serverStreaming,
});
@override
String toString() => 'DiscoveredMethod($name)';
}
/// Client for discovering gRPC services using server reflection.
///
/// Connects to a gRPC server's reflection service to enumerate available
/// services and their method signatures. This is useful for development
/// and proto generation.
///
/// Example usage:
/// ```dart
/// final discovery = GrpcDiscoveryClient(config: GrpcConfig.development);
/// try {
/// final services = await discovery.listServices();
/// for (final service in services) {
/// print('Service: $service');
/// }
/// } finally {
/// await discovery.close();
/// }
/// ```
class GrpcDiscoveryClient {
final GrpcConfig config;
late final ClientChannel _channel;
late final ServerReflectionClient _stub;
bool _isInitialized = false;
GrpcDiscoveryClient({required this.config});
/// Initializes the gRPC channel and reflection client.
///
/// This is called automatically on first use, but can be called
/// explicitly to verify connection.
void _ensureInitialized() {
if (_isInitialized) return;
_channel = ClientChannel(
config.host,
port: config.port,
options: ChannelOptions(
credentials: config.useTls
? const ChannelCredentials.secure()
: const ChannelCredentials.insecure(),
connectionTimeout: config.timeout,
),
);
_stub = ServerReflectionClient(_channel);
_isInitialized = true;
}
/// Lists all available services on the server.
///
/// Returns a list of fully qualified service names.
/// Excludes the reflection service itself by default.
///
/// Throws [ConnectionException] if connection fails.
/// Throws [ReflectionException] if reflection service returns an error.
Future<List<String>> listServices({bool includeReflection = false}) async {
_ensureInitialized();
try {
final responseStream = _stub.serverReflectionInfo(
_createRequestStream([
ServerReflectionRequest()..listServices = '',
]),
);
final responses = await responseStream.toList();
if (responses.isEmpty) {
throw ReflectionException('No response from reflection service', 0);
}
final response = responses.first;
if (response.hasErrorResponse()) {
throw ReflectionException(
response.errorResponse.errorMessage,
response.errorResponse.errorCode,
);
}
List<String> services = response.listServicesResponse.service
.map((s) => s.name)
.toList();
if (!includeReflection) {
services = services
.where((s) => !s.contains('reflection'))
.toList();
}
return services;
} on GrpcError catch (e) {
throw ConnectionException('Failed to connect to ${config.address}: ${e.message}');
}
}
/// Gets file descriptors for a symbol (service, message, etc.).
///
/// Returns a list of [FileDescriptorProto] that define the symbol
/// and all its transitive dependencies.
///
/// Throws [ConnectionException] if connection fails.
/// Throws [ReflectionException] if symbol not found or other error.
Future<List<FileDescriptorProto>> getFileDescriptorsForSymbol(
String symbol,
) async {
_ensureInitialized();
try {
final responseStream = _stub.serverReflectionInfo(
_createRequestStream([
ServerReflectionRequest()..fileContainingSymbol = symbol,
]),
);
final responses = await responseStream.toList();
if (responses.isEmpty) {
throw ReflectionException('No response for symbol: $symbol', 0);
}
final response = responses.first;
if (response.hasErrorResponse()) {
throw ReflectionException(
response.errorResponse.errorMessage,
response.errorResponse.errorCode,
);
}
return response.fileDescriptorResponse.fileDescriptorProto
.map((bytes) => FileDescriptorProto.fromBuffer(bytes))
.toList();
} on GrpcError catch (e) {
throw ConnectionException('Failed to get descriptors: ${e.message}');
}
}
/// Gets file descriptors by filename.
///
/// Returns a list of [FileDescriptorProto] for the specified file
/// and its dependencies.
///
/// Throws [ConnectionException] if connection fails.
/// Throws [ReflectionException] if file not found or other error.
Future<List<FileDescriptorProto>> getFileDescriptorsByName(
String filename,
) async {
_ensureInitialized();
try {
final responseStream = _stub.serverReflectionInfo(
_createRequestStream([
ServerReflectionRequest()..fileByFilename = filename,
]),
);
final responses = await responseStream.toList();
if (responses.isEmpty) {
throw ReflectionException('No response for file: $filename', 0);
}
final response = responses.first;
if (response.hasErrorResponse()) {
throw ReflectionException(
response.errorResponse.errorMessage,
response.errorResponse.errorCode,
);
}
return response.fileDescriptorResponse.fileDescriptorProto
.map((bytes) => FileDescriptorProto.fromBuffer(bytes))
.toList();
} on GrpcError catch (e) {
throw ConnectionException('Failed to get file descriptor: ${e.message}');
}
}
/// Discovers all services and their methods.
///
/// Returns a list of [DiscoveredService] containing service names
/// and their method signatures.
///
/// This is a convenience method that combines [listServices] and
/// [getFileDescriptorsForSymbol] to provide detailed service information.
Future<List<DiscoveredService>> discoverAllServices() async {
final serviceNames = await listServices();
final List<DiscoveredService> discoveredServices = [];
for (final serviceName in serviceNames) {
try {
final descriptors = await getFileDescriptorsForSymbol(serviceName);
final methods = <DiscoveredMethod>[];
for (final descriptor in descriptors) {
for (final service in descriptor.service) {
// Match the service by fully qualified name
final fullName = descriptor.package.isEmpty
? service.name
: '${descriptor.package}.${service.name}';
if (fullName == serviceName) {
for (final method in service.method) {
methods.add(DiscoveredMethod(
name: method.name,
inputType: method.inputType,
outputType: method.outputType,
clientStreaming: method.clientStreaming,
serverStreaming: method.serverStreaming,
));
}
}
}
}
discoveredServices.add(DiscoveredService(
name: serviceName,
methods: methods,
));
} on GrpcDiscoveryException {
// If we can't get details for a service, add it with no methods
discoveredServices.add(DiscoveredService(
name: serviceName,
methods: const [],
));
}
}
return discoveredServices;
}
/// Discovers services matching a pattern.
///
/// Filters discovered services by name containing the [pattern].
/// Case-insensitive matching.
Future<List<DiscoveredService>> discoverServicesMatching(String pattern) async {
final services = await discoverAllServices();
final lowerPattern = pattern.toLowerCase();
return services
.where((s) => s.name.toLowerCase().contains(lowerPattern))
.toList();
}
Stream<ServerReflectionRequest> _createRequestStream(
List<ServerReflectionRequest> requests,
) async* {
for (final request in requests) {
yield request;
}
}
/// Closes the gRPC channel connection.
///
/// Should be called when done with discovery to release resources.
Future<void> close() async {
if (_isInitialized) {
await _channel.shutdown();
_isInitialized = false;
}
}
}
/// Utility function to discover and print gRPC services.
///
/// This is a convenience function for development and debugging.
/// Connects to the server specified in [config], discovers all services,
/// and prints them to the console.
///
/// Returns a map of service names to their discovered service details.
Future<Map<String, DiscoveredService>> discoverAndPrintServices({
GrpcConfig config = GrpcConfig.development,
}) async {
final discovery = GrpcDiscoveryClient(config: config);
try {
final services = await discovery.discoverAllServices();
final Map<String, DiscoveredService> result = {};
for (final service in services) {
result[service.name] = service;
}
return result;
} finally {
await discovery.close();
}
}

View File

@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:google_navigation_flutter/google_navigation_flutter.dart'; import 'package:google_navigation_flutter/google_navigation_flutter.dart';
import '../models/delivery.dart'; import '../models/delivery.dart';
import '../theme/color_system.dart'; import '../theme/color_system.dart';
import '../utils/breakpoints.dart';
import '../utils/toast_helper.dart'; import '../utils/toast_helper.dart';
/// Enhanced dark-mode aware map component with custom styling /// Enhanced dark-mode aware map component with custom styling
@ -37,21 +36,11 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
Brightness? _lastBrightness; Brightness? _lastBrightness;
bool _isMapViewReady = false; bool _isMapViewReady = false;
bool _isDisposed = false; bool _isDisposed = false;
bool _isAudioGuidanceEnabled = false; // Audio guidance off by default
bool _pendingNavigationStart = false; // User requested navigation before map was ready
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Set destination if delivery is already selected when widget is created
_updateDestination();
_initializeNavigation(); _initializeNavigation();
// Ensure state is synced after a brief delay to allow map to fully load
Future.delayed(const Duration(milliseconds: 500), () {
if (mounted && !_isDisposed) {
_syncNavigationState();
}
});
} }
@override @override
@ -66,8 +55,6 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (oldWidget.selectedDelivery != widget.selectedDelivery) { if (oldWidget.selectedDelivery != widget.selectedDelivery) {
_updateDestination(); _updateDestination();
// Sync navigation state with actual SDK state
_syncNavigationState();
// If navigation was active, restart navigation to new delivery // If navigation was active, restart navigation to new delivery
if (_isNavigating && if (_isNavigating &&
@ -108,48 +95,13 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
} }
} }
/// Sync local navigation state with actual SDK navigation state
Future<void> _syncNavigationState() async {
try {
final bool isActuallyNavigating = await GoogleMapsNavigator.isGuidanceRunning();
if (mounted && !_isDisposed) {
if (_isNavigating != isActuallyNavigating) {
debugPrint('State mismatch detected! Local: $_isNavigating, SDK: $isActuallyNavigating');
setState(() {
_isNavigating = isActuallyNavigating;
});
debugPrint('Navigation state synced to: $_isNavigating');
} else {
debugPrint('Navigation state already in sync: $_isNavigating');
}
}
} catch (e) {
debugPrint('Failed to sync navigation state: $e');
}
}
Future<void> _initializeNavigation() async { Future<void> _initializeNavigation() async {
if (_isInitializing || _isSessionInitialized) { if (_isInitializing || _isSessionInitialized) return;
debugPrint('Skipping initialization: initializing=$_isInitializing, initialized=$_isSessionInitialized');
return;
}
debugPrint('Initializing navigation session...');
setState(() { setState(() {
_isInitializing = true; _isInitializing = true;
}); });
// Safety timeout to reset flag if initialization takes too long
Future.delayed(const Duration(seconds: 15), () {
if (mounted && _isInitializing && !_isSessionInitialized) {
debugPrint('Initialization timeout - resetting flag');
setState(() {
_isInitializing = false;
});
}
});
try { try {
final termsAccepted = await GoogleMapsNavigator.areTermsAccepted(); final termsAccepted = await GoogleMapsNavigator.areTermsAccepted();
if (!termsAccepted) { if (!termsAccepted) {
@ -196,25 +148,15 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
if (widget.selectedDelivery != null) { if (widget.selectedDelivery != null) {
final address = widget.selectedDelivery!.deliveryAddress; final address = widget.selectedDelivery!.deliveryAddress;
if (address?.latitude != null && address?.longitude != null) { if (address?.latitude != null && address?.longitude != null) {
final lat = address!.latitude!;
final lon = address.longitude!;
setState(() { setState(() {
_destinationLocation = LatLng( _destinationLocation = LatLng(
latitude: lat, latitude: address!.latitude!,
longitude: lon, longitude: address.longitude!,
); );
}); });
debugPrint('Destination set to: $lat, $lon for delivery: ${widget.selectedDelivery!.name}');
// Just store the destination, don't move camera // Just store the destination, don't move camera
// The navigation will handle camera positioning // The navigation will handle camera positioning
} else {
debugPrint('Delivery ${widget.selectedDelivery!.name} has no valid address');
} }
} else {
debugPrint('No delivery selected, clearing destination');
setState(() {
_destinationLocation = null;
});
} }
} }
@ -225,15 +167,6 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
try { try {
if (!mounted || _isDisposed) return; if (!mounted || _isDisposed) return;
// Get current theme brightness
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
// Force night mode based on theme
await _navigationController!.setForceNightMode(
isDarkMode ? NavigationForceNightMode.forceNight : NavigationForceNightMode.forceDay,
);
debugPrint('Night mode set to: ${isDarkMode ? 'night' : 'day'}');
// Force dark mode map style using Google's standard dark theme // Force dark mode map style using Google's standard dark theme
const String darkMapStyle = ''' const String darkMapStyle = '''
[ [
@ -336,51 +269,8 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
} }
} }
Future<void> _toggleAudioGuidance() async {
if (_isDisposed) return;
try {
final newState = !_isAudioGuidanceEnabled;
await GoogleMapsNavigator.setAudioGuidance(
NavigationAudioGuidanceSettings(
guidanceType: newState
? NavigationAudioGuidanceType.alertsAndGuidance
: NavigationAudioGuidanceType.silent,
),
);
if (mounted) {
setState(() {
_isAudioGuidanceEnabled = newState;
});
debugPrint('Audio guidance ${newState ? 'enabled' : 'disabled'}');
}
} catch (e) {
debugPrint('Error toggling audio guidance: $e');
}
}
Future<void> _startNavigation() async { Future<void> _startNavigation() async {
if (_destinationLocation == null) { if (_destinationLocation == null) return;
debugPrint('Cannot start navigation: no destination set');
return;
}
debugPrint('Starting navigation to: $_destinationLocation');
// Check if map is ready before attempting to start
if (!_isMapViewReady) {
debugPrint('Map not ready yet - navigation will start automatically when ready');
if (mounted) {
setState(() {
_pendingNavigationStart = true;
_isStartingNavigation = true;
_loadingMessage = 'Waiting for map to load...';
});
ToastHelper.showInfo(context, 'Map is loading. Navigation will start automatically...');
}
return;
}
// Show loading indicator // Show loading indicator
if (mounted) { if (mounted) {
@ -390,19 +280,6 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
}); });
} }
// Safety timeout to reset flag if navigation start takes too long
Future.delayed(const Duration(seconds: 10), () {
if (mounted && _isStartingNavigation) {
debugPrint('Navigation start timeout - resetting flag');
setState(() {
_isStartingNavigation = false;
});
ToastHelper.showError(context, 'Navigation start timed out. Please try again.');
}
});
bool navigationStarted = false;
try { try {
// Ensure session is initialized before starting navigation // Ensure session is initialized before starting navigation
if (!_isSessionInitialized && !_isInitializing) { if (!_isSessionInitialized && !_isInitializing) {
@ -419,6 +296,9 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
if (!_isSessionInitialized) { if (!_isSessionInitialized) {
if (mounted) { if (mounted) {
setState(() {
_isStartingNavigation = false;
});
ToastHelper.showError(context, 'Navigation initialization timeout'); ToastHelper.showError(context, 'Navigation initialization timeout');
} }
return; return;
@ -484,7 +364,6 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
setState(() { setState(() {
_isNavigating = true; _isNavigating = true;
_isStartingNavigation = false; _isStartingNavigation = false;
_pendingNavigationStart = false; // Clear pending flag on success
}); });
} }
} catch (e) { } catch (e) {
@ -495,7 +374,6 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
if (mounted) { if (mounted) {
setState(() { setState(() {
_isStartingNavigation = false; _isStartingNavigation = false;
_pendingNavigationStart = false; // Clear pending flag on error
}); });
ToastHelper.showError(context, 'Navigation error: $errorMessage', duration: const Duration(seconds: 4)); ToastHelper.showError(context, 'Navigation error: $errorMessage', duration: const Duration(seconds: 4));
@ -518,28 +396,14 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
await GoogleMapsNavigator.stopGuidance(); await GoogleMapsNavigator.stopGuidance();
await GoogleMapsNavigator.clearDestinations(); await GoogleMapsNavigator.clearDestinations();
// Wait a moment for the SDK to fully stop
await Future.delayed(const Duration(milliseconds: 200));
// Verify navigation actually stopped by checking SDK state
final bool isStillRunning = await GoogleMapsNavigator.isGuidanceRunning();
if (mounted) { if (mounted) {
setState(() { setState(() {
_isNavigating = isStillRunning; _isNavigating = false;
_pendingNavigationStart = false; // Clear pending flag when stopping
}); });
debugPrint('Navigation stopped, state synced: $_isNavigating');
} }
} catch (e) { } catch (e) {
if (mounted) { if (mounted) {
debugPrint('Navigation stop error: $e'); debugPrint('Navigation stop error: $e');
setState(() {
_pendingNavigationStart = false; // Clear pending flag on error
});
// Even on error, try to sync state
await _syncNavigationState();
} }
} }
} }
@ -565,17 +429,12 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Driver's current location (defaults to Trois-Rivières if not available) // Driver's current location (defaults to Montreal if not available)
final initialPosition = const LatLng(latitude: 46.33857534324389, longitude: -72.60787418369715); final initialPosition = const LatLng(latitude: 45.5017, longitude: -73.5673);
// Get safe area insets to avoid rounded corners and notches
final bottomSafeArea = MediaQuery.of(context).padding.bottom;
// Calculate dynamic padding for bottom button bar // Calculate dynamic padding for bottom button bar
// Must account for full button container height to prevent map showing underneath
// Button container height = top padding (8) + button height (~44) + bottom padding (bottomSafeArea + 8)
final topPadding = 0.0; final topPadding = 0.0;
final bottomPadding = 100.0; // Full height of button container to properly cut off map final bottomPadding = 60.0;
return Stack( return Stack(
children: [ children: [
@ -618,34 +477,11 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
if (!mounted || _isDisposed) return; if (!mounted || _isDisposed) return;
await controller.setNavigationFooterEnabled(true); await controller.setNavigationFooterEnabled(true);
if (!mounted || _isDisposed) return; if (!mounted || _isDisposed) return;
// Disable navigation trip progress bar await controller.setNavigationTripProgressBarEnabled(true);
await controller.setNavigationTripProgressBarEnabled(false);
if (!mounted || _isDisposed) return;
// Enable recenter button
await controller.setRecenterButtonEnabled(true);
if (!mounted || _isDisposed) return;
// Enable speed limit icon
await controller.setSpeedLimitIconEnabled(true);
if (!mounted || _isDisposed) return;
// Enable traffic incident cards
await controller.setTrafficIncidentCardsEnabled(true);
if (!mounted || _isDisposed) return;
// Disable traffic prompts
await controller.setTrafficPromptsEnabled(false);
if (!mounted || _isDisposed) return; if (!mounted || _isDisposed) return;
// Disable report incident button // Disable report incident button
await controller.setReportIncidentButtonEnabled(false); await controller.setReportIncidentButtonEnabled(false);
if (!mounted || _isDisposed) return; debugPrint('Navigation UI elements enabled');
// Enable speedometer
await controller.setSpeedometerEnabled(true);
if (!mounted || _isDisposed) return;
// Set audio guidance to silent by default
await GoogleMapsNavigator.setAudioGuidance(
NavigationAudioGuidanceSettings(
guidanceType: NavigationAudioGuidanceType.silent,
),
);
debugPrint('Navigation UI elements configured');
// Configure map settings to reduce GPU load for devices with limited graphics capabilities // Configure map settings to reduce GPU load for devices with limited graphics capabilities
if (!mounted || _isDisposed) return; if (!mounted || _isDisposed) return;
@ -664,42 +500,40 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
if (!mounted || _isDisposed) return; if (!mounted || _isDisposed) return;
await _applyDarkModeStyle(); await _applyDarkModeStyle();
// Immediately follow user location on map initialization // Wrap camera animation in try-catch to handle "No valid view found" errors
// This can happen on Android when the view isn't fully ready
try { try {
if (mounted && _navigationController != null && _isMapViewReady && !_isDisposed) { if (mounted && _navigationController != null && _isMapViewReady && !_isDisposed) {
// Start following user location immediately await controller.animateCamera(
await _recenterMap(); CameraUpdate.newLatLngZoom(initialPosition, 12),
debugPrint('Map initialized following user location'); );
// Sync navigation state to ensure button reflects actual navigation state
await _syncNavigationState();
// Auto-start navigation if user requested it before map was ready // Auto-recenter to current location after initial setup
if (_pendingNavigationStart && !_isNavigating && !_isDisposed && mounted) { await Future.delayed(const Duration(milliseconds: 500));
debugPrint('Auto-starting navigation as requested by user'); if (mounted && _navigationController != null && !_isDisposed) {
_pendingNavigationStart = false; await _recenterMap();
await _startNavigation(); debugPrint('Auto-recentered map to current location on initialization');
} }
} }
} catch (e) { } catch (e) {
debugPrint('Follow location error (view may not be ready): $e'); debugPrint('Camera animation error (view may not be ready): $e');
if (_isDisposed || !mounted) return; if (_isDisposed || !mounted) return;
// Retry once after a longer delay // Retry once after a longer delay
await Future.delayed(const Duration(milliseconds: 1500)); await Future.delayed(const Duration(milliseconds: 1500));
if (mounted && _navigationController != null && _isMapViewReady && !_isDisposed) { if (mounted && _navigationController != null && _isMapViewReady && !_isDisposed) {
try { try {
await _recenterMap(); await controller.animateCamera(
debugPrint('Map initialized following user location (retry)'); CameraUpdate.newLatLngZoom(initialPosition, 12),
// Sync navigation state to ensure button reflects actual navigation state );
await _syncNavigationState();
// Auto-start navigation if user requested it before map was ready // Auto-recenter to current location after retry
if (_pendingNavigationStart && !_isNavigating && !_isDisposed && mounted) { await Future.delayed(const Duration(milliseconds: 500));
debugPrint('Auto-starting navigation as requested by user (after retry)'); if (mounted && _navigationController != null && !_isDisposed) {
_pendingNavigationStart = false; await _recenterMap();
await _startNavigation(); debugPrint('Auto-recentered map to current location on initialization (retry)');
} }
} catch (e2) { } catch (e2) {
debugPrint('Follow location retry failed: $e2'); debugPrint('Camera animation retry failed: $e2');
} }
} }
} }
@ -726,108 +560,63 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
), ),
], ],
), ),
padding: EdgeInsets.only( padding: const EdgeInsets.symmetric(
left: 12, horizontal: 12,
right: 12, vertical: 8,
top: 8,
// Add safe area padding plus extra margin to avoid rounded corners
bottom: bottomSafeArea > 0 ? bottomSafeArea + 8 : 16,
), ),
child: Builder( child: Row(
builder: (context) { children: [
final isMobile = context.isMobile; // Start button
final showButtonLabels = !isMobile; Expanded(
child: _buildBottomActionButton(
return Row( label: _isNavigating ? 'Stop' : 'Start',
children: [ icon: _isNavigating ? Icons.stop : Icons.navigation,
// Start button onPressed: _isStartingNavigation || _isInitializing || (widget.selectedDelivery == null && !_isNavigating)
Expanded( ? null
child: _buildBottomActionButton( : (_isNavigating ? _stopNavigation : _startNavigation),
label: _isNavigating ? 'Stop' : 'Start', isDanger: _isNavigating,
icon: _isNavigating ? Icons.stop : Icons.navigation, ),
onPressed: _isStartingNavigation || _isInitializing || (!_isMapViewReady && !_isNavigating) || (widget.selectedDelivery == null && !_isNavigating) ),
? null const SizedBox(width: 8),
: (_isNavigating ? _stopNavigation : _startNavigation), // Photo button (disabled when no delivery selected or warehouse delivery)
isDanger: _isNavigating, Expanded(
showLabel: showButtonLabels, child: _buildBottomActionButton(
), label: 'Photo',
), icon: Icons.camera_alt,
const SizedBox(width: 8), onPressed: widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery
// Photo button (disabled when no delivery selected or warehouse delivery) ? () => widget.onAction?.call('photo')
Expanded( : null,
child: _buildBottomActionButton( ),
label: 'Photo', ),
icon: Icons.camera_alt, const SizedBox(width: 8),
onPressed: widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery // Note button (only enabled if delivery has notes and not warehouse)
? () => widget.onAction?.call('photo') Expanded(
: null, child: _buildBottomActionButton(
showLabel: showButtonLabels, label: 'Note',
), icon: Icons.note_add,
), onPressed: _hasNotes() && widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery
const SizedBox(width: 8), ? () => widget.onAction?.call('note')
// Note button (only enabled if delivery has notes and not warehouse) : null,
Expanded( ),
child: _buildBottomActionButton( ),
label: 'Note', const SizedBox(width: 8),
icon: Icons.note_add, // Completed button (disabled for warehouse delivery)
onPressed: _hasNotes() && widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery Expanded(
? () => widget.onAction?.call('note') child: _buildBottomActionButton(
: null, label: widget.selectedDelivery?.delivered == true ? 'Undo' : 'Completed',
showLabel: showButtonLabels, icon: widget.selectedDelivery?.delivered == true ? Icons.undo : Icons.check_circle,
), onPressed: widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery
), ? () => widget.onAction?.call(
const SizedBox(width: 8), widget.selectedDelivery!.delivered ? 'uncomplete' : 'complete',
// Completed button (disabled for warehouse delivery) )
Expanded( : null,
child: _buildBottomActionButton( isPrimary: widget.selectedDelivery != null && !widget.selectedDelivery!.delivered && !widget.selectedDelivery!.isWarehouseDelivery,
label: widget.selectedDelivery?.delivered == true ? 'Undo' : 'Completed', ),
icon: widget.selectedDelivery?.delivered == true ? Icons.undo : Icons.check_circle,
onPressed: widget.selectedDelivery != null && !widget.selectedDelivery!.isWarehouseDelivery
? () => widget.onAction?.call(
widget.selectedDelivery!.delivered ? 'uncomplete' : 'complete',
)
: null,
isPrimary: widget.selectedDelivery != null && !widget.selectedDelivery!.delivered && !widget.selectedDelivery!.isWarehouseDelivery,
showLabel: showButtonLabels,
),
),
],
);
},
),
),
),
// Audio guidance toggle button - positioned below green navigation card
Positioned(
top: topPadding + 48,
right: 16,
child: Material(
color: Colors.transparent,
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(28),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.2),
blurRadius: 8,
offset: const Offset(0, 2),
), ),
], ],
), ),
child: IconButton(
icon: Icon(
_isAudioGuidanceEnabled ? Icons.volume_up : Icons.volume_off,
color: _isAudioGuidanceEnabled
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.onSurfaceVariant,
),
onPressed: _toggleAudioGuidance,
tooltip: _isAudioGuidanceEnabled ? 'Mute navigation' : 'Unmute navigation',
),
), ),
), ),
),
// Loading overlay during navigation initialization and start // Loading overlay during navigation initialization and start
if (_isStartingNavigation || _isInitializing) if (_isStartingNavigation || _isInitializing)
Positioned.fill( Positioned.fill(
@ -895,7 +684,6 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
required VoidCallback? onPressed, required VoidCallback? onPressed,
bool isPrimary = false, bool isPrimary = false,
bool isDanger = false, bool isDanger = false,
bool showLabel = true,
}) { }) {
Color backgroundColor; Color backgroundColor;
Color textColor = Colors.white; Color textColor = Colors.white;
@ -921,9 +709,9 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
onTap: onPressed, onTap: onPressed,
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
child: Padding( child: Padding(
padding: EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: showLabel ? 8 : 12, horizontal: 8,
vertical: showLabel ? 10 : 12, vertical: 10,
), ),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -932,19 +720,17 @@ class _DarkModeMapComponentState extends State<DarkModeMapComponent> {
Icon( Icon(
icon, icon,
color: textColor, color: textColor,
size: showLabel ? 18 : 20, size: 18,
), ),
if (showLabel) ...[ const SizedBox(width: 6),
const SizedBox(width: 6), Text(
Text( label,
label, style: TextStyle(
style: TextStyle( color: textColor,
color: textColor, fontWeight: FontWeight.w600,
fontWeight: FontWeight.w600, fontSize: 14,
fontSize: 14,
),
), ),
], ),
], ],
), ),
), ),

View File

@ -125,7 +125,7 @@ class _DeliveryListItemState extends State<DeliveryListItem>
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
border: widget.isSelected border: widget.isSelected
? Border.all( ? Border.all(
color: Theme.of(context).colorScheme.surface, color: Colors.white,
width: 3, width: 3,
) )
: null, : null,
@ -134,7 +134,7 @@ class _DeliveryListItemState extends State<DeliveryListItem>
BoxShadow( BoxShadow(
color: widget.isSelected color: widget.isSelected
? statusColor.withValues(alpha: 0.5) ? statusColor.withValues(alpha: 0.5)
: Theme.of(context).colorScheme.scrim.withValues( : Colors.black.withValues(
alpha: isDark ? 0.3 : 0.15, alpha: isDark ? 0.3 : 0.15,
), ),
blurRadius: widget.isSelected ? 12 : 8, blurRadius: widget.isSelected ? 12 : 8,
@ -146,15 +146,15 @@ class _DeliveryListItemState extends State<DeliveryListItem>
), ),
child: Center( child: Center(
child: widget.delivery.isWarehouseDelivery child: widget.delivery.isWarehouseDelivery
? Icon( ? const Icon(
Icons.warehouse, Icons.warehouse,
color: Theme.of(context).colorScheme.onPrimary, color: Colors.white,
size: 32, size: 32,
) )
: Text( : Text(
'${widget.delivery.deliveryIndex + 1}', '${widget.delivery.deliveryIndex + 1}',
style: TextStyle( style: const TextStyle(
color: Theme.of(context).colorScheme.onPrimary, color: Colors.white,
fontSize: 26, fontSize: 26,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
), ),
@ -178,10 +178,10 @@ class _DeliveryListItemState extends State<DeliveryListItem>
), ),
child: Transform.rotate( child: Transform.rotate(
angle: 4.71239, // 270 degrees in radians (3*pi/2) angle: 4.71239, // 270 degrees in radians (3*pi/2)
child: Icon( child: const Icon(
Icons.note, Icons.note,
size: 12, size: 12,
color: Theme.of(context).colorScheme.onPrimary, color: Colors.white,
), ),
), ),
), ),
@ -232,7 +232,7 @@ class _DeliveryListItemState extends State<DeliveryListItem>
boxShadow: (_isHovered || widget.isSelected) && !widget.delivery.delivered boxShadow: (_isHovered || widget.isSelected) && !widget.delivery.delivered
? [ ? [
BoxShadow( BoxShadow(
color: Theme.of(context).colorScheme.scrim.withValues( color: Colors.black.withValues(
alpha: isDark ? 0.3 : 0.08, alpha: isDark ? 0.3 : 0.08,
), ),
blurRadius: 8, blurRadius: 8,
@ -261,15 +261,15 @@ class _DeliveryListItemState extends State<DeliveryListItem>
), ),
child: Center( child: Center(
child: widget.delivery.isWarehouseDelivery child: widget.delivery.isWarehouseDelivery
? Icon( ? const Icon(
Icons.warehouse, Icons.warehouse,
color: Theme.of(context).colorScheme.onPrimary, color: Colors.white,
size: 24, size: 24,
) )
: Text( : Text(
'${widget.delivery.deliveryIndex + 1}', '${widget.delivery.deliveryIndex + 1}',
style: TextStyle( style: const TextStyle(
color: Theme.of(context).colorScheme.onPrimary, color: Colors.white,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
), ),
@ -343,7 +343,7 @@ class _DeliveryListItemState extends State<DeliveryListItem>
), ),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Theme.of(context).colorScheme.scrim.withValues(alpha: 0.2), color: Colors.black.withValues(alpha: 0.2),
blurRadius: 4, blurRadius: 4,
offset: const Offset(0, 2), offset: const Offset(0, 2),
), ),
@ -351,10 +351,10 @@ class _DeliveryListItemState extends State<DeliveryListItem>
), ),
child: Transform.rotate( child: Transform.rotate(
angle: 4.71239, // 270 degrees in radians (3*pi/2) angle: 4.71239, // 270 degrees in radians (3*pi/2)
child: Icon( child: const Icon(
Icons.note, Icons.note,
size: 14, size: 14,
color: Theme.of(context).colorScheme.onPrimary, color: Colors.white,
), ),
), ),
), ),

View File

@ -50,21 +50,21 @@ class _GlassmorphicRouteCardState extends State<GlassmorphicRouteCard>
// Red to orange (0-30%) // Red to orange (0-30%)
return Color.lerp( return Color.lerp(
SvrntyColors.crimsonRed, SvrntyColors.crimsonRed,
SvrntyColors.progressLow, const Color(0xFFFF9800),
(progress / 0.3), (progress / 0.3),
)!; )!;
} else if (progress < 0.7) { } else if (progress < 0.7) {
// Orange to yellow (30-70%) // Orange to yellow (30-70%)
return Color.lerp( return Color.lerp(
SvrntyColors.progressLow, const Color(0xFFFF9800),
SvrntyColors.progressMedium, const Color(0xFFFFC107),
((progress - 0.3) / 0.4), ((progress - 0.3) / 0.4),
)!; )!;
} else { } else {
// Yellow to green (70-100%) // Yellow to green (70-100%)
return Color.lerp( return Color.lerp(
SvrntyColors.progressMedium, const Color(0xFFFFC107),
SvrntyColors.progressHigh, const Color(0xFF4CAF50),
((progress - 0.7) / 0.3), ((progress - 0.7) / 0.3),
)!; )!;
} }

View File

@ -1,237 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/delivery.dart';
import '../providers/providers.dart';
import '../l10n/app_localizations.dart';
import 'dark_mode_map.dart';
import 'unified_delivery_list.dart';
/// Mobile-optimized map layout with toggleable deliveries list overlay
///
/// This component provides a full-screen map view for mobile devices with
/// a bottom overlay that can be toggled to show the deliveries list.
class MobileMapWithOverlay extends ConsumerStatefulWidget {
final List<Delivery> deliveries;
final Delivery? selectedDelivery;
final ValueChanged<Delivery?> onDeliverySelected;
final Function(Delivery, String) onDeliveryAction;
const MobileMapWithOverlay({
super.key,
required this.deliveries,
this.selectedDelivery,
required this.onDeliverySelected,
required this.onDeliveryAction,
});
@override
ConsumerState<MobileMapWithOverlay> createState() => _MobileMapWithOverlayState();
}
class _MobileMapWithOverlayState extends ConsumerState<MobileMapWithOverlay>
with SingleTickerProviderStateMixin {
late ScrollController _listScrollController;
late AnimationController _animationController;
late Animation<double> _slideAnimation;
@override
void initState() {
super.initState();
_listScrollController = ScrollController();
_animationController = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
_slideAnimation = CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOut,
);
}
@override
void dispose() {
_listScrollController.dispose();
_animationController.dispose();
super.dispose();
}
void _toggleList() {
final isOpen = ref.read(mobileDeliveriesListOpenProvider);
if (isOpen) {
_animationController.reverse();
} else {
_animationController.forward();
}
ref.read(mobileDeliveriesListOpenProvider.notifier).toggle();
}
int get _completedCount {
return widget.deliveries.where((d) => d.delivered).length;
}
int get _totalCount {
// Exclude warehouse delivery from total count
return widget.deliveries.where((d) => !d.isWarehouseDelivery).length;
}
@override
Widget build(BuildContext context) {
final isListOpen = ref.watch(mobileDeliveriesListOpenProvider);
final l10n = AppLocalizations.of(context);
final screenHeight = MediaQuery.of(context).size.height;
final overlayHeight = screenHeight * 0.7;
return Stack(
children: [
// Full-screen map
Positioned.fill(
child: DarkModeMapComponent(
deliveries: widget.deliveries,
selectedDelivery: widget.selectedDelivery,
onDeliverySelected: widget.onDeliverySelected,
onAction: (action) {
if (widget.selectedDelivery != null) {
widget.onDeliveryAction(widget.selectedDelivery!, action);
}
},
),
),
// Dimmed overlay when list is open
if (isListOpen)
Positioned.fill(
child: GestureDetector(
onTap: _toggleList,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 300),
opacity: isListOpen ? 0.3 : 0.0,
child: Container(
color: Colors.black,
),
),
),
),
// Animated deliveries overlay
AnimatedBuilder(
animation: _slideAnimation,
builder: (context, child) {
return Positioned(
left: 0,
right: 0,
bottom: -overlayHeight * (1 - _slideAnimation.value),
height: overlayHeight,
child: GestureDetector(
onVerticalDragEnd: (details) {
// Swipe down to close
if (details.primaryVelocity != null && details.primaryVelocity! > 500) {
_toggleList();
}
},
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(16),
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.2),
blurRadius: 10,
offset: const Offset(0, -2),
),
],
),
child: Column(
children: [
// Drag handle
Container(
height: 32,
alignment: Alignment.center,
child: Container(
height: 4,
width: 40,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(2),
),
),
),
// Header with close button
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Theme.of(context).dividerColor,
width: 1,
),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
l10n.deliveries,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w700,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: _toggleList,
tooltip: l10n.close,
),
],
),
),
// Deliveries list
Expanded(
child: UnifiedDeliveryListView(
deliveries: widget.deliveries,
selectedDelivery: widget.selectedDelivery,
scrollController: _listScrollController,
onDeliverySelected: (delivery) {
widget.onDeliverySelected(delivery);
// Auto-close the overlay after selection for better mobile UX
_toggleList();
},
onItemAction: (delivery, action) {
widget.onDeliveryAction(delivery, action);
},
isCollapsed: false,
),
),
],
),
),
),
);
},
),
// Floating toggle button (FAB) - only show when list is closed
if (!isListOpen)
Positioned(
bottom: 110, // Slightly lowered for better positioning
right: 16,
child: FloatingActionButton.extended(
heroTag: 'mobile_deliveries_toggle_fab',
onPressed: _toggleList,
icon: const Icon(Icons.list),
label: Text(
'$_completedCount/$_totalCount',
style: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 15,
),
),
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Colors.white,
elevation: 4,
),
),
],
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from cqrs_services.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
/// InvoiceReportFilter enum
class InvoiceReportFilter extends $pb.ProtobufEnum {
static const InvoiceReportFilter INVOICE_REPORT_FILTER_DELIVERY =
InvoiceReportFilter._(
0, _omitEnumNames ? '' : 'INVOICE_REPORT_FILTER_DELIVERY');
static const InvoiceReportFilter INVOICE_REPORT_FILTER_OTHERS =
InvoiceReportFilter._(
1, _omitEnumNames ? '' : 'INVOICE_REPORT_FILTER_OTHERS');
static const InvoiceReportFilter INVOICE_REPORT_FILTER_ALL =
InvoiceReportFilter._(
2, _omitEnumNames ? '' : 'INVOICE_REPORT_FILTER_ALL');
static const $core.List<InvoiceReportFilter> values = <InvoiceReportFilter>[
INVOICE_REPORT_FILTER_DELIVERY,
INVOICE_REPORT_FILTER_OTHERS,
INVOICE_REPORT_FILTER_ALL,
];
static final $core.List<InvoiceReportFilter?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 2);
static InvoiceReportFilter? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const InvoiceReportFilter._(super.value, super.name);
}
/// UserRole enum
class UserRole extends $pb.ProtobufEnum {
static const UserRole USER_ROLE_OWNER =
UserRole._(0, _omitEnumNames ? '' : 'USER_ROLE_OWNER');
static const UserRole USER_ROLE_ADMIN =
UserRole._(1, _omitEnumNames ? '' : 'USER_ROLE_ADMIN');
static const UserRole USER_ROLE_DELIVERYMAN =
UserRole._(2, _omitEnumNames ? '' : 'USER_ROLE_DELIVERYMAN');
static const $core.List<UserRole> values = <UserRole>[
USER_ROLE_OWNER,
USER_ROLE_ADMIN,
USER_ROLE_DELIVERYMAN,
];
static final $core.List<UserRole?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 2);
static UserRole? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const UserRole._(super.value, super.name);
}
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -318,7 +318,6 @@ class _DeliveriesPageState extends ConsumerState<DeliveriesPage> {
endpoint: 'completeDelivery', endpoint: 'completeDelivery',
command: CompleteDeliveryCommand( command: CompleteDeliveryCommand(
deliveryId: delivery.id, deliveryId: delivery.id,
deliveredAt: DateTime.now().toUtc().toIso8601String(),
), ),
); );
result.when( result.when(

View File

@ -6,7 +6,9 @@ import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../models/delivery.dart'; import '../models/delivery.dart';
import '../models/delivery_route.dart'; import '../models/delivery_route.dart';
import '../models/delivery_commands.dart';
import '../providers/providers.dart'; import '../providers/providers.dart';
import '../api/client.dart';
import '../utils/toast_helper.dart'; import '../utils/toast_helper.dart';
import '../api/openapi_config.dart'; import '../api/openapi_config.dart';
import '../utils/http_client_factory.dart'; import '../utils/http_client_factory.dart';
@ -15,9 +17,7 @@ import '../components/dark_mode_map.dart';
import '../components/loading_dialog.dart'; import '../components/loading_dialog.dart';
import '../components/notes_dialog.dart'; import '../components/notes_dialog.dart';
import '../components/photo_capture_dialog.dart'; import '../components/photo_capture_dialog.dart';
import '../components/mobile_map_with_overlay.dart';
import '../services/location_permission_service.dart'; import '../services/location_permission_service.dart';
import '../utils/breakpoints.dart';
import 'deliveries_page.dart'; import 'deliveries_page.dart';
import 'settings_page.dart'; import 'settings_page.dart';
@ -74,7 +74,7 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
void _backToRoutes() { void _backToRoutes() {
setState(() { setState(() {
_selectedRoute = null; _selectedRoute = null;
// Keep _selectedDelivery to preserve selection when returning to map _selectedDelivery = null;
}); });
} }
@ -96,8 +96,11 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
return; return;
} }
// Use gRPC client for commands // Create API client with auth service for automatic token refresh
final grpcClient = ref.read(grpcClientProvider); final authClient = CqrsApiClient(
config: ApiClientConfig.development,
authService: authService,
);
switch (action) { switch (action) {
case 'complete': case 'complete':
@ -105,8 +108,11 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
LoadingDialog.show(context, message: l10n.completingDelivery); LoadingDialog.show(context, message: l10n.completingDelivery);
} }
final result = await grpcClient.completeDelivery( final result = await authClient.executeCommand(
deliveryId: delivery.id, endpoint: 'completeDelivery',
command: CompleteDeliveryCommand(
deliveryId: delivery.id,
),
); );
result.when( result.when(
success: (_) async { success: (_) async {
@ -115,13 +121,17 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
} }
if (mounted) { if (mounted) {
// Refresh providers to force fresh data fetch // Invalidate both providers to force refresh
await ref.refresh(deliveriesProvider(routeFragmentId).future); ref.invalidate(deliveriesProvider(routeFragmentId));
await ref.refresh(allDeliveriesProvider.future); ref.invalidate(allDeliveriesProvider);
ref.invalidate(deliveryRoutesProvider);
// Wait for providers to refresh
await Future.delayed(const Duration(milliseconds: 500));
if (mounted) { if (mounted) {
// Get refreshed deliveries // Get refreshed deliveries
final allDeliveries = ref.read(allDeliveriesProvider).value ?? []; final allDeliveries = await ref.read(allDeliveriesProvider.future);
final routeDeliveries = allDeliveries final routeDeliveries = allDeliveries
.where((d) => d.routeFragmentId == routeFragmentId) .where((d) => d.routeFragmentId == routeFragmentId)
.toList(); .toList();
@ -160,17 +170,12 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
debugPrint('Complete delivery failed - Type: ${error.type}, Message: ${error.message}'); debugPrint('Complete delivery failed - Type: ${error.type}, Message: ${error.message}');
debugPrint('Error details: ${error.details}'); debugPrint('Error details: ${error.details}');
debugPrint('Status code: ${error.statusCode}');
if (mounted) { if (mounted) {
String errorMessage = l10n.error(error.message); String errorMessage = l10n.error(error.message);
if (error.statusCode == 500) { if (error.statusCode == 500) {
errorMessage = l10n.serverError; errorMessage = l10n.serverError;
} else if (error.statusCode == 401) {
errorMessage = 'Unauthorized: You may not have permission to complete this delivery. Please check with your administrator.';
} else if (error.details != null) {
errorMessage = 'Error: ${error.details}';
} }
ToastHelper.showError(context, errorMessage, duration: const Duration(seconds: 5)); ToastHelper.showError(context, errorMessage);
} }
}, },
); );
@ -181,8 +186,9 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
LoadingDialog.show(context, message: l10n.markingAsUncompleted); LoadingDialog.show(context, message: l10n.markingAsUncompleted);
} }
final uncompleteResult = await grpcClient.markDeliveryAsUncompleted( final uncompleteResult = await authClient.executeCommand(
deliveryId: delivery.id, endpoint: 'markDeliveryAsUncompleted',
command: MarkDeliveryAsUncompletedCommand(deliveryId: delivery.id),
); );
uncompleteResult.when( uncompleteResult.when(
success: (_) async { success: (_) async {
@ -191,13 +197,17 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
} }
if (mounted) { if (mounted) {
// Refresh providers to force fresh data fetch // Invalidate both providers to force refresh
await ref.refresh(deliveriesProvider(routeFragmentId).future); ref.invalidate(deliveriesProvider(routeFragmentId));
await ref.refresh(allDeliveriesProvider.future); ref.invalidate(allDeliveriesProvider);
ref.invalidate(deliveryRoutesProvider);
// Wait for providers to refresh
await Future.delayed(const Duration(milliseconds: 500));
if (mounted) { if (mounted) {
// Get refreshed deliveries // Get refreshed deliveries
final allDeliveries = ref.read(allDeliveriesProvider).value ?? []; final allDeliveries = await ref.read(allDeliveriesProvider.future);
final updatedDelivery = allDeliveries.firstWhere( final updatedDelivery = allDeliveries.firstWhere(
(d) => d.id == delivery.id, (d) => d.id == delivery.id,
orElse: () => delivery, orElse: () => delivery,
@ -287,12 +297,12 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
try { try {
final Uri uploadUrl = Uri.parse( final Uri uploadUrl = Uri.parse(
'${ApiClientConfig.production.baseUrl}/api/delivery/uploadDeliveryPicture?deliveryId=${delivery.id}', '${ApiClientConfig.development.baseUrl}/api/delivery/uploadDeliveryPicture?deliveryId=${delivery.id}',
); );
// Create HTTP client that accepts self-signed certificates // Create HTTP client that accepts self-signed certificates
final client = HttpClientFactory.createClient( final client = HttpClientFactory.createClient(
allowSelfSigned: ApiClientConfig.production.allowSelfSignedCertificate, allowSelfSigned: ApiClientConfig.development.allowSelfSignedCertificate,
); );
final http.MultipartRequest request = http.MultipartRequest('POST', uploadUrl); final http.MultipartRequest request = http.MultipartRequest('POST', uploadUrl);
@ -373,40 +383,28 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
final userProfile = ref.watch(userProfileProvider); final userProfile = ref.watch(userProfileProvider);
final l10n = AppLocalizations.of(context); final l10n = AppLocalizations.of(context);
final isMobile = context.isMobile;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
leading: (isMobile && _selectedRoute != null)
? IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: _backToRoutes,
tooltip: 'Back to routes',
)
: null,
title: Text(l10n.deliveryRoutes), title: Text(l10n.deliveryRoutes),
elevation: 0, elevation: 0,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
actions: [ actions: [
// Hide refresh button when on map view (mobile + route selected) IconButton(
// Google Maps Navigation has its own built-in volume controls icon: (routesData.isLoading || allDeliveriesData.isLoading)
if (!(isMobile && _selectedRoute != null)) ? const SizedBox(
IconButton( width: 20,
icon: (routesData.isLoading || allDeliveriesData.isLoading) height: 20,
? const SizedBox( child: CircularProgressIndicator(strokeWidth: 2),
width: 20, )
height: 20, : const Icon(Icons.refresh),
child: CircularProgressIndicator(strokeWidth: 2), onPressed: (routesData.isLoading || allDeliveriesData.isLoading)
) ? null
: const Icon(Icons.refresh), : () {
onPressed: (routesData.isLoading || allDeliveriesData.isLoading) ref.invalidate(deliveryRoutesProvider);
? null ref.invalidate(allDeliveriesProvider);
: () { },
ref.invalidate(deliveryRoutesProvider); tooltip: 'Refresh',
ref.invalidate(allDeliveriesProvider); ),
},
tooltip: 'Refresh',
),
userProfile.when( userProfile.when(
data: (profile) { data: (profile) {
String getInitials(String? fullName) { String getInitials(String? fullName) {
@ -431,13 +429,12 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
child: CircleAvatar( child: CircleAvatar(
radius: 16, radius: 16,
backgroundColor: Theme.of(context).colorScheme.primary, backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.onPrimary,
child: Text( child: Text(
getInitials(profile?.fullName), getInitials(profile?.fullName),
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.onPrimary, color: Theme.of(context).colorScheme.onPrimary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w600,
), ),
), ),
), ),
@ -465,55 +462,6 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
} }
return allDeliveriesData.when( return allDeliveriesData.when(
data: (allDeliveries) { data: (allDeliveries) {
final isMobile = context.isMobile;
// Mobile layout: Show routes list full-screen when no route selected
if (isMobile && _selectedRoute == null) {
return RefreshIndicator(
onRefresh: () async {
// ignore: unused_result
ref.refresh(deliveryRoutesProvider);
// ignore: unused_result
ref.refresh(allDeliveriesProvider);
},
child: CollapsibleRoutesSidebar(
routes: routes,
selectedRoute: null,
onRouteSelected: _selectRoute,
),
);
}
// Mobile layout: full-screen map with overlay when route is selected
if (isMobile && _selectedRoute != null) {
final routeDeliveries = allDeliveries
.where((d) => d.routeFragmentId == _selectedRoute!.id)
.toList();
return RefreshIndicator(
onRefresh: () async {
// ignore: unused_result
ref.refresh(deliveryRoutesProvider);
// ignore: unused_result
ref.refresh(allDeliveriesProvider);
},
child: MobileMapWithOverlay(
deliveries: routeDeliveries,
selectedDelivery: _selectedDelivery,
onDeliverySelected: (delivery) {
setState(() {
_selectedDelivery = delivery;
});
_autoShowNotesIfNeeded(delivery);
},
onDeliveryAction: (delivery, action) {
_handleDeliveryAction(action, delivery, _selectedRoute!.id);
},
),
);
}
// Tablet/Desktop layout: split view with map + sidebar
return RefreshIndicator( return RefreshIndicator(
onRefresh: () async { onRefresh: () async {
// ignore: unused_result // ignore: unused_result

View File

@ -31,10 +31,7 @@ class SettingsPage extends ConsumerWidget {
children: [ children: [
Text( Text(
l10n.profile, l10n.profile,
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: Theme.of(context).textTheme.titleMedium,
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
userProfile.when( userProfile.when(
@ -52,14 +49,9 @@ class SettingsPage extends ConsumerWidget {
children: [ children: [
CircleAvatar( CircleAvatar(
radius: 32, radius: 32,
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.onPrimary,
child: Text( child: Text(
profile.firstName[0].toUpperCase(), profile.firstName[0].toUpperCase(),
style: Theme.of(context).textTheme.titleLarge?.copyWith( style: Theme.of(context).textTheme.titleLarge,
color: Theme.of(context).colorScheme.onPrimary,
fontWeight: FontWeight.w700,
),
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
@ -69,52 +61,33 @@ class SettingsPage extends ConsumerWidget {
children: [ children: [
Text( Text(
profile.fullName, profile.fullName,
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: Theme.of(context).textTheme.titleMedium,
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
profile.email, profile.email,
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodySmall,
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
),
), ),
], ],
), ),
), ),
], IconButton.filled(
), icon: const Icon(Icons.logout),
const SizedBox(height: 16), onPressed: () async {
SizedBox( final authService = ref.read(authServiceProvider);
width: double.infinity, await authService.logout();
child: FilledButton.tonalIcon(
onPressed: () async {
final authService = ref.read(authServiceProvider);
await authService.logout();
if (context.mounted) {
// ignore: unused_result
ref.refresh(isAuthenticatedProvider);
if (context.mounted) { if (context.mounted) {
Navigator.of(context).pushReplacementNamed('/'); // ignore: unused_result
ref.refresh(isAuthenticatedProvider);
if (context.mounted) {
Navigator.of(context).pushReplacementNamed('/');
}
} }
} },
}, color: Theme.of(context).colorScheme.error,
icon: const Icon(Icons.logout), tooltip: l10n.logout,
label: Text(
l10n.logout,
style: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 16,
),
), ),
style: FilledButton.styleFrom( ],
backgroundColor: Theme.of(context).colorScheme.errorContainer,
foregroundColor: Theme.of(context).colorScheme.onErrorContainer,
),
),
), ),
], ],
), ),
@ -135,32 +108,17 @@ class SettingsPage extends ConsumerWidget {
children: [ children: [
Text( Text(
l10n.preferences, l10n.preferences,
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: Theme.of(context).textTheme.titleMedium,
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
ListTile( ListTile(
title: Text( title: Text(l10n.language),
l10n.language,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w700,
fontSize: 16,
),
),
subtitle: Text( subtitle: Text(
language == 'system' language == 'system'
? l10n.systemLanguage ? l10n.systemLanguage
: language == 'fr' : language == 'fr'
? l10n.french ? l10n.french
: l10n.english, : l10n.english
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
),
), ),
trailing: DropdownButton<String>( trailing: DropdownButton<String>(
value: language, value: language,
@ -172,105 +130,52 @@ class SettingsPage extends ConsumerWidget {
items: [ items: [
DropdownMenuItem( DropdownMenuItem(
value: 'system', value: 'system',
child: Text( child: Text(l10n.systemLanguage),
l10n.systemLanguage,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
), ),
DropdownMenuItem( DropdownMenuItem(
value: 'en', value: 'en',
child: Text( child: Text(l10n.english),
l10n.english,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
), ),
DropdownMenuItem( DropdownMenuItem(
value: 'fr', value: 'fr',
child: Text( child: Text(l10n.french),
l10n.french,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
), ),
], ],
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
ListTile( Column(
title: Text( crossAxisAlignment: CrossAxisAlignment.start,
l10n.theme, children: [
style: TextStyle( Text(
color: Theme.of(context).colorScheme.onSurface, l10n.theme,
fontWeight: FontWeight.w700, style: Theme.of(context).textTheme.titleSmall,
fontSize: 16,
), ),
), const SizedBox(height: 8),
subtitle: Text( SegmentedButton<ThemeMode>(
themeMode == ThemeMode.light selected: {themeMode},
? l10n.themeLight onSelectionChanged: (Set<ThemeMode> newSelection) {
: themeMode == ThemeMode.dark ref.read(themeModeProvider.notifier).setThemeMode(newSelection.first);
? l10n.themeDark },
: 'Device', segments: [
style: TextStyle( ButtonSegment<ThemeMode>(
color: Theme.of(context).colorScheme.onSurface, value: ThemeMode.light,
fontWeight: FontWeight.w600, label: Text(l10n.themeLight),
fontSize: 14, icon: const Icon(Icons.light_mode),
),
ButtonSegment<ThemeMode>(
value: ThemeMode.dark,
label: Text(l10n.themeDark),
icon: const Icon(Icons.dark_mode),
),
ButtonSegment<ThemeMode>(
value: ThemeMode.system,
label: Text(l10n.themeSystem),
icon: const Icon(Icons.brightness_auto),
),
],
), ),
), ],
trailing: DropdownButton<ThemeMode>(
value: themeMode,
onChanged: (ThemeMode? newValue) {
if (newValue != null) {
ref.read(themeModeProvider.notifier).setThemeMode(newValue);
}
},
items: [
DropdownMenuItem(
value: ThemeMode.light,
child: Text(
l10n.themeLight,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
),
DropdownMenuItem(
value: ThemeMode.dark,
child: Text(
l10n.themeDark,
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
),
DropdownMenuItem(
value: ThemeMode.system,
child: Text(
'Device',
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
),
],
),
), ),
], ],
), ),
@ -283,29 +188,16 @@ class SettingsPage extends ConsumerWidget {
children: [ children: [
Text( Text(
l10n.about, l10n.about,
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: Theme.of(context).textTheme.titleMedium,
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
ListTile( ListTile(
title: Text( title: Text(l10n.appVersion),
l10n.appVersion, subtitle: const Text('1.0.0'),
style: TextStyle( ),
color: Theme.of(context).colorScheme.onSurface, ListTile(
fontWeight: FontWeight.w700, title: Text(l10n.builtWithFlutter),
fontSize: 16, subtitle: Text(l10n.appDescription),
),
),
subtitle: Text(
'1.0.0',
style: TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
), ),
], ],
), ),

View File

@ -3,108 +3,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../api/types.dart'; import '../api/types.dart';
import '../api/client.dart'; import '../api/client.dart';
import '../api/grpc_client.dart';
import '../api/grpc_config.dart';
import '../api/openapi_config.dart'; import '../api/openapi_config.dart';
import '../services/auth_service.dart'; import '../services/auth_service.dart';
import '../models/user_profile.dart'; import '../models/user_profile.dart';
import '../models/delivery_route.dart'; import '../models/delivery_route.dart';
import '../models/delivery.dart'; import '../models/delivery.dart';
// ============================================================================
// API Mode Configuration - Feature Flag for HTTP/gRPC Transport
// ============================================================================
/// Enum representing the available API transport modes.
enum ApiMode {
/// Use HTTP/REST-based CQRS API client
http,
/// Use gRPC-based CQRS API client
grpc,
}
/// Configuration for API transport mode selection.
///
/// This class allows switching between HTTP and gRPC transports
/// for API calls. Following the pattern from [ApiClientConfig].
///
/// Example usage:
/// ```dart
/// // To switch to gRPC, override the apiModeConfigProvider:
/// ProviderScope(
/// overrides: [
/// apiModeConfigProvider.overrideWithValue(ApiModeConfig.developmentGrpc),
/// ],
/// child: MyApp(),
/// )
/// ```
class ApiModeConfig {
/// The transport mode to use for API calls.
final ApiMode mode;
/// Whether to fall back to HTTP on gRPC failures.
/// Only applicable when [mode] is [ApiMode.grpc].
final bool fallbackToHttpOnError;
const ApiModeConfig({
required this.mode,
this.fallbackToHttpOnError = true,
});
/// Development configuration - defaults to HTTP for stability.
/// Use this for safe development when gRPC backend may be unavailable.
static const ApiModeConfig development = ApiModeConfig(
mode: ApiMode.http,
fallbackToHttpOnError: true,
);
/// gRPC-first development configuration for testing gRPC integration.
/// Use this when actively developing/testing gRPC functionality.
static const ApiModeConfig developmentGrpc = ApiModeConfig(
mode: ApiMode.grpc,
fallbackToHttpOnError: true,
);
/// Production configuration - uses HTTP until gRPC is verified stable.
static const ApiModeConfig production = ApiModeConfig(
mode: ApiMode.http,
fallbackToHttpOnError: false,
);
/// Production gRPC configuration for when gRPC is production-ready.
static const ApiModeConfig productionGrpc = ApiModeConfig(
mode: ApiMode.grpc,
fallbackToHttpOnError: false,
);
/// Whether the current mode is gRPC.
bool get isGrpc => mode == ApiMode.grpc;
/// Whether the current mode is HTTP.
bool get isHttp => mode == ApiMode.http;
}
/// Provider for API mode configuration.
///
/// Override this provider to switch between HTTP and gRPC:
/// ```dart
/// ProviderScope(
/// overrides: [
/// apiModeConfigProvider.overrideWithValue(ApiModeConfig.developmentGrpc),
/// ],
/// child: MyApp(),
/// )
/// ```
final apiModeConfigProvider = Provider<ApiModeConfig>((ref) {
// Use gRPC for development - HTTP backend has been deprecated
return ApiModeConfig.developmentGrpc;
});
// ============================================================================
// Core Service Providers
// ============================================================================
final authServiceProvider = Provider<AuthService>((ref) { final authServiceProvider = Provider<AuthService>((ref) {
return AuthService(config: AuthConfig.development); return AuthService(config: AuthConfig.development);
}); });
@ -112,36 +16,11 @@ final authServiceProvider = Provider<AuthService>((ref) {
final apiClientProvider = Provider<CqrsApiClient>((ref) { final apiClientProvider = Provider<CqrsApiClient>((ref) {
final authService = ref.watch(authServiceProvider); final authService = ref.watch(authServiceProvider);
return CqrsApiClient( return CqrsApiClient(
config: ApiClientConfig.production, config: ApiClientConfig.development,
authService: authService, authService: authService,
); );
}); });
/// Provider for the gRPC-based CQRS API client.
///
/// Uses auto-dispose to properly shut down the gRPC channel when the provider
/// is no longer being watched. This ensures network resources are cleaned up.
///
/// Example usage:
/// ```dart
/// final grpcClient = ref.watch(grpcClientProvider);
/// final result = await grpcClient.getDeliveryRoutes();
/// ```
final grpcClientProvider = Provider.autoDispose<GrpcCqrsApiClient>((ref) {
final authService = ref.watch(authServiceProvider);
final client = GrpcCqrsApiClient(
config: GrpcConfig.development,
authService: authService,
);
// Register disposal callback to clean up gRPC channel resources
ref.onDispose(() {
client.shutdown();
});
return client;
});
final isAuthenticatedProvider = FutureProvider<bool>((ref) async { final isAuthenticatedProvider = FutureProvider<bool>((ref) async {
final authService = ref.watch(authServiceProvider); final authService = ref.watch(authServiceProvider);
return await authService.isAuthenticated(); return await authService.isAuthenticated();
@ -159,9 +38,7 @@ final authTokenProvider = FutureProvider<String?>((ref) async {
return await authService.getToken(); return await authService.getToken();
}); });
/// Internal HTTP-based delivery routes provider. final deliveryRoutesProvider = FutureProvider<List<DeliveryRoute>>((ref) async {
/// Use [deliveryRoutesProvider] instead, which respects the API mode configuration.
final _httpDeliveryRoutesProvider = FutureProvider<List<DeliveryRoute>>((ref) async {
final authService = ref.watch(authServiceProvider); final authService = ref.watch(authServiceProvider);
final isAuthenticated = await authService.isAuthenticated(); final isAuthenticated = await authService.isAuthenticated();
@ -171,7 +48,7 @@ final _httpDeliveryRoutesProvider = FutureProvider<List<DeliveryRoute>>((ref) as
// Create a new client with auth service for automatic token refresh // Create a new client with auth service for automatic token refresh
final authClient = CqrsApiClient( final authClient = CqrsApiClient(
config: ApiClientConfig.production, config: ApiClientConfig.development,
authService: authService, authService: authService,
); );
@ -191,120 +68,7 @@ final _httpDeliveryRoutesProvider = FutureProvider<List<DeliveryRoute>>((ref) as
return result.whenSuccess((routes) => routes) ?? []; return result.whenSuccess((routes) => routes) ?? [];
}); });
/// Unified delivery routes provider that respects the API mode configuration. final deliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref, routeFragmentId) async {
///
/// Automatically switches between HTTP and gRPC based on [apiModeConfigProvider].
/// When gRPC mode is enabled and [ApiModeConfig.fallbackToHttpOnError] is true,
/// falls back to HTTP on gRPC failures.
///
/// Example usage:
/// ```dart
/// final routes = ref.watch(deliveryRoutesProvider);
/// routes.when(
/// data: (data) => displayRoutes(data),
/// loading: () => showLoading(),
/// error: (error, stack) => showError(error),
/// );
/// ```
final deliveryRoutesProvider = FutureProvider<List<DeliveryRoute>>((ref) async {
final apiModeConfig = ref.watch(apiModeConfigProvider);
if (apiModeConfig.isGrpc) {
try {
return await ref.watch(grpcDeliveryRoutesProvider.future);
} catch (e) {
if (apiModeConfig.fallbackToHttpOnError) {
debugPrint('gRPC failed, falling back to HTTP: $e');
return await ref.watch(_httpDeliveryRoutesProvider.future);
}
rethrow;
}
}
return await ref.watch(_httpDeliveryRoutesProvider.future);
});
/// Provider for delivery routes using gRPC.
///
/// This is the gRPC-based alternative to [deliveryRoutesProvider].
/// Uses [GrpcCqrsApiClient] for improved performance and type safety.
///
/// Example usage:
/// ```dart
/// final routes = ref.watch(grpcDeliveryRoutesProvider);
/// routes.when(
/// data: (data) => displayRoutes(data),
/// loading: () => showLoading(),
/// error: (error, stack) => showError(error),
/// );
/// ```
final grpcDeliveryRoutesProvider = FutureProvider<List<DeliveryRoute>>((ref) async {
final authService = ref.watch(authServiceProvider);
final isAuthenticated = await authService.isAuthenticated();
if (!isAuthenticated) {
throw Exception('User not authenticated');
}
final grpcClient = ref.watch(grpcClientProvider);
final result = await grpcClient.getDeliveryRoutes();
return result.when(
success: (routes) => routes,
onError: (error) {
debugPrint('ERROR fetching delivery routes via gRPC: ${error.message}');
if (error.originalException != null) {
debugPrint('Original exception: ${error.originalException}');
}
throw Exception(error.message);
},
);
});
/// Provider for deliveries using gRPC.
///
/// This is the gRPC-based alternative to [deliveriesProvider].
/// Uses [GrpcCqrsApiClient] for improved performance and type safety.
/// Takes a [routeFragmentId] parameter to fetch deliveries for a specific route.
///
/// Example usage:
/// ```dart
/// final deliveries = ref.watch(grpcDeliveriesProvider(routeFragmentId));
/// deliveries.when(
/// data: (data) => displayDeliveries(data),
/// loading: () => showLoading(),
/// error: (error, stack) => showError(error),
/// );
/// ```
final grpcDeliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref, routeFragmentId) async {
final authService = ref.watch(authServiceProvider);
final isAuthenticated = await authService.isAuthenticated();
if (!isAuthenticated) {
throw Exception('User not authenticated');
}
final grpcClient = ref.watch(grpcClientProvider);
final result = await grpcClient.getDeliveries(routeFragmentId: routeFragmentId);
final deliveries = result.when(
success: (deliveries) => deliveries,
onError: (error) {
debugPrint('ERROR fetching deliveries for route $routeFragmentId via gRPC: ${error.message}');
if (error.originalException != null) {
debugPrint('Original exception: ${error.originalException}');
}
throw Exception(error.message);
},
);
// Always append the warehouse delivery at the end
return [...deliveries, Delivery.createWarehouseDelivery()];
});
/// Internal HTTP-based deliveries provider.
/// Use [deliveriesProvider] instead, which respects the API mode configuration.
final _httpDeliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref, routeFragmentId) async {
final authService = ref.watch(authServiceProvider); final authService = ref.watch(authServiceProvider);
final isAuthenticated = await authService.isAuthenticated(); final isAuthenticated = await authService.isAuthenticated();
@ -313,7 +77,7 @@ final _httpDeliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref,
} }
final authClient = CqrsApiClient( final authClient = CqrsApiClient(
config: ApiClientConfig.production, config: ApiClientConfig.development,
authService: authService, authService: authService,
); );
@ -344,44 +108,9 @@ final _httpDeliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref,
return [...deliveries, Delivery.createWarehouseDelivery()]; return [...deliveries, Delivery.createWarehouseDelivery()];
}); });
/// Unified deliveries provider that respects the API mode configuration.
///
/// Automatically switches between HTTP and gRPC based on [apiModeConfigProvider].
/// When gRPC mode is enabled and [ApiModeConfig.fallbackToHttpOnError] is true,
/// falls back to HTTP on gRPC failures.
///
/// Takes a [routeFragmentId] parameter to fetch deliveries for a specific route.
///
/// Example usage:
/// ```dart
/// final deliveries = ref.watch(deliveriesProvider(routeFragmentId));
/// deliveries.when(
/// data: (data) => displayDeliveries(data),
/// loading: () => showLoading(),
/// error: (error, stack) => showError(error),
/// );
/// ```
final deliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref, routeFragmentId) async {
final apiModeConfig = ref.watch(apiModeConfigProvider);
if (apiModeConfig.isGrpc) {
try {
return await ref.watch(grpcDeliveriesProvider(routeFragmentId).future);
} catch (e) {
if (apiModeConfig.fallbackToHttpOnError) {
debugPrint('gRPC failed for route $routeFragmentId, falling back to HTTP: $e');
return await ref.watch(_httpDeliveriesProvider(routeFragmentId).future);
}
rethrow;
}
}
return await ref.watch(_httpDeliveriesProvider(routeFragmentId).future);
});
/// Provider to get all deliveries from all routes /// Provider to get all deliveries from all routes
final allDeliveriesProvider = FutureProvider<List<Delivery>>((ref) async { final allDeliveriesProvider = FutureProvider<List<Delivery>>((ref) async {
final routes = await ref.watch(deliveryRoutesProvider.future); final routes = await ref.read(deliveryRoutesProvider.future);
if (routes.isEmpty) { if (routes.isEmpty) {
return []; return [];
@ -389,7 +118,7 @@ final allDeliveriesProvider = FutureProvider<List<Delivery>>((ref) async {
// Fetch deliveries for all routes in parallel using Future.wait // Fetch deliveries for all routes in parallel using Future.wait
final deliveriesFutures = routes.map((route) { final deliveriesFutures = routes.map((route) {
return ref.watch(deliveriesProvider(route.id).future); return ref.read(deliveriesProvider(route.id).future);
}).toList(); }).toList();
// Wait for all futures to complete // Wait for all futures to complete
@ -450,19 +179,6 @@ final collapseStateProvider = NotifierProvider<CollapseStateNotifier, bool>(() {
return CollapseStateNotifier(); return CollapseStateNotifier();
}); });
// Mobile deliveries list toggle state notifier for mobile overlay
class MobileDeliveriesListOpenNotifier extends Notifier<bool> {
@override
bool build() => false; // Default: closed
void toggle() => state = !state;
void setOpen(bool open) => state = open;
}
final mobileDeliveriesListOpenProvider = NotifierProvider<MobileDeliveriesListOpenNotifier, bool>(() {
return MobileDeliveriesListOpenNotifier();
});
class _EmptyQuery implements Serializable { class _EmptyQuery implements Serializable {
@override @override
Map<String, Object?> toJson() => {}; Map<String, Object?> toJson() => {};

View File

@ -6,55 +6,55 @@ class MaterialTheme {
const MaterialTheme(this.textTheme); const MaterialTheme(this.textTheme);
// Svrnty Brand Colors - Light Theme (Enhanced Contrast) // Svrnty Brand Colors - Light Theme
static ColorScheme lightScheme() { static ColorScheme lightScheme() {
return const ColorScheme( return const ColorScheme(
brightness: Brightness.light, brightness: Brightness.light,
primary: Color(0xffC91F37), // Darker Crimson Red for better contrast primary: Color(0xffDF2D45), // Svrnty Crimson Red (updated)
surfaceTint: Color(0xffC91F37), surfaceTint: Color(0xffDF2D45),
onPrimary: Color(0xffffffff), onPrimary: Color(0xffffffff),
primaryContainer: Color(0xffFFE5E9), primaryContainer: Color(0xffFFE0E5),
onPrimaryContainer: Color(0xff2D0009), onPrimaryContainer: Color(0xff06080C),
secondary: Color(0xff2D3843), // Darker Slate for better contrast secondary: Color(0xff3A4958), // Svrnty Dark Slate
onSecondary: Color(0xffffffff), onSecondary: Color(0xffffffff),
secondaryContainer: Color(0xffE0E7EE), secondaryContainer: Color(0xffD0DCE8),
onSecondaryContainer: Color(0xff0A0F15), onSecondaryContainer: Color(0xff06080C),
tertiary: Color(0xff16803D), // Darker Green for contrast tertiary: Color(0xff1D2C39), // Svrnty Teal
onTertiary: Color(0xffffffff), onTertiary: Color(0xffffffff),
tertiaryContainer: Color(0xffD1F4DD), tertiaryContainer: Color(0xffBFD5E3),
onTertiaryContainer: Color(0xff00210B), onTertiaryContainer: Color(0xff06080C),
error: Color(0xffD32F2F), error: Color(0xffEF4444),
onError: Color(0xffffffff), onError: Color(0xffffffff),
errorContainer: Color(0xffFFEBEE), errorContainer: Color(0xffFEE2E2),
onErrorContainer: Color(0xff5F0000), onErrorContainer: Color(0xff7F1D1D),
surface: Color(0xffFCFCFC), surface: Color(0xffFAFAFC),
onSurface: Color(0xff1A1C1E), // Very dark gray for maximum contrast onSurface: Color(0xff06080C),
onSurfaceVariant: Color(0xff3E4A56), // Darker gray for secondary text (7:1 contrast) onSurfaceVariant: Color(0xff2D3843), // Enhanced contrast: 7.2:1 (WCAG AAA)
outline: Color(0xff5F6B77), // Darker outline (4.5:1 contrast) outline: Color(0xff737A82), // Enhanced contrast: 4.6:1
outlineVariant: Color(0xffC4C7CC), outlineVariant: Color(0xffD1D5DB),
shadow: Color(0x1F000000), shadow: Color(0x1A000000),
scrim: Color(0xff000000), scrim: Color(0xff000000),
inverseSurface: Color(0xff1A1C1E), inverseSurface: Color(0xff06080C),
inversePrimary: Color(0xffFF6B7D), inversePrimary: Color(0xffFF6B7D),
primaryFixed: Color(0xffFFE5E9), primaryFixed: Color(0xffFFE0E5),
onPrimaryFixed: Color(0xff2D0009), onPrimaryFixed: Color(0xff06080C),
primaryFixedDim: Color(0xffFFB3C0), primaryFixedDim: Color(0xffFFC0C9),
onPrimaryFixedVariant: Color(0xff8B1A2A), onPrimaryFixedVariant: Color(0xff8B1A2A),
secondaryFixed: Color(0xffE0E7EE), secondaryFixed: Color(0xffD0DCE8),
onSecondaryFixed: Color(0xff0A0F15), onSecondaryFixed: Color(0xff06080C),
secondaryFixedDim: Color(0xffA8B8C8), secondaryFixedDim: Color(0xffB0C4D8),
onSecondaryFixedVariant: Color(0xff2D3843), onSecondaryFixedVariant: Color(0xff3A4958),
tertiaryFixed: Color(0xffD1F4DD), tertiaryFixed: Color(0xffBFD5E3),
onTertiaryFixed: Color(0xff00210B), onTertiaryFixed: Color(0xff06080C),
tertiaryFixedDim: Color(0xff9FD8B1), tertiaryFixedDim: Color(0xff9FBDCF),
onTertiaryFixedVariant: Color(0xff16803D), onTertiaryFixedVariant: Color(0xff1D2C39),
surfaceDim: Color(0xffDEE1E4), surfaceDim: Color(0xffdadcde),
surfaceBright: Color(0xffFCFCFC), surfaceBright: Color(0xfffafafa),
surfaceContainerLowest: Color(0xffffffff), surfaceContainerLowest: Color(0xffffffff),
surfaceContainerLow: Color(0xffF5F6F7), surfaceContainerLow: Color(0xfff6f6f8),
surfaceContainer: Color(0xffEFF1F3), surfaceContainer: Color(0xfff1f1f4),
surfaceContainerHigh: Color(0xffE9EBED), surfaceContainerHigh: Color(0xffebebee),
surfaceContainerHighest: Color(0xffE3E5E8), surfaceContainerHighest: Color(0xffe5e5e8),
); );
} }
@ -62,55 +62,165 @@ class MaterialTheme {
return theme(lightScheme()); return theme(lightScheme());
} }
// Svrnty Brand Colors - Dark Theme (Forest Green with Maximum Contrast) static ColorScheme lightMediumContrastScheme() {
return const ColorScheme(
brightness: Brightness.light,
primary: Color(0xff0d3665),
surfaceTint: Color(0xff3d5f90),
onPrimary: Color(0xffffffff),
primaryContainer: Color(0xff4d6ea0),
onPrimaryContainer: Color(0xffffffff),
secondary: Color(0xff2d3747),
onSecondary: Color(0xffffffff),
secondaryContainer: Color(0xff636d80),
onSecondaryContainer: Color(0xffffffff),
tertiary: Color(0xff442e4c),
onTertiary: Color(0xffffffff),
tertiaryContainer: Color(0xff7d6485),
onTertiaryContainer: Color(0xffffffff),
error: Color(0xff740006),
onError: Color(0xffffffff),
errorContainer: Color(0xffcf2c27),
onErrorContainer: Color(0xffffffff),
surface: Color(0xfff9f9ff),
onSurface: Color(0xff0f1116),
onSurfaceVariant: Color(0xff33363d),
outline: Color(0xff4f525a),
outlineVariant: Color(0xff6a6d75),
shadow: Color(0xff000000),
scrim: Color(0xff000000),
inverseSurface: Color(0xff2e3035),
inversePrimary: Color(0xffa6c8ff),
primaryFixed: Color(0xff4d6ea0),
onPrimaryFixed: Color(0xffffffff),
primaryFixedDim: Color(0xff335686),
onPrimaryFixedVariant: Color(0xffffffff),
secondaryFixed: Color(0xff636d80),
onSecondaryFixed: Color(0xffffffff),
secondaryFixedDim: Color(0xff4b5567),
onSecondaryFixedVariant: Color(0xffffffff),
tertiaryFixed: Color(0xff7d6485),
onTertiaryFixed: Color(0xffffffff),
tertiaryFixedDim: Color(0xff644c6c),
onTertiaryFixedVariant: Color(0xffffffff),
surfaceDim: Color(0xffc5c6cd),
surfaceBright: Color(0xfff9f9ff),
surfaceContainerLowest: Color(0xffffffff),
surfaceContainerLow: Color(0xfff3f3fa),
surfaceContainer: Color(0xffe7e8ee),
surfaceContainerHigh: Color(0xffdcdce3),
surfaceContainerHighest: Color(0xffd0d1d8),
);
}
ThemeData lightMediumContrast() {
return theme(lightMediumContrastScheme());
}
static ColorScheme lightHighContrastScheme() {
return const ColorScheme(
brightness: Brightness.light,
primary: Color(0xff002c58),
surfaceTint: Color(0xff3d5f90),
onPrimary: Color(0xffffffff),
primaryContainer: Color(0xff264a79),
onPrimaryContainer: Color(0xffffffff),
secondary: Color(0xff232d3d),
onSecondary: Color(0xffffffff),
secondaryContainer: Color(0xff404a5b),
onSecondaryContainer: Color(0xffffffff),
tertiary: Color(0xff392441),
onTertiary: Color(0xffffffff),
tertiaryContainer: Color(0xff584160),
onTertiaryContainer: Color(0xffffffff),
error: Color(0xff600004),
onError: Color(0xffffffff),
errorContainer: Color(0xff98000a),
onErrorContainer: Color(0xffffffff),
surface: Color(0xfff9f9ff),
onSurface: Color(0xff000000),
onSurfaceVariant: Color(0xff000000),
outline: Color(0xff292c33),
outlineVariant: Color(0xff464951),
shadow: Color(0xff000000),
scrim: Color(0xff000000),
inverseSurface: Color(0xff2e3035),
inversePrimary: Color(0xffa6c8ff),
primaryFixed: Color(0xff264a79),
onPrimaryFixed: Color(0xffffffff),
primaryFixedDim: Color(0xff063361),
onPrimaryFixedVariant: Color(0xffffffff),
secondaryFixed: Color(0xff404a5b),
onSecondaryFixed: Color(0xffffffff),
secondaryFixedDim: Color(0xff293343),
onSecondaryFixedVariant: Color(0xffffffff),
tertiaryFixed: Color(0xff584160),
onTertiaryFixed: Color(0xffffffff),
tertiaryFixedDim: Color(0xff402b48),
onTertiaryFixedVariant: Color(0xffffffff),
surfaceDim: Color(0xffb7b8bf),
surfaceBright: Color(0xfff9f9ff),
surfaceContainerLowest: Color(0xffffffff),
surfaceContainerLow: Color(0xfff0f0f7),
surfaceContainer: Color(0xffe1e2e9),
surfaceContainerHigh: Color(0xffd3d4da),
surfaceContainerHighest: Color(0xffc5c6cd),
);
}
ThemeData lightHighContrast() {
return theme(lightHighContrastScheme());
}
// Svrnty Brand Colors - Dark Theme
static ColorScheme darkScheme() { static ColorScheme darkScheme() {
return const ColorScheme( return const ColorScheme(
brightness: Brightness.dark, brightness: Brightness.dark,
primary: Color(0xffFF5A6D), // Bright Crimson Red for dark mode primary: Color(0xffDF2D45), // Svrnty Crimson Red
surfaceTint: Color(0xff4ADE80), // Success Green tint surfaceTint: Color(0xff4ADE80), // Success Green tint
onPrimary: Color(0xff000000), // Black text on bright primary onPrimary: Color(0xffffffff),
primaryContainer: Color(0xff9C1A29), primaryContainer: Color(0xff9C1A29),
onPrimaryContainer: Color(0xffFFE5E8), onPrimaryContainer: Color(0xffFFE0E5),
secondary: Color(0xffA5B6C8), // Very light Slate Gray secondary: Color(0xff506576), // Svrnty Slate Gray
onSecondary: Color(0xff0C1410), onSecondary: Color(0xffffffff),
secondaryContainer: Color(0xff3A4958), secondaryContainer: Color(0xff3A4958),
onSecondaryContainer: Color(0xffF2F6FA), onSecondaryContainer: Color(0xffD0DCE8),
tertiary: Color(0xff5EE890), // Bright Success Green tertiary: Color(0xff4ADE80), // Svrnty Success Green - Light
onTertiary: Color(0xff003916), onTertiary: Color(0xff14532D), // Dark green for contrast
tertiaryContainer: Color(0xff15803D), tertiaryContainer: Color(0xff15803D), // Svrnty Forest Dark Green
onTertiaryContainer: Color(0xffE6FFF0), onTertiaryContainer: Color(0xffDCFCE7), // Light green tint
error: Color(0xffFF8A80), error: Color(0xffFF6B6B),
onError: Color(0xff000000), onError: Color(0xff4C0707),
errorContainer: Color(0xffB3261E), errorContainer: Color(0xff93000A),
onErrorContainer: Color(0xffFFEDEA), onErrorContainer: Color(0xffFEE2E2),
surface: Color(0xff0C1410), // Dark Forest Green Background surface: Color(0xff0C1410), // Svrnty Dark Green Background
onSurface: Color(0xffFFFFFF), // Pure white for primary text - maximum contrast onSurface: Color(0xffF0F0F2),
onSurfaceVariant: Color(0xffE0E8E4), // Very light gray-green for secondary text (much brighter) onSurfaceVariant: Color(0xffBFC3C8),
outline: Color(0xffA5B5AB), // Light gray-green outline outline: Color(0xff9CA3AF), // Enhanced contrast for dark mode
outlineVariant: Color(0xff4A5A52), outlineVariant: Color(0xff374151),
shadow: Color(0xff000000), shadow: Color(0xff000000),
scrim: Color(0xff000000), scrim: Color(0xff000000),
inverseSurface: Color(0xffF0F4F2), inverseSurface: Color(0xffE2E2E6),
inversePrimary: Color(0xffDF2D45), inversePrimary: Color(0xffDF2D45),
primaryFixed: Color(0xffFFE5E8), primaryFixed: Color(0xffFFE0E5),
onPrimaryFixed: Color(0xff3D0009), onPrimaryFixed: Color(0xff3D0009),
primaryFixedDim: Color(0xffFF6B7D), primaryFixedDim: Color(0xffFF6B7D),
onPrimaryFixedVariant: Color(0xff9C1A29), onPrimaryFixedVariant: Color(0xff9C1A29),
secondaryFixed: Color(0xffE8EEF3), secondaryFixed: Color(0xffD0DCE8),
onSecondaryFixed: Color(0xff0A0F15), onSecondaryFixed: Color(0xff06080C),
secondaryFixedDim: Color(0xffA5B6C8), secondaryFixedDim: Color(0xff506576),
onSecondaryFixedVariant: Color(0xff3A4958), onSecondaryFixedVariant: Color(0xff3A4958),
tertiaryFixed: Color(0xffE6FFF0), tertiaryFixed: Color(0xffDCFCE7), // Light green container
onTertiaryFixed: Color(0xff003916), onTertiaryFixed: Color(0xff14532D), // Dark green text
tertiaryFixedDim: Color(0xff5EE890), tertiaryFixedDim: Color(0xff4ADE80), // Success green
onTertiaryFixedVariant: Color(0xff15803D), onTertiaryFixedVariant: Color(0xff15803D), // Forest green
surfaceDim: Color(0xff08100D), // Darker forest green surfaceDim: Color(0xff0A110E), // Darker forest green
surfaceBright: Color(0xff1F2D25), // Lighter forest green surfaceBright: Color(0xff1F2D25), // Brighter green tint
surfaceContainerLowest: Color(0xff060D0A), // Deepest forest surfaceContainerLowest: Color(0xff070D0A), // Deepest green
surfaceContainerLow: Color(0xff141B18), // Low forest surfaceContainerLow: Color(0xff141B18), // Low green
surfaceContainer: Color(0xff18221D), // Mid forest green surfaceContainer: Color(0xff18221D), // Mid forest green
surfaceContainerHigh: Color(0xff1D2822), // High forest surfaceContainerHigh: Color(0xff1D2822), // High green
surfaceContainerHighest: Color(0xff2A3832), // Highest forest green (lighter) surfaceContainerHighest: Color(0xff222F29), // Highest green tint
); );
} }
@ -118,116 +228,117 @@ class MaterialTheme {
return theme(darkScheme()); return theme(darkScheme());
} }
TextTheme _buildTextTheme(ColorScheme colorScheme) { static ColorScheme darkMediumContrastScheme() {
return TextTheme( return const ColorScheme(
displayLarge: TextStyle( brightness: Brightness.dark,
fontFamily: 'Montserrat', primary: Color(0xffcbddff),
fontWeight: FontWeight.w700, surfaceTint: Color(0xffa6c8ff),
fontSize: 57, onPrimary: Color(0xff00264d),
letterSpacing: -0.5, primaryContainer: Color(0xff7192c6),
color: colorScheme.onSurface, onPrimaryContainer: Color(0xff000000),
), secondary: Color(0xffd3ddf2),
displayMedium: TextStyle( onSecondary: Color(0xff1c2636),
fontFamily: 'Montserrat', secondaryContainer: Color(0xff8791a5),
fontWeight: FontWeight.w700, onSecondaryContainer: Color(0xff000000),
fontSize: 45, tertiary: Color(0xfff1d2f8),
letterSpacing: -0.5, onTertiary: Color(0xff321e3a),
color: colorScheme.onSurface, tertiaryContainer: Color(0xffa387aa),
), onTertiaryContainer: Color(0xff000000),
displaySmall: TextStyle( error: Color(0xffffd2cc),
fontFamily: 'Montserrat', onError: Color(0xff540003),
fontWeight: FontWeight.w700, errorContainer: Color(0xffff5449),
fontSize: 36, onErrorContainer: Color(0xff000000),
letterSpacing: -0.25, surface: Color(0xff111318),
color: colorScheme.onSurface, onSurface: Color(0xffffffff),
), onSurfaceVariant: Color(0xffdadce5),
headlineLarge: TextStyle( outline: Color(0xffafb2bb),
fontFamily: 'Montserrat', outlineVariant: Color(0xff8d9099),
fontWeight: FontWeight.w600, shadow: Color(0xff000000),
fontSize: 32, scrim: Color(0xff000000),
letterSpacing: -0.25, inverseSurface: Color(0xffe1e2e9),
color: colorScheme.onSurface, inversePrimary: Color(0xff254978),
), primaryFixed: Color(0xffd5e3ff),
headlineMedium: TextStyle( onPrimaryFixed: Color(0xff001129),
fontFamily: 'Montserrat', primaryFixedDim: Color(0xffa6c8ff),
fontWeight: FontWeight.w600, onPrimaryFixedVariant: Color(0xff0d3665),
fontSize: 28, secondaryFixed: Color(0xffd9e3f8),
letterSpacing: 0, onSecondaryFixed: Color(0xff071120),
color: colorScheme.onSurface, secondaryFixedDim: Color(0xffbdc7dc),
), onSecondaryFixedVariant: Color(0xff2d3747),
headlineSmall: TextStyle( tertiaryFixed: Color(0xfff8d8ff),
fontFamily: 'Montserrat', onTertiaryFixed: Color(0xff1c0924),
fontWeight: FontWeight.w600, tertiaryFixedDim: Color(0xffdbbde2),
fontSize: 24, onTertiaryFixedVariant: Color(0xff442e4c),
letterSpacing: 0, surfaceDim: Color(0xff111318),
color: colorScheme.onSurface, surfaceBright: Color(0xff42444a),
), surfaceContainerLowest: Color(0xff05070c),
titleLarge: TextStyle( surfaceContainerLow: Color(0xff1b1e22),
fontFamily: 'Montserrat', surfaceContainer: Color(0xff26282d),
fontWeight: FontWeight.w600, surfaceContainerHigh: Color(0xff303338),
fontSize: 22, surfaceContainerHighest: Color(0xff3b3e43),
letterSpacing: 0,
color: colorScheme.onSurface,
),
titleMedium: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 16,
letterSpacing: 0.15,
color: colorScheme.onSurface,
),
titleSmall: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 14,
letterSpacing: 0.1,
color: colorScheme.onSurfaceVariant,
),
bodyLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 16,
letterSpacing: 0.5,
color: colorScheme.onSurface,
),
bodyMedium: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 14,
letterSpacing: 0.25,
color: colorScheme.onSurface,
),
bodySmall: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 12,
letterSpacing: 0.4,
color: colorScheme.onSurfaceVariant,
),
labelLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 14,
letterSpacing: 0.1,
color: colorScheme.onSurface,
),
labelMedium: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 12,
letterSpacing: 0.5,
color: colorScheme.onSurfaceVariant,
),
labelSmall: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 11,
letterSpacing: 0.5,
color: colorScheme.onSurfaceVariant,
),
); );
} }
ThemeData darkMediumContrast() {
return theme(darkMediumContrastScheme());
}
static ColorScheme darkHighContrastScheme() {
return const ColorScheme(
brightness: Brightness.dark,
primary: Color(0xffeaf0ff),
surfaceTint: Color(0xffa6c8ff),
onPrimary: Color(0xff000000),
primaryContainer: Color(0xffa3c4fb),
onPrimaryContainer: Color(0xff000b1e),
secondary: Color(0xffeaf0ff),
onSecondary: Color(0xff000000),
secondaryContainer: Color(0xffb9c3d8),
onSecondaryContainer: Color(0xff030b1a),
tertiary: Color(0xfffeeaff),
onTertiary: Color(0xff000000),
tertiaryContainer: Color(0xffd7b9de),
onTertiaryContainer: Color(0xff16041e),
error: Color(0xffffece9),
onError: Color(0xff000000),
errorContainer: Color(0xffffaea4),
onErrorContainer: Color(0xff220001),
surface: Color(0xff111318),
onSurface: Color(0xffffffff),
onSurfaceVariant: Color(0xffffffff),
outline: Color(0xffedf0f9),
outlineVariant: Color(0xffc0c2cb),
shadow: Color(0xff000000),
scrim: Color(0xff000000),
inverseSurface: Color(0xffe1e2e9),
inversePrimary: Color(0xff254978),
primaryFixed: Color(0xffd5e3ff),
onPrimaryFixed: Color(0xff000000),
primaryFixedDim: Color(0xffa6c8ff),
onPrimaryFixedVariant: Color(0xff001129),
secondaryFixed: Color(0xffd9e3f8),
onSecondaryFixed: Color(0xff000000),
secondaryFixedDim: Color(0xffbdc7dc),
onSecondaryFixedVariant: Color(0xff071120),
tertiaryFixed: Color(0xfff8d8ff),
onTertiaryFixed: Color(0xff000000),
tertiaryFixedDim: Color(0xffdbbde2),
onTertiaryFixedVariant: Color(0xff1c0924),
surfaceDim: Color(0xff111318),
surfaceBright: Color(0xff4e5055),
surfaceContainerLowest: Color(0xff000000),
surfaceContainerLow: Color(0xff1d2024),
surfaceContainer: Color(0xff2e3035),
surfaceContainerHigh: Color(0xff393b41),
surfaceContainerHighest: Color(0xff45474c),
);
}
ThemeData darkHighContrast() {
return theme(darkHighContrastScheme());
}
ThemeData theme(ColorScheme colorScheme) { ThemeData theme(ColorScheme colorScheme) {
return ThemeData( return ThemeData(
useMaterial3: true, useMaterial3: true,
@ -236,7 +347,101 @@ class MaterialTheme {
fontFamily: 'Montserrat', fontFamily: 'Montserrat',
scaffoldBackgroundColor: colorScheme.surface, scaffoldBackgroundColor: colorScheme.surface,
canvasColor: colorScheme.surface, canvasColor: colorScheme.surface,
textTheme: _buildTextTheme(colorScheme), textTheme: const TextTheme(
displayLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w700,
fontSize: 57,
letterSpacing: -0.5,
),
displayMedium: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w700,
fontSize: 45,
letterSpacing: -0.5,
),
displaySmall: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w700,
fontSize: 36,
letterSpacing: -0.25,
),
headlineLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 32,
letterSpacing: -0.25,
),
headlineMedium: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 28,
letterSpacing: 0,
),
headlineSmall: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 24,
letterSpacing: 0,
),
titleLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 22,
letterSpacing: 0,
),
titleMedium: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 16,
letterSpacing: 0.15,
),
titleSmall: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 14,
letterSpacing: 0.1,
),
bodyLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w400,
fontSize: 16,
letterSpacing: 0.5,
),
bodyMedium: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w400,
fontSize: 14,
letterSpacing: 0.25,
),
bodySmall: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w400,
fontSize: 12,
letterSpacing: 0.4,
),
labelLarge: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 14,
letterSpacing: 0.1,
),
labelMedium: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 12,
letterSpacing: 0.5,
),
labelSmall: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 11,
letterSpacing: 0.5,
),
).apply(
bodyColor: colorScheme.onSurface,
displayColor: colorScheme.onSurface,
),
// Component Themes // Component Themes
cardTheme: ComponentThemes.cardTheme(colorScheme), cardTheme: ComponentThemes.cardTheme(colorScheme),
appBarTheme: ComponentThemes.appBarTheme(colorScheme), appBarTheme: ComponentThemes.appBarTheme(colorScheme),
@ -256,4 +461,43 @@ class MaterialTheme {
sliderTheme: ComponentThemes.sliderTheme(colorScheme), sliderTheme: ComponentThemes.sliderTheme(colorScheme),
); );
} }
List<ExtendedColor> get extendedColors => [
];
}
class ExtendedColor {
final Color seed, value;
final ColorFamily light;
final ColorFamily lightHighContrast;
final ColorFamily lightMediumContrast;
final ColorFamily dark;
final ColorFamily darkHighContrast;
final ColorFamily darkMediumContrast;
const ExtendedColor({
required this.seed,
required this.value,
required this.light,
required this.lightHighContrast,
required this.lightMediumContrast,
required this.dark,
required this.darkHighContrast,
required this.darkMediumContrast,
});
}
class ColorFamily {
const ColorFamily({
required this.color,
required this.onColor,
required this.colorContainer,
required this.onColorContainer,
});
final Color color;
final Color onColor;
final Color colorContainer;
final Color onColorContainer;
} }

View File

@ -1,320 +0,0 @@
# Svrnty Theme System - Quick Reference
## Standard Color Access Pattern
**ALWAYS use:**
```dart
final colorScheme = Theme.of(context).colorScheme;
// Primary UI
colorScheme.primary // Primary brand color (Crimson Red)
colorScheme.onPrimary // Text on primary (white/black depending on theme)
// Secondary UI
colorScheme.secondary // Secondary brand color (Slate Blue)
colorScheme.onSecondary // Text on secondary
// Text
colorScheme.onSurface // Primary text
colorScheme.onSurfaceVariant // Secondary text
// Backgrounds
colorScheme.surface // Page background
colorScheme.surfaceContainer // Card background
// Status (specialized)
StatusColorScheme.getStatusColor(status)
StatusColorScheme.getStatusColorFromTheme(status, colorScheme) // Theme-aware (preferred)
```
**NEVER use:**
```dart
Colors.white // FORBIDDEN - use colorScheme.onPrimary or onSurface
Colors.black // FORBIDDEN - use colorScheme.onSurface or scrim
Color(0xFFXXXXXX) // FORBIDDEN in components (except in theme files)
SvrntyColors.crimsonRed // FORBIDDEN - use colorScheme.primary instead
```
## Theme Variants
The app provides **2 theme variants**:
### Light Theme
- **Background:** White (#FCFCFC)
- **Primary:** Crimson Red (#C91F37) - high contrast variant
- **Secondary:** Dark Slate (#2D3843) - high contrast variant
- **Text:** Very dark gray (#1A1C1E) - 16.5:1 contrast (WCAG AAA)
- **Secondary Text:** Dark gray (#3E4A56) - 7:1 contrast (WCAG AAA)
### Dark Theme (Forest Green)
- **Background:** Dark Forest Green (#0C1410) - unique branding
- **Primary:** Bright Crimson (#FF5A6D) - optimized for dark backgrounds
- **Secondary:** Light Slate Gray (#A5B6C8)
- **Text:** Pure white (#FFFFFF) - 18.2:1 contrast (WCAG AAA)
- **Secondary Text:** Light gray-green (#E0E8E4) - 14.1:1 contrast (WCAG AAA)
All text colors are WCAG AAA compliant (minimum 7:1 contrast for normal text, 4.5:1 for large text).
## Color Access Examples
### Good Examples
```dart
// Text on colored background (e.g., status badge, avatar)
Container(
color: Theme.of(context).colorScheme.primary,
child: Text(
'Label',
style: TextStyle(color: Theme.of(context).colorScheme.onPrimary),
),
)
// Primary text on page background
Text(
'Hello',
style: TextStyle(color: Theme.of(context).colorScheme.onSurface),
)
// Secondary/muted text
Text(
'Description',
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
)
// Shadow color
BoxShadow(
color: Theme.of(context).colorScheme.scrim.withValues(alpha: 0.2),
)
```
### Bad Examples (DON'T DO THIS)
```dart
// WRONG - hardcoded white
Text('Label', style: TextStyle(color: Colors.white))
// WRONG - hardcoded black
BoxShadow(color: Colors.black.withValues(alpha: 0.2))
// WRONG - hardcoded color value
Container(color: Color(0xFFFF9800))
// WRONG - using SvrntyColors directly for UI elements
Container(color: SvrntyColors.crimsonRed) // Use colorScheme.primary instead
```
## Status Colors
For delivery status indicators, use the `StatusColorScheme` utility:
```dart
import '../theme/status_colors.dart';
// Get status color (hardcoded, consistent across themes)
final color = StatusColorScheme.getStatusColor('completed');
// Get status color from theme (preferred - adapts to theme)
final themeColor = StatusColorScheme.getStatusColorFromTheme(
'completed',
Theme.of(context).colorScheme,
);
// Get background and text colors
final bgColor = StatusColorScheme.getStatusBackground('completed');
final textColor = StatusColorScheme.getStatusText('completed');
// Use pre-built widgets
StatusBadgeWidget(status: 'completed')
StatusAccentBar(status: 'in_transit')
```
**Supported Status Values:**
- `pending` - Amber (attention needed)
- `in_transit`, `in_progress`, `processing` - Slate blue (active)
- `completed`, `delivered`, `done` - Green (success)
- `failed`, `error` - Red (problem)
- `cancelled`, `skipped`, `rejected` - Gray (inactive)
- `on_hold`, `paused`, `waiting` - Slate (informational)
## Progress Gradient Colors
For progress indicators (e.g., route completion):
```dart
import '../theme/color_system.dart';
// Progress colors (0-100%)
SvrntyColors.progressLow // Orange - 0-40%
SvrntyColors.progressMedium // Amber - 40-70%
SvrntyColors.progressHigh // Green - 70-100%
// Example: color interpolation
Color progressColor = Color.lerp(
SvrntyColors.progressLow,
SvrntyColors.progressMedium,
progressPercent,
)!;
```
## Modifying Colors
### Changing Brand Colors
Edit the ColorScheme definitions in `/lib/theme.dart`:
```dart
// Light theme
static ColorScheme lightScheme() {
return const ColorScheme(
brightness: Brightness.light,
primary: Color(0xffC91F37), // Change this for new primary color
secondary: Color(0xff2D3843), // Change this for new secondary color
// ... rest of colors
);
}
// Dark theme
static ColorScheme darkScheme() {
return const ColorScheme(
brightness: Brightness.dark,
primary: Color(0xffFF5A6D), // Change this for new primary color
secondary: Color(0xffA5B6C8), // Change this for new secondary color
// ... rest of colors
);
}
```
### Adding New Semantic Colors
Add to `/lib/theme/color_system.dart`:
```dart
class SvrntyColors {
// ... existing colors
/// New semantic color
static const Color myNewColor = Color(0xFFXXXXXX);
}
```
Then use it in components:
```dart
Container(color: SvrntyColors.myNewColor)
```
### Changing Status Colors
Edit `/lib/theme/status_colors.dart`:
```dart
class StatusColorScheme {
static const Color completed = Color(0xFF22C55E); // Change this
static const Color completedBackground = Color(0xFFD1FAE5); // Change this
static const Color completedText = Color(0xFF065F46); // Change this
// ... rest of colors
}
```
## Text Theme
The app uses **Montserrat** font family for all text with explicit color assignments.
**Font Weights:**
- 300 (Light) - Unused in current design
- 400 (Regular) - Body text
- 500 (Medium) - Labels, buttons
- 600 (SemiBold) - Headings, titles
- 700 (Bold) - Display text, emphasis
**Text Styles:**
```dart
Theme.of(context).textTheme.displayLarge // 57px, bold, onSurface
Theme.of(context).textTheme.headlineMedium // 28px, semibold, onSurface
Theme.of(context).textTheme.titleLarge // 22px, semibold, onSurface
Theme.of(context).textTheme.bodyMedium // 14px, regular, onSurface
Theme.of(context).textTheme.labelSmall // 11px, medium, onSurfaceVariant
```
All text styles automatically adapt to light/dark themes with proper contrast.
## Accessibility
All color combinations meet **WCAG AAA** standards (7:1 contrast for normal text, 4.5:1 for large text):
**Light Theme:**
- Primary text on background: 16.5:1 (WCAG AAA)
- Secondary text on background: 7:1 (WCAG AAA)
- Text on primary color: 6.2:1 (WCAG AA Large)
**Dark Theme:**
- Primary text on background: 18.2:1 (WCAG AAA)
- Secondary text on background: 14.1:1 (WCAG AAA)
- Text on primary color: 11.8:1 (WCAG AAA)
## Component Themes
Component-specific theme configurations are in `/lib/theme/component_themes.dart`:
- CardTheme - Elevated cards with subtle shadows
- AppBarTheme - Navigation bars
- ButtonTheme - Filled, outlined, elevated buttons
- InputDecorationTheme - Text fields
- SnackBarTheme - Toast messages
- DialogTheme - Modal dialogs
- BottomNavigationBarTheme - Bottom navigation
- ChipTheme - Status chips
- ProgressIndicatorTheme - Loading indicators
- FloatingActionButtonTheme - FAB
- SliderTheme - Range inputs
All component themes use `ColorScheme` properties for consistency.
## Migration Guide
If you need to migrate old hardcoded colors to the new theme system:
### Step 1: Find Hardcoded Colors
```bash
# Search for hardcoded colors in your components
grep -r "Colors\.white\|Colors\.black\|Color(0x" lib/components/ lib/pages/
```
### Step 2: Replace with Theme Colors
| Old Pattern | New Pattern |
|------------|-------------|
| `Colors.white` on colored bg | `colorScheme.onPrimary` |
| `Colors.white` on page | `colorScheme.surface` |
| `Colors.black` for text | `colorScheme.onSurface` |
| `Colors.black` for shadow | `colorScheme.scrim` |
| `Color(0xFFXXXXXX)` | Use `colorScheme` or `SvrntyColors` |
### Step 3: Test Both Themes
- Run app in light mode, verify all text is visible
- Run app in dark mode, verify all text is visible
- Check color contrast with browser dev tools
## Troubleshooting
**Text not visible in dark mode:**
- Ensure you're using `colorScheme.onSurface` or `onSurfaceVariant` for text colors
- Don't use hardcoded `Colors.black` or dark colors for text
- Check that TextTheme is properly applied with `_buildTextTheme()`
**Colors not updating when switching themes:**
- Use `Theme.of(context).colorScheme` instead of `SvrntyColors` constants
- Ensure widget rebuilds when theme changes (use `ConsumerWidget` for Riverpod)
- Avoid caching ColorScheme outside of build method
**Wrong colors in components:**
- Verify component uses `colorScheme` parameter correctly
- Check that custom theme is applied in MaterialApp
- Use `theme()` method to generate ThemeData
## Resources
- **Material Design 3:** https://m3.material.io/
- **WCAG Contrast Checker:** https://webaim.org/resources/contrastchecker/
- **Flutter Theme Guide:** https://docs.flutter.dev/cookbook/design/themes
- **ColorScheme Docs:** https://api.flutter.dev/flutter/material/ColorScheme-class.html

View File

@ -44,19 +44,6 @@ class SvrntyColors {
/// Error - Red for errors, failures, and destructive actions /// Error - Red for errors, failures, and destructive actions
static const Color error = Color(0xFFEF4444); static const Color error = Color(0xFFEF4444);
// ============================================
// PROGRESS GRADIENT COLORS
// ============================================
/// Progress Low - Orange for low progress (0-40%)
static const Color progressLow = Color(0xFFFF9800);
/// Progress Medium - Amber for medium progress (40-70%)
static const Color progressMedium = Color(0xFFFFC107);
/// Progress High - Green for high progress (70-100%)
static const Color progressHigh = Color(0xFF4CAF50);
// ============================================ // ============================================
// DELIVERY STATUS COLORS (OPTIMIZED SVRNTY MAPPING) // DELIVERY STATUS COLORS (OPTIMIZED SVRNTY MAPPING)
// ============================================ // ============================================
@ -110,4 +97,88 @@ class SvrntyColors {
/// Surface Subdued - Subdued light surface /// Surface Subdued - Subdued light surface
static const Color surfaceSubdued = Color(0xFFE8EAEE); static const Color surfaceSubdued = Color(0xFFE8EAEE);
// ============================================
// EXTENDED COLOR FAMILIES - SUCCESS (GREEN)
// ============================================
/// Success color light theme
static const Color successLight = Color(0xFF22C55E);
/// Success on color light theme
static const Color onSuccessLight = Color(0xFFFFFFFF);
/// Success container light theme
static const Color successContainerLight = Color(0xFFDCFCE7);
/// Success on container light theme
static const Color onSuccessContainerLight = Color(0xFF14532D);
/// Success color dark theme
static const Color successDark = Color(0xFF4ADE80);
/// Success on color dark theme
static const Color onSuccessDark = Color(0xFF14532D);
/// Success container dark theme
static const Color successContainerDark = Color(0xFF15803D);
/// Success on container dark theme
static const Color onSuccessContainerDark = Color(0xFFDCFCE7);
// ============================================
// EXTENDED COLOR FAMILIES - WARNING (AMBER)
// ============================================
/// Warning color light theme
static const Color warningLight = Color(0xFFF59E0B);
/// Warning on color light theme
static const Color onWarningLight = Color(0xFFFFFFFF);
/// Warning container light theme
static const Color warningContainerLight = Color(0xFFFEF3C7);
/// Warning on container light theme
static const Color onWarningContainerLight = Color(0xFF78350F);
/// Warning color dark theme
static const Color warningDark = Color(0xFFFBBF24);
/// Warning on color dark theme
static const Color onWarningDark = Color(0xFF78350F);
/// Warning container dark theme
static const Color warningContainerDark = Color(0xFFD97706);
/// Warning on container dark theme
static const Color onWarningContainerDark = Color(0xFFFEF3C7);
// ============================================
// EXTENDED COLOR FAMILIES - INFO (BLUE)
// ============================================
/// Info color light theme
static const Color infoLight = Color(0xFF3B82F6);
/// Info on color light theme
static const Color onInfoLight = Color(0xFFFFFFFF);
/// Info container light theme
static const Color infoContainerLight = Color(0xFFDEEEFF);
/// Info on container light theme
static const Color onInfoContainerLight = Color(0xFF003DA1);
/// Info color dark theme
static const Color infoDark = Color(0xFF90CAF9);
/// Info on color dark theme
static const Color onInfoDark = Color(0xFF003DA1);
/// Info container dark theme
static const Color infoContainerDark = Color(0xFF0D47A1);
/// Info on container dark theme
static const Color onInfoContainerDark = Color(0xFFDEEEFF);
} }

View File

@ -63,36 +63,6 @@ class StatusColorScheme {
} }
} }
/// Get status color from ColorScheme (preferred over hardcoded)
/// This method returns status colors that better integrate with the current theme
static Color getStatusColorFromTheme(String status, ColorScheme colorScheme) {
switch (status.toLowerCase()) {
case 'completed':
case 'delivered':
case 'done':
return colorScheme.tertiary; // Use theme green
case 'failed':
case 'error':
return colorScheme.error; // Use theme error
case 'pending':
return SvrntyColors.warning; // Keep custom warning
case 'in_transit':
case 'in_progress':
case 'processing':
return colorScheme.secondary; // Use theme secondary
case 'cancelled':
case 'skipped':
case 'rejected':
return colorScheme.onSurfaceVariant; // Use theme variant
case 'on_hold':
case 'paused':
case 'waiting':
return colorScheme.outline; // Use theme outline
default:
return getStatusColor(status); // Fallback to hardcoded
}
}
/// Get status background color by status type /// Get status background color by status type
static Color getStatusBackground(String status) { static Color getStatusBackground(String status) {
switch (status.toLowerCase()) { switch (status.toLowerCase()) {

View File

@ -48,18 +48,14 @@ class ToastHelper {
final screenWidth = MediaQuery.of(context).size.width; final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height; final screenHeight = MediaQuery.of(context).size.height;
final topPadding = MediaQuery.of(context).padding.top; final topPadding = MediaQuery.of(context).padding.top;
final bottomPadding = MediaQuery.of(context).padding.bottom;
final toastWidth = screenWidth * 0.5; // 50% of screen width final toastWidth = screenWidth * 0.5; // 50% of screen width
final horizontalMargin = (screenWidth - toastWidth) / 2; final horizontalMargin = (screenWidth - toastWidth) / 2;
// Position toast at top with safe padding // Position toast very close to top (10px into safe area)
final topMargin = topPadding + 10; final topMargin = topPadding - 10;
const toastHeight = 60.0; const toastHeight = 60.0;
final bottomMargin = screenHeight - topMargin - toastHeight; final bottomMargin = screenHeight - topMargin - toastHeight;
// Ensure bottom margin is at least the safe area padding
final safeBottomMargin = bottomMargin > bottomPadding ? bottomMargin : bottomPadding + 10;
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
@ -76,7 +72,7 @@ class ToastHelper {
top: topMargin, top: topMargin,
left: horizontalMargin, left: horizontalMargin,
right: horizontalMargin, right: horizontalMargin,
bottom: safeBottomMargin, bottom: bottomMargin,
), ),
), ),
); );

7
macos/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
# Flutter-related
**/Flutter/ephemeral/
**/Pods/
# Xcode-related
**/dgph
**/xcuserdata/

View File

@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@ -0,0 +1,22 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
import file_selector_macos
import flutter_appauth
import flutter_secure_storage_macos
import path_provider_foundation
import shared_preferences_foundation
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FlutterAppauthPlugin.register(with: registry.registrar(forPlugin: "FlutterAppauthPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}

42
macos/Podfile Normal file
View File

@ -0,0 +1,42 @@
platform :osx, '10.15'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_macos_podfile_setup
target 'Runner' do
use_frameworks!
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
end

66
macos/Podfile.lock Normal file
View File

@ -0,0 +1,66 @@
PODS:
- AppAuth (2.0.0):
- AppAuth/Core (= 2.0.0)
- AppAuth/ExternalUserAgent (= 2.0.0)
- AppAuth/Core (2.0.0)
- AppAuth/ExternalUserAgent (2.0.0):
- AppAuth/Core
- file_selector_macos (0.0.1):
- FlutterMacOS
- flutter_appauth (0.0.1):
- AppAuth (= 2.0.0)
- FlutterMacOS
- flutter_secure_storage_macos (6.1.3):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- url_launcher_macos (0.0.1):
- FlutterMacOS
DEPENDENCIES:
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
- flutter_appauth (from `Flutter/ephemeral/.symlinks/plugins/flutter_appauth/macos`)
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
SPEC REPOS:
trunk:
- AppAuth
EXTERNAL SOURCES:
file_selector_macos:
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
flutter_appauth:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_appauth/macos
flutter_secure_storage_macos:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
FlutterMacOS:
:path: Flutter/ephemeral
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
SPEC CHECKSUMS:
AppAuth: 1c1a8afa7e12f2ec3a294d9882dfa5ab7d3cb063
file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7
flutter_appauth: 84cbf57c7926a898a612726e99241a031e33fac3
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd
PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009
COCOAPODS: 1.16.2

View File

@ -0,0 +1,806 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXAggregateTarget section */
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
buildPhases = (
33CC111E2044C6BF0003C045 /* ShellScript */,
);
dependencies = (
);
name = "Flutter Assemble";
productName = FLX;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
8DB9DF1D0D67F627976B9567 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 041F85059F9328D34942F9D6 /* Pods_Runner.framework */; };
C401667496D831E1EC00C98A /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA5800EB37305EF0FF4DF44E /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 33CC10EC2044A3C60003C045;
remoteInfo = Runner;
};
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 33CC111A2044C6BA0003C045;
remoteInfo = FLX;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
33CC110E2044A8840003C045 /* Bundle Framework */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Bundle Framework";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
041F85059F9328D34942F9D6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2EC7CE87754DF92A83806AA2 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* planb_logistic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = planb_logistic.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
8F033A11E9EAC4D52F9AB11B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
AE7E230E90375211956F6A11 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
B85AF793493B7D2C94B0B6C0 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
B94CEBF26FBF21F1D205C7F5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
E61D7373F33D6ACFB1A7CE5A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
FA5800EB37305EF0FF4DF44E /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
331C80D2294CF70F00263BE5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C401667496D831E1EC00C98A /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10EA2044A3C60003C045 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8DB9DF1D0D67F627976B9567 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C80D6294CF71000263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C80D7294CF71000263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
33BA886A226E78AF003329D5 /* Configs */ = {
isa = PBXGroup;
children = (
33E5194F232828860026EE4D /* AppInfo.xcconfig */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
);
path = Configs;
sourceTree = "<group>";
};
33CC10E42044A3C60003C045 = {
isa = PBXGroup;
children = (
33FAB671232836740065AC1E /* Runner */,
33CEB47122A05771004F2AC0 /* Flutter */,
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
9ADF7908BFA81F757DA35875 /* Pods */,
);
sourceTree = "<group>";
};
33CC10EE2044A3C60003C045 /* Products */ = {
isa = PBXGroup;
children = (
33CC10ED2044A3C60003C045 /* planb_logistic.app */,
331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
33CC11242044D66E0003C045 /* Resources */ = {
isa = PBXGroup;
children = (
33CC10F22044A3C60003C045 /* Assets.xcassets */,
33CC10F42044A3C60003C045 /* MainMenu.xib */,
33CC10F72044A3C60003C045 /* Info.plist */,
);
name = Resources;
path = ..;
sourceTree = "<group>";
};
33CEB47122A05771004F2AC0 /* Flutter */ = {
isa = PBXGroup;
children = (
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
);
path = Flutter;
sourceTree = "<group>";
};
33FAB671232836740065AC1E /* Runner */ = {
isa = PBXGroup;
children = (
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
33E51914231749380026EE4D /* Release.entitlements */,
33CC11242044D66E0003C045 /* Resources */,
33BA886A226E78AF003329D5 /* Configs */,
);
path = Runner;
sourceTree = "<group>";
};
9ADF7908BFA81F757DA35875 /* Pods */ = {
isa = PBXGroup;
children = (
E61D7373F33D6ACFB1A7CE5A /* Pods-Runner.debug.xcconfig */,
B94CEBF26FBF21F1D205C7F5 /* Pods-Runner.release.xcconfig */,
AE7E230E90375211956F6A11 /* Pods-Runner.profile.xcconfig */,
8F033A11E9EAC4D52F9AB11B /* Pods-RunnerTests.debug.xcconfig */,
B85AF793493B7D2C94B0B6C0 /* Pods-RunnerTests.release.xcconfig */,
2EC7CE87754DF92A83806AA2 /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
041F85059F9328D34942F9D6 /* Pods_Runner.framework */,
FA5800EB37305EF0FF4DF44E /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C80D4294CF70F00263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
C9F125A1B896BACD72110FA3 /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C80DA294CF71000263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
33CC10EC2044A3C60003C045 /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
C9BE0B5B71F736CE7DDAB12A /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
A43917F429562A98B78A57E7 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
33CC11202044C79F0003C045 /* PBXTargetDependency */,
);
name = Runner;
productName = Runner;
productReference = 33CC10ED2044A3C60003C045 /* planb_logistic.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
33CC10E52044A3C60003C045 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80D4294CF70F00263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 33CC10EC2044A3C60003C045;
};
33CC10EC2044A3C60003C045 = {
CreatedOnToolsVersion = 9.2;
LastSwiftMigration = 1100;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Sandbox = {
enabled = 1;
};
};
};
33CC111A2044C6BA0003C045 = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Manual;
};
};
};
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 33CC10E42044A3C60003C045;
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
33CC10EC2044A3C60003C045 /* Runner */,
331C80D4294CF70F00263BE5 /* RunnerTests */,
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C80D3294CF70F00263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10EB2044A3C60003C045 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
};
33CC111E2044C6BF0003C045 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
Flutter/ephemeral/FlutterInputs.xcfilelist,
);
inputPaths = (
Flutter/ephemeral/tripwire,
);
outputFileListPaths = (
Flutter/ephemeral/FlutterOutputs.xcfilelist,
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
A43917F429562A98B78A57E7 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
C9BE0B5B71F736CE7DDAB12A /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
C9F125A1B896BACD72110FA3 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C80D1294CF70F00263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10E92044A3C60003C045 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C80DA294CF71000263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CC10EC2044A3C60003C045 /* Runner */;
targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */;
};
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
33CC10F52044A3C60003C045 /* Base */,
);
name = MainMenu.xib;
path = Runner;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 8F033A11E9EAC4D52F9AB11B /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.goutezplanb.planbLogistic.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/planb_logistic.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/planb_logistic";
};
name = Debug;
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B85AF793493B7D2C94B0B6C0 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.goutezplanb.planbLogistic.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/planb_logistic.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/planb_logistic";
};
name = Release;
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2EC7CE87754DF92A83806AA2 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.goutezplanb.planbLogistic.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/planb_logistic.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/planb_logistic";
};
name = Profile;
};
338D0CE9231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Profile;
};
338D0CEA231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = LD76P8L42W;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Profile;
};
338D0CEB231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Profile;
};
33CC10F92044A3C60003C045 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
33CC10FA2044A3C60003C045 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Release;
};
33CC10FC2044A3C60003C045 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = 833P6TSX55;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
33CC10FD2044A3C60003C045 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = LD76P8L42W;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Release;
};
33CC111C2044C6BA0003C045 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
33CC111D2044C6BA0003C045 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C80DB294CF71000263BE5 /* Debug */,
331C80DC294CF71000263BE5 /* Release */,
331C80DD294CF71000263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC10F92044A3C60003C045 /* Debug */,
33CC10FA2044A3C60003C045 /* Release */,
338D0CE9231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC10FC2044A3C60003C045 /* Debug */,
33CC10FD2044A3C60003C045 /* Release */,
338D0CEA231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC111C2044C6BA0003C045 /* Debug */,
33CC111D2044C6BA0003C045 /* Release */,
338D0CEB231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 33CC10E52044A3C60003C045 /* Project object */;
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "planb_logistic.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "planb_logistic.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C80D4294CF70F00263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "planb_logistic.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "planb_logistic.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,13 @@
import Cocoa
import FlutterMacOS
@main
class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
return true
}
}

View File

@ -0,0 +1,68 @@
{
"images" : [
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "app_icon_16.png",
"scale" : "1x"
},
{
"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_64.png",
"scale" : "2x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "app_icon_128.png",
"scale" : "1x"
},
{
"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_512.png",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "app_icon_512.png",
"scale" : "1x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "app_icon_1024.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,343 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Runner" customModuleProvider="target">
<connections>
<outlet property="applicationMenu" destination="uQy-DD-JDr" id="XBo-yE-nKs"/>
<outlet property="mainFlutterWindow" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="APP_NAME" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="APP_NAME" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About APP_NAME" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide APP_NAME" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit APP_NAME" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
<items>
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
<connections>
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
<connections>
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
<connections>
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
<connections>
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
<connections>
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
</connections>
</menuItem>
<menuItem title="Delete" id="pa3-QI-u2k">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
<connections>
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
<menuItem title="Find" id="4EN-yA-p0u">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Find" id="1b7-l0-nxx">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
<connections>
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
<connections>
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
<connections>
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
<connections>
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
<connections>
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
<connections>
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
<connections>
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="9ic-FL-obx">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
<items>
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
</connections>
</menuItem>
<menuItem title="Smart Links" id="cwL-P1-jid">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
</connections>
</menuItem>
<menuItem title="Data Detectors" id="tRr-pd-1PS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="2oI-Rn-ZJC">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
<items>
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="xrE-MZ-jX0">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
<items>
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
<items>
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
<connections>
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="R4o-n2-Eq4">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="EPT-qC-fAb">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="rJ0-wn-3NY"/>
</menuItem>
</items>
<point key="canvasLocation" x="142" y="-258"/>
</menu>
<window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="Runner" customModuleProvider="target">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="335" y="390" width="800" height="600"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1577"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="800" height="600"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</window>
</objects>
</document>

View File

@ -0,0 +1,14 @@
// Application-level settings for the Runner target.
//
// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
// future. If not, the values below would default to using the project name when this becomes a
// 'flutter create' template.
// The application's name. By default this is also the title of the Flutter window.
PRODUCT_NAME = planb_logistic
// The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = com.local.planbLogistic
// The copyright displayed in application information
PRODUCT_COPYRIGHT = Copyright © 2025 com.goutezplanb. All rights reserved.

View File

@ -0,0 +1,2 @@
#include "../../Flutter/Flutter-Debug.xcconfig"
#include "Warnings.xcconfig"

View File

@ -0,0 +1,2 @@
#include "../../Flutter/Flutter-Release.xcconfig"
#include "Warnings.xcconfig"

View File

@ -0,0 +1,13 @@
WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
GCC_WARN_UNDECLARED_SELECTOR = YES
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
CLANG_WARN_PRAGMA_PACK = YES
CLANG_WARN_STRICT_PROTOTYPES = YES
CLANG_WARN_COMMA = YES
GCC_WARN_STRICT_SELECTOR_MATCH = YES
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
GCC_WARN_SHADOW = YES
CLANG_WARN_UNREACHABLE_CODE = YES

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.goutezplanb.planb-logistic</string>
</array>
</dict>
</plist>

32
macos/Runner/Info.plist Normal file
View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>$(PRODUCT_COPYRIGHT)</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -0,0 +1,15 @@
import Cocoa
import FlutterMacOS
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let flutterViewController = FlutterViewController()
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
RegisterGeneratedPlugins(registry: flutterViewController)
super.awakeFromNib()
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.goutezplanb.planb-logistic</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
import Cocoa
import FlutterMacOS
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}

View File

@ -0,0 +1 @@
5cde0a78d118f9e043e7443ceca0f306

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d1b134ad118e25bf8a1dc2b9ce79ad5d","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/GoogleNavigation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"GoogleNavigation","INFOPLIST_FILE":"Target Support Files/GoogleNavigation/ResourceBundle-GoogleNavigationResources-GoogleNavigation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"GoogleNavigationResources","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98654fae4296dc5751ac9d756d9dc36c1e","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9896631f0702bcaa9fd24776311b2cd48b","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/GoogleNavigation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"GoogleNavigation","INFOPLIST_FILE":"Target Support Files/GoogleNavigation/ResourceBundle-GoogleNavigationResources-GoogleNavigation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","PRODUCT_NAME":"GoogleNavigationResources","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e980a002d7dd790eb3cbcf1a8009bc4439a","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9896631f0702bcaa9fd24776311b2cd48b","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/GoogleNavigation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"GoogleNavigation","INFOPLIST_FILE":"Target Support Files/GoogleNavigation/ResourceBundle-GoogleNavigationResources-GoogleNavigation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","PRODUCT_NAME":"GoogleNavigationResources","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e981d5b7ba262dce1f6706128fba960f1ce","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98bc8aaa9cab3591c49705029f91b06de6","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98d7882cb7e7e2096e74a80981e2418f35","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98313329d51e705fb6ce392e38d83a004c","guid":"bfdfe7dc352907fc980b868725387e98a3dc015cb98170f31ad6d86aa524b818"}],"guid":"bfdfe7dc352907fc980b868725387e98947e6e86a6a40368b18d6ecdc96c368d","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e9840209c7fe78cadee2612d71e96cd4bdb","name":"GoogleNavigation-GoogleNavigationResources","productReference":{"guid":"bfdfe7dc352907fc980b868725387e9896ff2333d2f65de7e44bf6896a8741c5","name":"GoogleNavigationResources.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98a1a39aaea5af2ba63294afc25a75a7e4","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98587b3fe1afcbe113356f962b7437612d","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e980d7fa4a1253053ca3fd7d132636d1340","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98c5d0e1ed7e6a7b273203839c1dcf3983","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e980d7fa4a1253053ca3fd7d132636d1340","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98a775653f895e396868c12e2332cb2abf","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e985d66c08890a6c8ef680001402a445f53","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9836ae1a0e28845970edd8d32f7e018b0a","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98c79c0f30a3b36d9e3ba24ba75b56a881","guid":"bfdfe7dc352907fc980b868725387e98b94944de210da9c395429e2a8fb03b4f"}],"guid":"bfdfe7dc352907fc980b868725387e984397c4d2abb7ee69743821db03e2ab9b","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e987ea64ee8d53085bf9edd1a57aaf8cbb5","name":"path_provider_foundation-path_provider_foundation_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e986e649604f74c414a7c2dbe5ef4cc4e75","name":"path_provider_foundation_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98a553cb6838f3dba8465d8e4475e67146","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppAuth","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"AppAuth","INFOPLIST_FILE":"Target Support Files/AppAuth/ResourceBundle-AppAuthCore_Privacy-AppAuth-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"AppAuthCore_Privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98439b74840e95c117db5f42cdf80e53d2","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98853e49f132a195ea0f4a3955deb01309","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppAuth","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"AppAuth","INFOPLIST_FILE":"Target Support Files/AppAuth/ResourceBundle-AppAuthCore_Privacy-AppAuth-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"AppAuthCore_Privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98a22414cb00cd15c3439640af7894cfbb","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98853e49f132a195ea0f4a3955deb01309","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AppAuth","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"AppAuth","INFOPLIST_FILE":"Target Support Files/AppAuth/ResourceBundle-AppAuthCore_Privacy-AppAuth-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"AppAuthCore_Privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98f23d0d665c129afc428a5dd94c278e58","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e982e193386a8c6c93c535225e95333da8c","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98a8d52a63f94af3aac430ffff1430fdf1","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e989d84a52718b57739049593ec7bcff072","guid":"bfdfe7dc352907fc980b868725387e98135caa02afe381ca8187e00959fc2041"}],"guid":"bfdfe7dc352907fc980b868725387e98800326bb0a43ad022ad5efa714aaa85d","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e98410c96b4e26fc36411e63b84c3491605","name":"AppAuth-AppAuthCore_Privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e986d566b0f46776138a3ba88837e01b2bf","name":"AppAuthCore_Privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e986d3e6fe5a6e621cced341ee873850040","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e986d016da354f3a459dcbbc0bc3aa504d4","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d0b24e03f50d0470357d26e4f8a02735","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e9847c3a289e72a64d753bb10a5cb8915a5","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d0b24e03f50d0470357d26e4f8a02735","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98d36fda1d2bfc83c42830a49385040c15","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98c0d91e6b857a686e8565c5deacabf60b","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e982972ffa1a081226a2c629865c594ad13","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98fb3bfaadcdb5b2857988cbc2ef7557ef","guid":"bfdfe7dc352907fc980b868725387e98fdf6309dd30e74d7f9d10386e3b30a92"}],"guid":"bfdfe7dc352907fc980b868725387e98422b283e061839ac3ce68befcefda198","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e9802f35ab680609a626ebd2ddd692a3822","name":"permission_handler_apple-permission_handler_apple_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e983e9a904e8a35cb34b69458780be142b3","name":"permission_handler_apple_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982f985d09c7cc7155033fe82268497d22","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/google_navigation_flutter","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"google_navigation_flutter","INFOPLIST_FILE":"Target Support Files/google_navigation_flutter/ResourceBundle-google_navigation_flutter_privacy_info-google_navigation_flutter-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"google_navigation_flutter_privacy_info","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98752011596fc869a834e8528c73ef279b","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98ab248c6763e47003ca200ac075684f2b","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/google_navigation_flutter","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"google_navigation_flutter","INFOPLIST_FILE":"Target Support Files/google_navigation_flutter/ResourceBundle-google_navigation_flutter_privacy_info-google_navigation_flutter-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","PRODUCT_NAME":"google_navigation_flutter_privacy_info","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e982cceafe2be828c9723ab385557be436c","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98ab248c6763e47003ca200ac075684f2b","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/google_navigation_flutter","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"google_navigation_flutter","INFOPLIST_FILE":"Target Support Files/google_navigation_flutter/ResourceBundle-google_navigation_flutter_privacy_info-google_navigation_flutter-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","PRODUCT_NAME":"google_navigation_flutter_privacy_info","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e9826583347601a9aa812b297e38af0eeac","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9892886dc904b36aacb2ab9d013be96636","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98c10994d292cbc8c39344b9d0c712477b","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e982cab8dfb60c6c5e899a43b5e4cf34529","guid":"bfdfe7dc352907fc980b868725387e983dae192296c61ece93492dfe204360fe"}],"guid":"bfdfe7dc352907fc980b868725387e9890c28f2a1cb69a31f0b102c661e71019","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e98ac39a888cfe1cb710fc82f373c10df1a","name":"google_navigation_flutter-google_navigation_flutter_privacy_info","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98f30d584e5ae71ad240f9f8224d5a008f","name":"google_navigation_flutter_privacy_info.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e981ef08c6dea34941e9a4dbdf79cdda6cb","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/url_launcher_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"url_launcher_ios","INFOPLIST_FILE":"Target Support Files/url_launcher_ios/ResourceBundle-url_launcher_ios_privacy-url_launcher_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"url_launcher_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98e538e294d2bef1d12b0b4c6c1b4adef7","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9877ace9a7bfa4a14a21241facb205746c","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/url_launcher_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"url_launcher_ios","INFOPLIST_FILE":"Target Support Files/url_launcher_ios/ResourceBundle-url_launcher_ios_privacy-url_launcher_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","PRODUCT_NAME":"url_launcher_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e987da90b1825e20dc7164eb9d75e7336ee","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9877ace9a7bfa4a14a21241facb205746c","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/url_launcher_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"url_launcher_ios","INFOPLIST_FILE":"Target Support Files/url_launcher_ios/ResourceBundle-url_launcher_ios_privacy-url_launcher_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","PRODUCT_NAME":"url_launcher_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98f2f7644bf615fe4d30ffd64a417384b8","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98776a8886f3a4f687fd9150930b326f97","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98262609f70ac231708da98c1103de8913","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9884009c7e86d9122a27fb3926d34d3ec9","guid":"bfdfe7dc352907fc980b868725387e9882c29da6cb2086ccfb74e13d18787d39"}],"guid":"bfdfe7dc352907fc980b868725387e9869a5c5e10c8c0072113593518680754f","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e9891b3b8cc56823cdea4b418e009a423b2","name":"url_launcher_ios-url_launcher_ios_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e9827df8da513ac7d6928fc311b53a7155d","name":"url_launcher_ios_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d1b134ad118e25bf8a1dc2b9ce79ad5d","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IPHONEOS_DEPLOYMENT_TARGET":"16.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","ONLY_ACTIVE_ARCH":"NO","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2"},"guid":"bfdfe7dc352907fc980b868725387e98d9973325385d84e0e77b85c54100d070","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9896631f0702bcaa9fd24776311b2cd48b","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IPHONEOS_DEPLOYMENT_TARGET":"16.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e98ce9c972125fa8e60135d49830ab80fb9","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9896631f0702bcaa9fd24776311b2cd48b","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IPHONEOS_DEPLOYMENT_TARGET":"16.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e9856cf668712b9a03308963239dfa31677","name":"Release"}],"buildPhases":[{"alwaysOutOfDate":"false","alwaysRunForInstallHdrs":"false","buildFiles":[],"emitEnvironment":"false","guid":"bfdfe7dc352907fc980b868725387e9875f5f7294d970da29740ea9d892ff270","inputFileListPaths":["${PODS_ROOT}/Target Support Files/GoogleNavigation/GoogleNavigation-xcframeworks-input-files.xcfilelist"],"inputFilePaths":[],"name":"[CP] Copy XCFrameworks","originalObjectID":"181935D79354233793EF8014128D7B3E","outputFileListPaths":["${PODS_ROOT}/Target Support Files/GoogleNavigation/GoogleNavigation-xcframeworks-output-files.xcfilelist"],"outputFilePaths":[],"sandboxingOverride":"basedOnBuildSetting","scriptContents":"\"${PODS_ROOT}/Target Support Files/GoogleNavigation/GoogleNavigation-xcframeworks.sh\"\n","shellPath":"/bin/sh","type":"com.apple.buildphase.shell-script"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e9818352c54edac2258b91768852065ce5e","name":"GoogleMaps"},{"guid":"bfdfe7dc352907fc980b868725387e9840209c7fe78cadee2612d71e96cd4bdb","name":"GoogleNavigation-GoogleNavigationResources"}],"guid":"bfdfe7dc352907fc980b868725387e98282d9246524ea316059ab11846dac3ef","name":"GoogleNavigation","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Release","provisioningStyle":0}],"type":"aggregate"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9817e4b806b80581ad59086f05c18c0abc","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/image_picker_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"image_picker_ios","INFOPLIST_FILE":"Target Support Files/image_picker_ios/ResourceBundle-image_picker_ios_privacy-image_picker_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"image_picker_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98df4a049c8d956a0e300ff8741d2502a1","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982a6ba965c0d1565e3ac936b521de1c02","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/image_picker_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"image_picker_ios","INFOPLIST_FILE":"Target Support Files/image_picker_ios/ResourceBundle-image_picker_ios_privacy-image_picker_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","PRODUCT_NAME":"image_picker_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98298ad06d2db424041a77af82a3b4f89c","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982a6ba965c0d1565e3ac936b521de1c02","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/image_picker_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"image_picker_ios","INFOPLIST_FILE":"Target Support Files/image_picker_ios/ResourceBundle-image_picker_ios_privacy-image_picker_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","PRODUCT_NAME":"image_picker_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98ce99df14b1a56298b5cbb05e4a25b1a7","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98b1d731e1c47e24f2d3d9365594b534c2","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e987adb5d8d9a741d3612168cc3dbfcf91a","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98ef98da3dfb1614c9251036934326194c","guid":"bfdfe7dc352907fc980b868725387e98acd19b46d12f2b8464b372a006a67261"}],"guid":"bfdfe7dc352907fc980b868725387e9815a3f9bb03e106f67d64f3a72a41e042","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e98082dc85da1fc941e5234c7cc1f11b27d","name":"image_picker_ios-image_picker_ios_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98cba567c8a049008de84f093e54e3191c","name":"image_picker_ios_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98160bc0fdb96a014912e5cb08e18463a0","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/shared_preferences_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"shared_preferences_foundation","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/ResourceBundle-shared_preferences_foundation_privacy-shared_preferences_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"shared_preferences_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e983047af32f8e2e016fbf9be06870c33e6","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98a3c42da36a093d8623310a791cd3dc6d","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/shared_preferences_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"shared_preferences_foundation","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/ResourceBundle-shared_preferences_foundation_privacy-shared_preferences_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","PRODUCT_NAME":"shared_preferences_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98700000cb76fafd9e45a1f6e29803b245","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98a3c42da36a093d8623310a791cd3dc6d","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/shared_preferences_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"shared_preferences_foundation","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/ResourceBundle-shared_preferences_foundation_privacy-shared_preferences_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","PRODUCT_NAME":"shared_preferences_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98c62c43014bb9dfc10f724f45a1ac65f8","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98f97dfc877762175831b0b4212fe180f9","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98de9b2c5134e95e1e06be5d8762603813","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98ec37b801b9a069998dd77146ec9fdad3","guid":"bfdfe7dc352907fc980b868725387e98cebc3bb5d2a8f91e65023731ed1fd203"}],"guid":"bfdfe7dc352907fc980b868725387e98ee249dae93bf8c8d96fc8e23a1de09bc","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e98e0be3b0d5ad56f1985578b1f97431765","name":"shared_preferences_foundation-shared_preferences_foundation_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98ad625504a4c1e61077bbfd33bd1d1785","name":"shared_preferences_foundation_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9840ae838f8ac69bc67263efbe8dc323d7","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IPHONEOS_DEPLOYMENT_TARGET":"16.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","ONLY_ACTIVE_ARCH":"NO","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2"},"guid":"bfdfe7dc352907fc980b868725387e98644b3fe27382cec8a7bd8d5de6d3bf23","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e989bf599cd5d4dd79de867d43540047de6","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IPHONEOS_DEPLOYMENT_TARGET":"16.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e9873ec9b10f7565a6466b1212456cdaadb","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e989bf599cd5d4dd79de867d43540047de6","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IPHONEOS_DEPLOYMENT_TARGET":"16.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e986321e0a9b9c9f4570e60c08f0377621a","name":"Release"}],"buildPhases":[{"alwaysOutOfDate":"false","alwaysRunForInstallHdrs":"false","buildFiles":[],"emitEnvironment":"false","guid":"bfdfe7dc352907fc980b868725387e98b21ffc68aa281b044f48f05e9d22d849","inputFileListPaths":["${PODS_ROOT}/Target Support Files/GoogleMaps/GoogleMaps-xcframeworks-input-files.xcfilelist"],"inputFilePaths":[],"name":"[CP] Copy XCFrameworks","originalObjectID":"B4014D7E512183EABBE5F8E70545CAF8","outputFileListPaths":["${PODS_ROOT}/Target Support Files/GoogleMaps/GoogleMaps-xcframeworks-output-files.xcfilelist"],"outputFilePaths":[],"sandboxingOverride":"basedOnBuildSetting","scriptContents":"\"${PODS_ROOT}/Target Support Files/GoogleMaps/GoogleMaps-xcframeworks.sh\"\n","shellPath":"/bin/sh","type":"com.apple.buildphase.shell-script"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e9877354dc0c1379e634078de2da2deba6b","name":"GoogleMaps-GoogleMapsResources"}],"guid":"bfdfe7dc352907fc980b868725387e9818352c54edac2258b91768852065ce5e","name":"GoogleMaps","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Release","provisioningStyle":0}],"type":"aggregate"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e988fc4ed18f636615e52006d03796a45a9","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/flutter_appauth","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"flutter_appauth","INFOPLIST_FILE":"Target Support Files/flutter_appauth/ResourceBundle-flutter_appauth_privacy-flutter_appauth-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"flutter_appauth_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98eb5e4b173a8a222bc4dd2b991a9b796c","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98488326edb025622cc45efa16ad2f4033","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/flutter_appauth","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"flutter_appauth","INFOPLIST_FILE":"Target Support Files/flutter_appauth/ResourceBundle-flutter_appauth_privacy-flutter_appauth-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"flutter_appauth_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e982da7903f6bf4fbac53ab8010b0c4810e","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98488326edb025622cc45efa16ad2f4033","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/flutter_appauth","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"flutter_appauth","INFOPLIST_FILE":"Target Support Files/flutter_appauth/ResourceBundle-flutter_appauth_privacy-flutter_appauth-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"flutter_appauth_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e9800469c3da0970cdb833fb4e3b00b7acb","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98dfbcd1a74cf8ad9dbd5ed77f4effcc1a","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9824a1deca64e220c3512947ea4eb1d5b3","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98fa36d3533e98bbd2853301b1d0435f65","guid":"bfdfe7dc352907fc980b868725387e9818635a98dc9294c0d431f5a9d106526e"}],"guid":"bfdfe7dc352907fc980b868725387e981b2008682b8523b8fe291e154d1d5931","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e9838116aba79bee5cd919637253bcf2ecc","name":"flutter_appauth-flutter_appauth_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e982460b3be5f4208d02013fc970dac2dce","name":"flutter_appauth_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9840ae838f8ac69bc67263efbe8dc323d7","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/GoogleMaps","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"GoogleMaps","INFOPLIST_FILE":"Target Support Files/GoogleMaps/ResourceBundle-GoogleMapsResources-GoogleMaps-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"GoogleMapsResources","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e982c14955c63412351f74695d1b6225c3e","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e989bf599cd5d4dd79de867d43540047de6","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/GoogleMaps","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"GoogleMaps","INFOPLIST_FILE":"Target Support Files/GoogleMaps/ResourceBundle-GoogleMapsResources-GoogleMaps-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","PRODUCT_NAME":"GoogleMapsResources","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e982a9acfb9f68977d7a38499ab60ebd7fe","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e989bf599cd5d4dd79de867d43540047de6","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/GoogleMaps","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"GoogleMaps","INFOPLIST_FILE":"Target Support Files/GoogleMaps/ResourceBundle-GoogleMapsResources-GoogleMaps-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"16.0","PRODUCT_NAME":"GoogleMapsResources","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98d4e10b4069fe9558f6d49c1a01a7c632","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e985f6dda4fc1bb8e4d92d7ac93bc6e6ba1","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9807d7fec25bf2c1bd052de32d1578f0aa","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98408aeea65f8576fdbf766a4c1aafc7f3","guid":"bfdfe7dc352907fc980b868725387e988186244c4109758cf0a2e67498b727d0"}],"guid":"bfdfe7dc352907fc980b868725387e98266cd70b115d0472b8370de763869623","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e9877354dc0c1379e634078de2da2deba6b","name":"GoogleMaps-GoogleMapsResources","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98e1226e3627f386c3cc556b927e8c995d","name":"GoogleMapsResources.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d419f50ce432ed26acea72a8689cf65d","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/flutter_secure_storage","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"flutter_secure_storage","INFOPLIST_FILE":"Target Support Files/flutter_secure_storage/ResourceBundle-flutter_secure_storage-flutter_secure_storage-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"flutter_secure_storage","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98197bd3cfd8fa3bd41e88a3946f74d36d","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e980272323ab8cd909b1b93bca3b700be56","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/flutter_secure_storage","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"flutter_secure_storage","INFOPLIST_FILE":"Target Support Files/flutter_secure_storage/ResourceBundle-flutter_secure_storage-flutter_secure_storage-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","PRODUCT_NAME":"flutter_secure_storage","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98f12b4b44a5231c41985e39f0ad2cd11a","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e980272323ab8cd909b1b93bca3b700be56","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/flutter_secure_storage","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_LOCATION=1 PERMISSION_CAMERA=1 PERMISSION_PHOTOS=1","IBSC_MODULE":"flutter_secure_storage","INFOPLIST_FILE":"Target Support Files/flutter_secure_storage/ResourceBundle-flutter_secure_storage-flutter_secure_storage-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","PRODUCT_NAME":"flutter_secure_storage","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e9853895883505158a4f7b52bb67f133f9c","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9862f74ca3c0a0277e461b20e30338447b","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e985e62bbdae2a14eb08f8b7f4a2d7456e7","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98373359216b673381bf820b29f93ee608","guid":"bfdfe7dc352907fc980b868725387e98e05e804bf30e8a8eb0be4a83a4cab8b2"}],"guid":"bfdfe7dc352907fc980b868725387e981e8032e9ce87101012ec0a04f86dc3f4","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e98a0220561f537715e864e45aed9ae8b8b","name":"flutter_secure_storage-flutter_secure_storage","productReference":{"guid":"bfdfe7dc352907fc980b868725387e989548ba3fd96e73f640dce7442408204f","name":"flutter_secure_storage.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

Some files were not shown because too many files have changed in this diff Show More