This commit is contained in:
Riccardo Usardi committed 2025-07-18 22:24:01 +02:00
commit e833bcaec4
224 files changed
+11812

No files matched your search

+45
View File
@@ -0,0 +1,45 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
+45
View File
@@ -0,0 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "077b4a4ce10a07b82caa6897f0c626f9c0a3ac90"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
base_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
- platform: android
create_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
base_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
- platform: ios
create_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
base_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
- platform: linux
create_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
base_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
- platform: macos
create_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
base_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
- platform: web
create_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
base_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
- platform: windows
create_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
base_revision: 077b4a4ce10a07b82caa6897f0c626f9c0a3ac90
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
+16
View File
@@ -0,0 +1,16 @@
# u_vineyard
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
+28
View File
@@ -0,0 +1,28 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
+14
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
+44
View File
@@ -0,0 +1,44 @@
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.example.u_vineyard"
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.example.u_vineyard"
// 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
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
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")
}
}
}
flutter {
source = "../.."
}
@@ -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>
+45
View File
@@ -0,0 +1,45 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="u_vineyard"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<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" />
</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>
@@ -0,0 +1,5 @@
package com.example.u_vineyard
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity()
@@ -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>
@@ -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

@@ -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>
@@ -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="@android:style/Theme.Light.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.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -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>
+21
View File
@@ -0,0 +1,21 @@
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)
}
+3
View File
@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
+5
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
+25
View File
@@ -0,0 +1,25 @@
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.7.3" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
}
include(":app")
+34
View File
@@ -0,0 +1,34 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
+26
View File
@@ -0,0 +1,26 @@
<?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>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>
+1
View File
@@ -0,0 +1 @@
#include "Generated.xcconfig"
+1
View File
@@ -0,0 +1 @@
#include "Generated.xcconfig"
+616
View File
@@ -0,0 +1,616 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
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_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
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_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.uVineyard;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.uVineyard.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.uVineyard.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.uVineyard.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
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_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
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_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
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_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
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_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
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_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.uVineyard;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.uVineyard;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -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>
@@ -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>PreviewsEnabled</key>
<false/>
</dict>
</plist>
@@ -0,0 +1,101 @@
<?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 = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
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"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.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 = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
@@ -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>
@@ -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>PreviewsEnabled</key>
<false/>
</dict>
</plist>
+13
View File
@@ -0,0 +1,13 @@
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
@@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

@@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
+49
View File
@@ -0,0 +1,49 @@
<?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>CFBundleDisplayName</key>
<string>U Vineyard</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>u_vineyard</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
+1
View File
@@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"
+12
View File
@@ -0,0 +1,12 @@
import Flutter
import UIKit
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.
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 765 KiB

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="17.0605" height="18.4082">
<g>
<rect height="18.4082" opacity="0" width="17.0605" x="0" y="0"/>
<path d="M2.39258 18.4082L14.668 18.4082C16.2891 18.4082 17.0605 17.9199 17.0605 16.8457C17.0605 14.2871 13.8281 10.5859 8.53516 10.5859C3.23242 10.5859 0 14.2871 0 16.8457C0 17.9199 0.771484 18.4082 2.39258 18.4082ZM1.93359 16.9336C1.67969 16.9336 1.57227 16.8652 1.57227 16.6602C1.57227 15.0586 4.05273 12.0605 8.53516 12.0605C13.0078 12.0605 15.4883 15.0586 15.4883 16.6602C15.4883 16.8652 15.3906 16.9336 15.1367 16.9336ZM8.53516 9.375C10.8594 9.375 12.7539 7.30469 12.7539 4.78516C12.7539 2.28516 10.8691 0.322266 8.53516 0.322266C6.2207 0.322266 4.31641 2.32422 4.31641 4.80469C4.32617 7.31445 6.21094 9.375 8.53516 9.375ZM8.53516 7.90039C7.10938 7.90039 5.88867 6.5332 5.88867 4.80469C5.88867 3.10547 7.08984 1.79688 8.53516 1.79688C9.99023 1.79688 11.1816 3.08594 11.1816 4.78516C11.1816 6.51367 9.9707 7.90039 8.53516 7.90039Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" id="dashboard-apps"><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 5a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V5zM4 15a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-4zM4 5a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5zm8 10a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-4z"></path></svg>

After

Width:  |  Height:  |  Size: 480 B

+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
<circle cx="9" cy="9" r="4" fill="#494c4e" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 282 B

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="26.4746" height="16.6113">
<g>
<rect height="16.6113" opacity="0" width="26.4746" x="0" y="0"/>
<path d="M13.2422 16.6113C21.0645 16.6113 26.4746 10.2832 26.4746 8.31055C26.4746 6.32812 21.0547 0.00976562 13.2422 0.00976562C5.51758 0.00976562 0 6.32812 0 8.31055C0 10.2832 5.51758 16.6113 13.2422 16.6113ZM13.2422 13.75C10.1953 13.75 7.7832 11.2793 7.77344 8.31055C7.76367 5.26367 10.1953 2.87109 13.2422 2.87109C16.2598 2.87109 18.7012 5.26367 18.7012 8.31055C18.7012 11.2793 16.2598 13.75 13.2422 13.75ZM13.2422 10.2734C14.3262 10.2734 15.2246 9.38477 15.2246 8.31055C15.2246 7.22656 14.3262 6.33789 13.2422 6.33789C12.1484 6.33789 11.25 7.22656 11.25 8.31055C11.25 9.38477 12.1484 10.2734 13.2422 10.2734Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="26.4746" height="18.2812">
<g>
<rect height="18.2812" opacity="0" width="26.4746" x="0" y="0"/>
<path d="M13.2422 17.4463C15.0488 17.4463 16.7285 17.1143 18.2031 16.5674L15.6445 14.0088C14.9219 14.3799 14.1016 14.585 13.2422 14.585C10.1953 14.585 7.7832 12.1143 7.77344 9.14551C7.77344 8.2666 7.97852 7.43652 8.33984 6.7041L5 3.34473C1.92383 5.26855 0 7.97363 0 9.14551C0 11.1182 5.51758 17.4463 13.2422 17.4463ZM21.7578 14.7803C24.6094 12.8955 26.4746 10.3076 26.4746 9.14551C26.4746 7.16309 21.0547 0.844727 13.2422 0.844727C11.582 0.844727 10.0195 1.12793 8.60352 1.59668L11.1426 4.13574C11.7871 3.8623 12.4902 3.70605 13.2422 3.70605C16.2598 3.70605 18.7012 6.09863 18.7012 9.14551C18.7012 9.8877 18.5352 10.6006 18.2422 11.2256ZM10.127 8.9209C10.127 10.6396 11.543 12.0264 13.252 12.0264C13.3887 12.0264 13.5156 12.0166 13.6523 12.0068L10.1465 8.50098C10.1367 8.6377 10.127 8.78418 10.127 8.9209ZM16.3477 8.94043C16.3477 7.23145 14.9707 5.84473 13.2422 5.84473C13.1152 5.84473 12.9883 5.85449 12.8711 5.86426L16.3281 9.32129C16.3379 9.2041 16.3477 9.06738 16.3477 8.94043ZM20.8398 17.6025C21.1328 17.9053 21.6016 17.9248 21.9043 17.6025C22.2266 17.2803 22.1973 16.8408 21.9043 16.5381L5.57617 0.219727C5.2832-0.0732422 4.80469-0.0732422 4.50195 0.219727C4.21875 0.50293 4.21875 1.00098 4.50195 1.28418Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="11.6553" height="11.0815">
<g>
<rect height="11.0815" opacity="0" width="11.6553" x="0" y="0"/>
<path d="M7.08496 9.46899L4.56543 9.46899L4.56543 6.24146C4.56543 6.01685 4.7168 5.87036 4.94141 5.87036L6.71387 5.87036C6.93848 5.87036 7.08496 6.01685 7.08496 6.24146ZM1.52344 9.17603C1.52344 9.85474 1.93359 10.2551 2.62207 10.2551L9.04297 10.2551C9.73145 10.2551 10.1367 9.85474 10.1367 9.17603L10.1367 5.30884L6.12305 1.94458C5.9375 1.78833 5.71777 1.79321 5.53711 1.94458L1.52344 5.30884ZM0 4.82056C0 5.02075 0.15625 5.21118 0.419922 5.21118C0.556641 5.21118 0.668945 5.13794 0.771484 5.05493L5.65918 0.953369C5.7666 0.855713 5.89844 0.855713 6.00586 0.953369L10.8936 5.05493C10.9912 5.13794 11.1035 5.21118 11.2402 5.21118C11.4697 5.21118 11.6553 5.06958 11.6553 4.83521C11.6553 4.68872 11.6064 4.59106 11.5039 4.50317L6.4209 0.230713C6.05957-0.0769043 5.61035-0.0769043 5.24414 0.230713L0.15625 4.50317C0.0488281 4.59106 0 4.70825 0 4.82056ZM8.91113 2.61841L10.1367 3.65356L10.1367 1.39771C10.1367 1.18286 10 1.04614 9.78516 1.04614L9.2627 1.04614C9.05273 1.04614 8.91113 1.18286 8.91113 1.39771Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+5
View File
@@ -0,0 +1,5 @@
<svg width="2421" height="1364" viewBox="0 0 2421 1364" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.4614 620.447L657.461 1241.05C659.404 1242.94 660.5 1245.53 660.5 1248.23V1354C660.5 1359.52 656.023 1364 650.5 1364H10.5C4.97715 1364 0.5 1359.52 0.5 1354V1244V627.626C0.5 618.791 11.1187 614.297 17.4614 620.447Z" fill="#64748B"/>
<path d="M2403.04 620.447L1763.04 1241.05C1761.1 1242.94 1760 1245.53 1760 1248.23V1354C1760 1359.52 1764.48 1364 1770 1364H2410C2415.52 1364 2420 1359.52 2420 1354V1244V627.626C2420 618.791 2409.38 614.297 2403.04 620.447Z" fill="#64748B"/>
<path d="M0 145.758V10C0 4.47715 4.47715 0 10 0H565.555C568.177 0 570.695 1.03027 572.565 2.86882L1203.49 623.108C1207.38 626.933 1213.62 626.933 1217.51 623.108L1848.43 2.86881C1850.3 1.03026 1852.82 0 1855.45 0H2411C2416.52 0 2421 4.47715 2421 10V145.758C2421 148.469 2419.9 151.064 2417.95 152.948L1217.45 1313.28C1213.57 1317.03 1207.43 1317.03 1203.55 1313.28L3.05027 152.948C1.10086 151.064 0 148.469 0 145.758Z" fill="#64748B"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="19.9219" height="19.9316">
<g>
<rect height="19.9316" opacity="0" width="19.9219" x="0" y="0"/>
<path d="M9.96094 19.9219C15.4102 19.9219 19.9219 15.4004 19.9219 9.96094C19.9219 4.51172 15.4004 0 9.95117 0C4.51172 0 0 4.51172 0 9.96094C0 15.4004 4.52148 19.9219 9.96094 19.9219ZM9.96094 18.2617C5.35156 18.2617 1.66992 14.5703 1.66992 9.96094C1.66992 5.35156 5.3418 1.66016 9.95117 1.66016C14.5605 1.66016 18.2617 5.35156 18.2617 9.96094C18.2617 14.5703 14.5703 18.2617 9.96094 18.2617ZM6.12305 10.791L13.7891 10.791C14.3359 10.791 14.707 10.498 14.707 9.98047C14.707 9.45312 14.3555 9.15039 13.7891 9.15039L6.12305 9.15039C5.55664 9.15039 5.19531 9.45312 5.19531 9.98047C5.19531 10.498 5.57617 10.791 6.12305 10.791Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="800px" height="800px" viewBox="0 0 20 20" fill="none">
<path fill="#000000" fill-rule="evenodd" d="M19 4a1 1 0 01-1 1H2a1 1 0 010-2h16a1 1 0 011 1zm0 6a1 1 0 01-1 1H2a1 1 0 110-2h16a1 1 0 011 1zm-1 7a1 1 0 100-2H2a1 1 0 100 2h16z"/>
</svg>

After

Width:  |  Height:  |  Size: 288 B

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12.4707" height="24.2449">
<g>
<rect height="24.2449" opacity="0" width="12.4707" x="0" y="0"/>
<path d="M6.24023 0.144902C2.76367 0.144902 0 2.90857 0 6.36561C0 8.97303 1.5625 11.2777 4.00391 12.2054L4.00391 21.8441C4.00391 22.0883 4.08203 22.2738 4.25781 22.4594L5.88867 24.1C6.05469 24.266 6.38672 24.3148 6.5918 24.1097L9.6875 21.014C9.89258 20.7992 9.88281 20.516 9.6875 20.3109L7.76367 18.4164L10.4004 15.7894C10.5859 15.5941 10.5859 15.3109 10.3809 15.0961L7.77344 12.4691C10.791 11.2679 12.4707 9.04139 12.4707 6.36561C12.4707 2.92811 9.6875 0.144902 6.24023 0.144902ZM6.24023 5.86756C5.33203 5.86756 4.60938 5.13514 4.60938 4.2367C4.60938 3.3285 5.32227 2.60584 6.24023 2.60584C7.13867 2.60584 7.87109 3.3285 7.87109 4.2367C7.87109 5.13514 7.13867 5.86756 6.24023 5.86756Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="19.9219" height="19.9316">
<g>
<rect height="19.9316" opacity="0" width="19.9219" x="0" y="0"/>
<path d="M9.96094 19.9219C15.4102 19.9219 19.9219 15.4004 19.9219 9.96094C19.9219 4.51172 15.4004 0 9.95117 0C4.51172 0 0 4.51172 0 9.96094C0 15.4004 4.52148 19.9219 9.96094 19.9219ZM9.96094 18.2617C5.35156 18.2617 1.66992 14.5703 1.66992 9.96094C1.66992 5.35156 5.3418 1.66016 9.95117 1.66016C14.5605 1.66016 18.2617 5.35156 18.2617 9.96094C18.2617 14.5703 14.5703 18.2617 9.96094 18.2617ZM16.6406 16.3965L16.6113 16.2891C16.1328 14.8535 13.5547 13.2812 9.96094 13.2812C6.37695 13.2812 3.79883 14.8535 3.31055 16.2793L3.28125 16.3965C5.03906 18.1348 8.05664 19.1504 9.96094 19.1504C11.875 19.1504 14.8633 18.1445 16.6406 16.3965ZM9.96094 11.6211C11.8457 11.6406 13.3105 10.0391 13.3105 7.93945C13.3105 5.9668 11.8359 4.33594 9.96094 4.33594C8.08594 4.33594 6.60156 5.9668 6.61133 7.93945C6.62109 10.0391 8.08594 11.6016 9.96094 11.6211Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="21.9922" height="21.6794">
<g>
<rect height="21.6794" opacity="0" width="21.9922" x="0" y="0"/>
<path d="M10.9961 20.3465C11.25 20.3465 11.4941 20.327 11.7578 20.3075L12.3145 21.3719C12.4316 21.5965 12.6367 21.704 12.9102 21.6747C13.1543 21.6258 13.3203 21.4403 13.3594 21.1864L13.5254 20.0047C14.0137 19.868 14.4922 19.6825 14.9512 19.4872L15.8301 20.2782C16.0156 20.454 16.25 20.4833 16.4941 20.3563C16.709 20.2294 16.7969 20.0047 16.748 19.7411L16.5039 18.579C16.9141 18.2958 17.3145 17.9735 17.6758 17.6122L18.7598 18.0614C19.0039 18.1688 19.2383 18.1102 19.4238 17.8954C19.5898 17.7098 19.5996 17.4657 19.4629 17.2411L18.8281 16.2254C19.1211 15.8251 19.3555 15.3758 19.5801 14.9071L20.7812 14.9657C21.0352 14.9852 21.2402 14.8387 21.3281 14.6044C21.4062 14.3602 21.3379 14.1258 21.1328 13.9696L20.1953 13.2274C20.3223 12.7489 20.4199 12.2508 20.4688 11.7235L21.5918 11.3622C21.8457 11.284 21.9922 11.0985 21.9922 10.8348C21.9922 10.5712 21.8457 10.3856 21.5918 10.2977L20.4688 9.94615C20.4199 9.41881 20.3223 8.93053 20.1953 8.44225L21.1328 7.70006C21.3281 7.54381 21.4062 7.3192 21.3281 7.07506C21.2402 6.84068 21.0352 6.6942 20.7812 6.71373L19.5801 6.75279C19.3555 6.28404 19.1211 5.85435 18.8281 5.43443L19.4629 4.41881C19.5996 4.21373 19.5801 3.96959 19.4238 3.78404C19.2383 3.5692 19.0039 3.52037 18.7598 3.61803L17.6758 4.05748C17.3145 3.70592 16.9141 3.37389 16.5039 3.09068L16.748 1.93834C16.8066 1.6649 16.709 1.44029 16.4941 1.3231C16.25 1.18639 16.0156 1.21568 15.8301 1.40123L14.9512 2.18248C14.4922 1.9774 14.0137 1.81139 13.5254 1.6649L13.3594 0.493026C13.3203 0.23912 13.1445 0.0535732 12.9004 0.0047451C12.6367-0.0245518 12.4219 0.0828701 12.3145 0.297714L11.7578 1.36217C11.4941 1.34264 11.25 1.33287 10.9961 1.33287C10.7324 1.33287 10.498 1.34264 10.2344 1.36217L9.66797 0.297714C9.56055 0.0828701 9.3457-0.0245518 9.08203 0.0047451C8.83789 0.0535732 8.66211 0.23912 8.63281 0.493026L8.45703 1.6649C7.96875 1.81139 7.5 1.96764 7.03125 2.18248L6.15234 1.40123C5.9668 1.21568 5.73242 1.19615 5.48828 1.3231C5.27344 1.44029 5.17578 1.6649 5.23438 1.93834L5.47852 3.09068C5.07812 3.37389 4.66797 3.70592 4.30664 4.05748L3.22266 3.61803C2.97852 3.52037 2.75391 3.5692 2.56836 3.78404C2.40234 3.96959 2.38281 4.21373 2.51953 4.41881L3.1543 5.43443C2.87109 5.85435 2.62695 6.28404 2.40234 6.75279L1.21094 6.71373C0.957031 6.6942 0.742188 6.84068 0.654297 7.07506C0.576172 7.3192 0.654297 7.54381 0.849609 7.70006L1.78711 8.44225C1.66016 8.93053 1.5625 9.41881 1.5332 9.93639L0.390625 10.2977C0.136719 10.3856 0 10.5712 0 10.8348C0 11.0985 0.136719 11.284 0.390625 11.3622L1.5332 11.7235C1.5625 12.2508 1.66016 12.7489 1.78711 13.2274L0.849609 13.9696C0.654297 14.1161 0.585938 14.3504 0.654297 14.6044C0.742188 14.8387 0.957031 14.9852 1.21094 14.9657L2.40234 14.9071C2.62695 15.3758 2.87109 15.8251 3.1543 16.2254L2.51953 17.2411C2.38281 17.4657 2.40234 17.7098 2.56836 17.8954C2.75391 18.1102 2.97852 18.1688 3.22266 18.0614L4.30664 17.6122C4.66797 17.9735 5.07812 18.2958 5.47852 18.579L5.23438 19.7411C5.18555 20.0047 5.27344 20.2294 5.48828 20.3563C5.73242 20.4833 5.9668 20.454 6.15234 20.2782L7.03125 19.4872C7.5 19.6825 7.96875 19.868 8.45703 20.0047L8.63281 21.1864C8.66211 21.4403 8.83789 21.6258 9.08203 21.6747C9.3457 21.704 9.55078 21.5965 9.66797 21.3719L10.2344 20.3075C10.4883 20.327 10.7324 20.3465 10.9961 20.3465ZM10.9961 18.8719C6.52344 18.8719 3.06641 15.2977 3.06641 10.8446C3.06641 6.3817 6.52344 2.80748 10.9961 2.80748C15.4688 2.80748 18.9258 6.3817 18.9258 10.8446C18.9258 15.2977 15.4688 18.8719 10.9961 18.8719ZM9.28711 9.23326L10.3711 8.54967L7.06055 2.8856L5.9375 3.52037ZM13.2617 11.4598L19.8535 11.4598L19.8438 10.2001L13.2617 10.2001ZM10.3809 13.1493L9.30664 12.4462L5.83984 18.12L6.95312 18.7743ZM10.9766 13.4129C12.3828 13.4129 13.5254 12.2704 13.5254 10.8544C13.5254 9.43834 12.3828 8.29576 10.9766 8.29576C9.56055 8.29576 8.41797 9.43834 8.41797 10.8544C8.41797 12.2704 9.56055 13.4129 10.9766 13.4129ZM10.9766 12.036C10.3027 12.036 9.79492 11.5184 9.79492 10.8544C9.79492 10.1903 10.3027 9.67271 10.9766 9.67271C11.6406 9.67271 12.1484 10.1903 12.1484 10.8544C12.1484 11.5184 11.6406 12.036 10.9766 12.036Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+59
View File
@@ -0,0 +1,59 @@
class Address {
final int id;
final String country;
final String postalCode;
final String county;
final String province;
final String city;
final String street;
final String houseNumber;
final double latitude;
final double longitude;
final bool active;
Address({
required this.id,
required this.country,
required this.postalCode,
required this.county,
required this.province,
required this.city,
required this.street,
required this.houseNumber,
required this.latitude,
required this.longitude,
required this.active,
});
Map<String, dynamic> toJson() {
return {
'id': id,
'country': country,
'postalCode': postalCode,
'county': county,
'province': province,
'city': city,
'street': street,
'houseNumber': houseNumber,
'latitude': latitude,
'longitude': longitude,
'active': active,
};
}
factory Address.fromJson(Map<String, dynamic> json) {
return Address(
id: json['id'] as int,
country: json['country'] as String,
postalCode: json['postalCode'] as String,
county: json['county'] as String,
province: json['province'] as String,
city: json['city'] as String,
street: json['street'] as String,
houseNumber: json['houseNumber'] as String,
latitude: (json['latitude'] as num).toDouble(),
longitude: (json['longitude'] as num).toDouble(),
active: json['active'] as bool,
);
}
}
+49
View File
@@ -0,0 +1,49 @@
import 'contact.type.dart';
class Contact {
final int id;
final ContactType contactType;
final String value;
final int priority;
final String notes;
final DateTime creationDate;
final DateTime? updateDate;
final bool active;
Contact({
required this.id,
required this.contactType,
required this.value,
required this.priority,
required this.notes,
required this.creationDate,
this.updateDate,
required this.active,
});
Map<String, dynamic> toJson() {
return {
'id': id,
'contactType': contactType.toJson(),
'value': value,
'priority': priority,
'notes': notes,
'creationDate': creationDate.toIso8601String(),
'updateDate': updateDate?.toIso8601String(),
'active': active,
};
}
factory Contact.fromJson(Map<String, dynamic> json) {
return Contact(
id: json['id'] as int,
contactType: ContactType.fromJson(json['contactType'] as Map<String, dynamic>),
value: json['value'] as String,
priority: json['priority'] as int,
notes: json['notes'] as String,
creationDate: DateTime.parse(json['creationDate'] as String),
updateDate: json['updateDate'] != null ? DateTime.parse(json['updateDate'] as String) : null,
active: json['active'] as bool,
);
}
}
+31
View File
@@ -0,0 +1,31 @@
class ContactType {
final int id;
final String type;
final String description;
final bool active;
ContactType({
required this.id,
required this.type,
required this.description,
required this.active,
});
Map<String, dynamic> toJson() {
return {
'id': id,
'type': type,
'description': description,
'active': active,
};
}
factory ContactType.fromJson(Map<String, dynamic> json) {
return ContactType(
id: json['id'] as int,
type: json['type'] as String,
description: json['description'] as String,
active: json['active'] as bool,
);
}
}
+25
View File
@@ -0,0 +1,25 @@
class Coordinates {
final double latitude;
final double longitude;
Coordinates({
required this.latitude,
required this.longitude,
});
// ---
Map<String, dynamic> toJson() {
return {
'latitude': latitude,
'longitude': longitude,
};
}
factory Coordinates.fromJson(Map<String, dynamic> json) {
return Coordinates(
latitude: (json['latitude'] as num).toDouble(),
longitude: (json['longitude'] as num).toDouble(),
);
}
}
+74
View File
@@ -0,0 +1,74 @@
// Importa le classi annidate
import 'contact.dart';
import 'vineyard.dart';
import 'address.dart';
class Owner {
final int id;
final String? name;
final String? surname;
final String? companyName;
final bool isActive;
final DateTime creationDate;
final String note;
final List<Contact>? contacts;
final List<Vineyard>? vineyards;
final List<Address>? addresses;
// Costruttore con parametri nominati e 'required'
Owner({
required this.id,
this.name,
this.surname,
this.companyName,
required this.isActive,
required this.creationDate,
required this.note,
this.contacts,
this.vineyards,
this.addresses,
});
// ---
/// Converte l'oggetto Owner in una mappa per la serializzazione JSON.
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'surname': surname,
'companyName': companyName,
'isActive': isActive,
'creationDate': creationDate.toIso8601String(),
'note': note,
'contacts': contacts?.map((contact) => contact.toJson()).toList(),
'vineyards': vineyards?.map((vineyard) => vineyard.toJson()).toList(),
'addresses': addresses?.map((address) => address.toJson()).toList(),
};
}
/// Crea un oggetto Owner da una mappa (es. da una risposta JSON).
factory Owner.fromJson(Map<String, dynamic> json) {
try{
return Owner(
id: json['id'] as int,
name: json['name'] as String,
surname: json['surname'] as String,
companyName: json['companyName'] as String,
isActive: json['isActive'] as bool,
creationDate: DateTime.parse(json['creationDate'] as String),
note: json['note'] as String,
// Mappa ogni elemento JSON in un oggetto Contact
contacts: (json['contacts'] as List).map((i) => Contact.fromJson(i as Map<String, dynamic>)).toList(),
// Mappa ogni elemento JSON in un oggetto Vineyard
vineyards: (json['vineyards'] as List).map((i) => Vineyard.fromJson(i as Map<String, dynamic>)).toList(),
// Mappa ogni elemento JSON in un oggetto Address
addresses: (json['addresses'] as List).map((i) => Address.fromJson(i as Map<String, dynamic>)).toList(),
);
}
catch (e) {
print('Errore durante la deserializzazione dell\'oggetto Owner: $e');
return Owner(id: 0, isActive: false, creationDate: DateTime.now(), note: ''); // Restituisce un oggetto Owner vuoto in caso di errore
}
}
}
+35
View File
@@ -0,0 +1,35 @@
class PlantVariety {
final int id;
final String type;
final String quality;
final String name;
final String colour;
PlantVariety({
required this.id,
required this.type,
required this.quality,
required this.name,
required this.colour,
});
Map<String, dynamic> toJson() {
return {
'id': id,
'type': type,
'quality': quality,
'name': name,
'colour': colour,
};
}
factory PlantVariety.fromJson(Map<String, dynamic> json) {
return PlantVariety(
id: json['id'] as int,
type: json['type'] as String,
quality: json['quality'] as String,
name: json['name'] as String,
colour: json['colour'] as String,
);
}
}
+33
View File
@@ -0,0 +1,33 @@
class Role {
// Proprietà della classe
final int id;
final String name;
final String description;
// Costruttore con parametri nominati e 'required'
Role({
required this.id,
required this.name,
required this.description,
});
// ---
/// Converte l'oggetto Role in una mappa per la serializzazione JSON.
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'description': description,
};
}
/// Crea un oggetto Role da una mappa (es. da una risposta JSON).
factory Role.fromJson(Map<String, dynamic> json) {
return Role(
id: json['id'] as int,
name: json['name'] as String,
description: json['description'] as String,
);
}
}
+51
View File
@@ -0,0 +1,51 @@
// Assumiamo che la classe VinePlant sia stata definita in un file 'vine_plant.dart'
import 'vine.plant.dart';
class Row {
final int id;
final int vineyardId;
final int rowNum;
final double length;
final List<VinePlant>? vinePlants;
// Costruttore con parametri nominati.
// 'vinePlants' è opzionale perché è nullable.
Row({
required this.id,
required this.vineyardId,
required this.rowNum,
required this.length,
this.vinePlants,
});
// ---
/// Converte l'oggetto Row in una mappa per la serializzazione JSON.
Map<String, dynamic> toJson() {
return {
'id': id,
'vineyardId': vineyardId,
'rowNum': rowNum,
'length': length,
// Se la lista non è null, la converte in una lista di mappe
'vinePlants': vinePlants?.map((plant) => plant.toJson()).toList(),
};
}
/// Crea un oggetto Row da una mappa (es. da una risposta JSON).
factory Row.fromJson(Map<String, dynamic> json) {
// La lista viene creata solo se esiste e non è null nella mappa JSON
final List<dynamic>? plantsJson = json['vinePlants'];
final List<VinePlant>? plantsList = plantsJson != null
? plantsJson.map((json) => VinePlant.fromJson(json as Map<String, dynamic>)).toList()
: null;
return Row(
id: json['id'] as int,
vineyardId: json['vineyardId'] as int,
rowNum: json['rowNum'] as int,
length: (json['length'] as num).toDouble(),
vinePlants: plantsList,
);
}
}
+61
View File
@@ -0,0 +1,61 @@
// Importa le classi annidate
import 'role.dart';
import 'owner.dart';
class User {
final int? id;
final String? username;
final String? password;
final Role? role;
final bool? active;
final List<Owner>? owners;
// Costruttore con parametri nominati e 'required'
User({
this.id,
this.username,
this.password,
this.role,
this.active,
this.owners,
});
// ---
/// Converte l'oggetto User in una mappa per la serializzazione JSON.
Map<String, dynamic> toJson() {
try{
return {
'id': id,
'username': username,
'password': password,
'role': role?.toJson(), // Chiama il metodo toJson() della classe Role
'active': active,
'owners': owners?.map((owner) => owner.toJson()).toList(), // Converte la lista in una lista di mappe JSON
};
} catch (e) {
print('Errore durante la serializzazione dell\'oggetto User: $e');
return {};
}
}
/// Crea un oggetto User da una mappa (es. da una risposta JSON).
factory User.fromJson(Map<String, dynamic> json) {
final Map<String, dynamic> userJson = json['user'] as Map<String, dynamic>;
try{
return User(
id: userJson['id'] as int,
username: userJson['username'] as String?,
password: userJson['password'] as String?,
role: Role.fromJson(userJson['role'] as Map<String, dynamic>), // Crea un oggetto Role dalla mappa annidata
active: json['active'] as bool?,
owners: (userJson['owners'] as List)
.map((i) => Owner.fromJson(i as Map<String, dynamic>))
.toList(), // Mappa ogni elemento JSON in un oggetto Owner
);
} catch (e) {
print('Errore durante la deserializzazione dell\'oggetto User: $e');
return User(); // Restituisce un oggetto User vuoto in caso di errore
}
}
}
+48
View File
@@ -0,0 +1,48 @@
// Assumiamo che la classe PlantVariety sia stata definita in un file 'plant_variety.dart'
import 'plant.variety.dart';
class VinePlant {
// Proprietà della classe
final int id;
final int rowId;
final int plantNumberInRow;
final int varietyId;
final PlantVariety variety;
final DateTime plantingDate;
// Costruttore con parametri nominati
VinePlant({
required this.id,
required this.rowId,
required this.plantNumberInRow,
required this.varietyId,
required this.variety,
required this.plantingDate,
});
// ---
/// Converte l'oggetto VinePlant in una mappa per la serializzazione JSON.
Map<String, dynamic> toJson() {
return {
'id': id,
'rowId': rowId,
'plantNumberInRow': plantNumberInRow,
'varietyId': varietyId,
'variety': variety.toJson(),
'plantingDate': plantingDate.toIso8601String(),
};
}
/// Crea un oggetto VinePlant da una mappa (es. da una risposta JSON).
factory VinePlant.fromJson(Map<String, dynamic> json) {
return VinePlant(
id: json['id'] as int,
rowId: json['rowId'] as int,
plantNumberInRow: json['plantNumberInRow'] as int,
varietyId: json['varietyId'] as int,
variety: PlantVariety.fromJson(json['variety'] as Map<String, dynamic>),
plantingDate: DateTime.parse(json['plantingDate'] as String),
);
}
}
+87
View File
@@ -0,0 +1,87 @@
// Assumiamo che le classi Coordinates e Row siano definite
// in file separati
import 'coordinates.dart';
import 'row.dart';
class Vineyard {
final int id;
final String name;
final String location;
final double hectares;
final Coordinates? coordinates;
final DateTime creationDate;
final List<Row>? rows;
final Map<int, Coordinates>? area;
// Costruttore con parametri nominati.
// 'rows' è opzionale perché è nullable.
Vineyard({
required this.id,
required this.name,
required this.location,
required this.hectares,
this.coordinates,
required this.creationDate,
this.rows,
this.area,
});
// ---
/// Converte l'oggetto Vineyard in una mappa per la serializzazione JSON.
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'location': location,
'hectares': hectares,
'coordinates': coordinates?.toJson(),
'creationDate': creationDate.toIso8601String(),
// Se 'rows' non è null, lo converte in una lista di mappe JSON
'rows': rows?.map((row) => row.toJson()).toList(),
// Converte la mappa 'area'
'area': area?.map((key, value) => MapEntry(key.toString(), value.toJson())),
};
}
/// Crea un oggetto Vineyard da una mappa (es. da una risposta JSON).
factory Vineyard.fromJson(Map<String, dynamic> json) {
try{
// Gestione della lista di 'rows'
final List<dynamic>? rowsJson = json['rows'];
final List<Row>? rowsList = rowsJson?.map((json) => Row.fromJson(json as Map<String, dynamic>)).toList();
// Gestione della mappa 'area'
final Map<dynamic, dynamic> areaJson = json['area'] as Map<dynamic, dynamic>;
final Map<int, Coordinates> areaMap = areaJson.map(
(key, value) => MapEntry(
int.parse(key as String), // Converte la chiave da String a int
Coordinates.fromJson(value as Map<String, dynamic>),
),
);
return Vineyard(
id: json['id'] as int,
name: json['name'] as String,
location: json['location'] as String,
hectares: (json['hectares'] as num).toDouble(),
coordinates: null,//Coordinates.fromJson(json['coordinates'] as Map<String, dynamic>),
creationDate: DateTime.parse(json['creationDate'] as String),
rows: rowsList,
area: areaMap,
);
} catch (e) {
print('Errore durante la deserializzazione dell\'oggetto Vineyard: $e');
return Vineyard(
id: 0,
name: '',
location: '',
hectares: 0.0,
coordinates: null,
creationDate: DateTime.now(),
rows: [],
area: {},
); // Restituisce un oggetto Vineyard vuoto in caso di errore
}
}
}
+52
View File
@@ -0,0 +1,52 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get_navigation/src/root/get_material_app.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:u_vineyard/template/src/classes/constents.class.dart';
import 'package:u_vineyard/template/src/classes/functions.class.dart';
import 'package:u_vineyard/template/src/classes/routes.class.dart';
import 'package:u_vineyard/template/src/platform/platform_functions.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
PlatformFunctions.init();
await initializeProviders();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Dashboard',
debugShowCheckedModeBanner: false,
getPages: appRoutes,
initialRoute: appRoutes.first.name,
scrollBehavior: const MaterialScrollBehavior().copyWith(
dragDevices: {
PointerDeviceKind.mouse,
PointerDeviceKind.touch,
PointerDeviceKind.stylus,
PointerDeviceKind.unknown
},
),
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: primaryColor).copyWith(
surfaceTint: Colors.transparent,
),
textSelectionTheme: TextSelectionThemeData(
cursorColor: primaryColor,
selectionColor: primaryColor.withOpacity(.3),
),
useMaterial3: true,
textTheme: GoogleFonts.poppinsTextTheme(),
),
);
}
}
+287
View File
@@ -0,0 +1,287 @@
// import '../../../widgets/responsive_widgets/responsive.widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:u_vineyard/services/api.service.dart';
import 'package:u_vineyard/template/src/classes/enums.class.dart';
import 'package:u_vineyard/template/src/classes/functions.class.dart';
import 'package:u_vineyard/template/src/providers/alert.provider.dart';
import 'package:u_vineyard/template/src/providers/auth.provider.dart';
import 'package:u_vineyard/template/src/widgets/responsive_widgets/responsive.widget.dart';
import 'package:u_vineyard/template/src/widgets/simple_loader.widget.dart';
// import '../../../widgets/simple_loader.widget.dart';
class LoginPage extends StatefulWidget {
static const route = '/login';
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
bool isVisible = false;
bool isLoading = false;
String? error;
@override
void dispose() {
emailController.dispose();
passwordController.dispose();
super.dispose();
}
update(VoidCallback func) {
if (mounted) setState(func);
}
bool validate() {
final email = emailController.text;
final pass = passwordController.text;
if(email != "admin"){
if (email.isEmpty) {
return !setError('The email address is required');
}
if (!email.isEmail) {
return !setError('The email address is inviled');
}
if (pass.isEmpty) {
return !setError('The password is required');
}
}
return true;
}
login() async {
setError('');
update(() => isLoading = true);
final state = validate();
if (state) {
TextInput.finishAutofillContext();
await Future.delayed(const Duration(seconds: 1), () async {
ApiService.login(
emailController.text,
passwordController.text,
).then((value) {
if (value == '200') {
Get.find<AuthProvider>().toggleAuth(true);
Get.offAllNamed('/');
} else {
setError('Login failed: $value');
}
}).catchError((e) {
setError('Login failed: $e');
});
Get.offAllNamed('/');
});
initializeProviders();
}
update(() => isLoading = false);
}
togglePass() {
if (mounted) setState(() => isVisible = !isVisible);
}
bool setError(String error) {
final alerter = Get.find<AlertProvider>();
alerter.setAlert(
error,
type: AlertType.danger,
dismissable: false,
);
if (mounted) {
setState(() {});
}
if (error.isEmpty) return false;
return true;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ResponsiveWidget(
builder: (cnx, screen) => Container(
width: double.infinity,
height: double.infinity,
decoration: !screen.isMobile
? BoxDecoration(
image: DecorationImage(
image: AssetImage(imgUrl('login.jpg')),
fit: BoxFit.cover,
),
)
: null,
child: Center(
child: SingleChildScrollView(
physics:
screen.isBig ? const NeverScrollableScrollPhysics() : null,
child: Container(
width: !screen.isMobile ? 550 : null,
decoration: BoxDecoration(
color: !screen.isMobile ? Colors.white : null,
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 50),
Text(
'Welcome Back',
style:
Theme.of(context).textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.w600,
color: const Color(0xff0f0f0f),
),
),
const SizedBox(height: 50),
GetBuilder<AlertProvider>(
init: AlertProvider(),
builder: (alerter) {
return Padding(
padding: const EdgeInsets.only(
bottom: 20,
left: 20,
right: 20,
),
child: alerter.alert ?? const SizedBox(),
);
},
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: AutofillGroup(
child: Column(
children: [
TextField(
controller: emailController,
autofocus: true,
autofillHints: const [AutofillHints.email],
decoration: InputDecoration(
labelText: 'Email',
icon: SizedBox(
width: 20,
child: svg(
'profile',
color: Colors.grey.shade800,
),
),
filled: true,
fillColor: const Color(0xFFf0f1f5),
border: const OutlineInputBorder(
borderSide: BorderSide(
color: Color(0xFFf0f1f5),
),
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(
color: Color(0xFFf0f1f5),
),
),
),
onChanged: (value) => setError(''),
onEditingComplete:
TextInput.finishAutofillContext,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.emailAddress,
onSubmitted: (_) => login(),
),
const SizedBox(height: 20),
TextField(
autofillHints: const [AutofillHints.password],
controller: passwordController,
autofocus: false,
obscureText: !isVisible,
decoration: InputDecoration(
labelText: 'Password',
icon: SizedBox(
width: 20,
child: svg(
'password',
color: Colors.grey.shade800,
),
),
suffixIcon: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: IconButton(
onPressed: togglePass,
icon: isVisible
? svg('eye.slash.fill',
size: 16,
color: Colors.grey.shade800)
: svg('eye.fill',
size: 15,
color: Colors.grey.shade800),
),
),
filled: true,
fillColor: const Color(0xFFf0f1f5),
border: const OutlineInputBorder(
borderSide: BorderSide(
color: Color(0xFFf0f1f5),
),
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(
color: Color(0xFFf0f1f5),
),
),
),
onChanged: (value) => setError(''),
onEditingComplete:
TextInput.finishAutofillContext,
textInputAction: TextInputAction.go,
keyboardType: TextInputType.visiblePassword,
onSubmitted: (_) => login(),
),
const SizedBox(height: 50),
SizedBox(
width: 300,
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
),
onPressed: isLoading ? null : login,
child: AnimatedCrossFade(
crossFadeState: !isLoading
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: const Duration(milliseconds: 300),
alignment: Alignment.center,
firstChild: const Text('Login'),
secondChild: const Center(
child: SimpleLoader(
strokeWidth: 3,
size: 20,
),
),
),
),
)
],
),
),
),
const SizedBox(height: 50, width: 200),
],
),
),
),
),
),
),
);
}
}
+250
View File
@@ -0,0 +1,250 @@
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:u_vineyard/services/polygon.area.calculator.service.dart';
import 'package:u_vineyard/template/src/widgets/card.widget.dart';
import 'package:u_vineyard/template/src/widgets/responsive_widgets/repesponsive_grid_item.widget.dart';
import 'package:u_vineyard/template/src/widgets/responsive_widgets/responsive_grid.widget.dart';
import 'package:u_vineyard/widgets/map.widget.dart';
class NewVineyardScreen extends StatefulWidget {
const NewVineyardScreen({super.key});
@override
State<NewVineyardScreen> createState() => _NewVineyardScreenState(); // Correzione: nome della classe State
}
class _NewVineyardScreenState extends State<NewVineyardScreen> { // Correzione: nome della classe State
// Aggiungi un TextEditingController per il TextFormField
final TextEditingController _nomeVignaController = TextEditingController();
final TextEditingController _superficieController = TextEditingController();
List<LatLng> _polygonPoints = [];
double _calculatedArea = 0.0; // Area calcolata, inizialmente impostata a 0
final TextEditingController _localitaController = TextEditingController();
@override
void dispose() {
_nomeVignaController.dispose(); // Libera il controller quando il widget viene eliminato
_superficieController.dispose(); // Libera il controller quando il widget viene eliminato
_localitaController.dispose(); // Libera il controller quando il widget viene eliminato
super.dispose();
}
void _handleMapTap(TapPosition tapPosition, LatLng latLng) {
setState(() {
_polygonPoints.add(latLng);
_calculatedArea = PolygonAreaCalculator.calculateAreaInHectares(_polygonPoints);
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Punto aggiunto: ${latLng.latitude.toStringAsFixed(4)}, ${latLng.longitude.toStringAsFixed(4)}'),
duration: const Duration(milliseconds: 800),
),
);
}
void _clearPolygon() {
setState(() {
_polygonPoints.clear();
_calculatedArea = 0.0;
_superficieController.clear();
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Poligono e superficie resettati.'),
duration: Duration(milliseconds: 800),
),
);
}
void _showAreaConfirmationDialog() {
if (_calculatedArea > 0) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Conferma Superficie'),
content: Text(
'L\'area calcolata del poligono è di ${_calculatedArea.toStringAsFixed(2)} ettari.\n\nVuoi utilizzare questo valore o inserirlo manualmente?'),
actions: <Widget>[
TextButton(
child: const Text('Inserisci Manualmente'),
onPressed: () {
Navigator.of(context).pop();
_superficieController.clear();
},
),
FilledButton(
child: const Text('Usa Valore Calcolato'),
onPressed: () {
setState(() {
_superficieController.text = _calculatedArea.toStringAsFixed(2);
});
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
void _submitForm() {
//if (_formKey.currentState!.validate()) {
if (true) {
if (_polygonPoints.length < 3) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Disegna almeno 3 punti per il poligono della vigna.')),
);
return;
}
print('--- Dati Vigna ---');
print('Nome Vigna: ${_nomeVignaController.text}');
print('Località: ${_localitaController.text}');
print('Superficie (ha): ${_superficieController.text}');
print('Coordinate Poligono:');
_polygonPoints.forEach((point) {
print(' Lat: ${point.latitude}, Lng: ${point.longitude}');
});
print('-----------------');
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Dati inviati (simulato)! Controlla la console.')),
);
}
}
@override
Widget build(BuildContext context) {
return ResponsiveGrid(
childrenBuilder: (context, screen) {
return [
ResponsiveGridItem(
crossAxisCellCount: screen.setAxis(12, 12, 12, 12),
child: Container(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CardWidget(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Aggiungi Nuova Vigna',
style: Theme.of(context).textTheme.titleLarge,
),
),
),
const SizedBox(height: 16.0), // Spazio dopo il CardWidget
// *** INIZIO DELLA CORREZIONE ***
Row(
children: [
Expanded( // <--- AVVOLGI IL TextFormField IN UN Expanded
child: TextFormField(
controller: _nomeVignaController, // Collega il controller
decoration: const InputDecoration(
labelText: 'Nome Vigna',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.grass),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Inserisci il nome della vigna';
}
return null;
},
),
),
],
),
const SizedBox(height: 12),
TextFormField(
controller: _localitaController,
decoration: const InputDecoration(
labelText: 'Località',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.location_on),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Inserisci la località';
}
return null;
},
),
const SizedBox(height: 12),
TextFormField(
//controller: superficieController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Superficie (ettari)',
border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.area_chart),
suffixIcon: _calculatedArea > 0
? IconButton(
icon: const Icon(Icons.auto_mode, color: Colors.green),
onPressed: _showAreaConfirmationDialog, // Mostra il dialogo di conferma
tooltip: 'Usa area calcolata',
)
: null,
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Inserisci la superficie';
}
if (double.tryParse(value) == null) {
return 'Inserisci un numero valido';
}
return null;
},
),
// *** FINE DELLA CORREZIONE ***
// Add your form or content here
Row(
children: [
Expanded(
child: VignaMapWidget(
polygonPoints: _polygonPoints,
onMapTap: _handleMapTap,
onClearPolygon: _clearPolygon,
calculatedArea: _calculatedArea,
),
),
],
),
Row(
children: [
Expanded(
child: SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: _submitForm,
icon: const Icon(Icons.send),
label: const Text(
'Invia Dati Vigna',
style: TextStyle(fontSize: 18),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green[800],
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
),
),
],
),
],
),
),
),
];
},
);
}
}
+71
View File
@@ -0,0 +1,71 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'auth.service.dart';
class ApiService {
static const String _baseUrl = 'http://192.168.0.9:5000'; // cambia qui
// Token memorizzato in memoria (per sessione)
static String? _token;
static String? get token => _token;
static String get baseUrl => _baseUrl;
// Login con Basic Auth e salvataggio token
static Future<String> login(String username, String password) async {
final url = Uri.parse('$_baseUrl/User/login');
// Header con Basic Auth
String basicAuth =
'Basic ${base64Encode(utf8.encode('$username:$password'))}';
final response = await http.get(
url,
headers: {
'Authorization': basicAuth,
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
_token = data['access_token']; // salva il token in memoria
print('Token ricevuto: $_token'); // stampa in console
AuthService.instance.saveToken(_token!);
return '${response.statusCode}';
} else {
throw Exception(
'Login fallito: ${response.statusCode} - ${response.body}');
}
}
static Future<dynamic> checkLogin() async {
final token = AuthService.instance.token;
print('Token corrente: $token'); // stampa in console
if (token == null) {
print('Token non disponibile. Effettua il login prima.'); // stampa in console
throw Exception('Token non disponibile. Effettua il login prima.');
}
final url = Uri.parse('$_baseUrl/Test/cklogin');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
final object = jsonDecode(response.body);
print('Risposta cklogin: $object'); // stampa in console
return object;
} else {
throw Exception(
'Errore checkLogin: ${response.statusCode} - ${response.body}');
}
}
}
+42
View File
@@ -0,0 +1,42 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:u_vineyard/services/auth.service.dart';
import '../entities/user.dart';
import 'api.service.dart';
class UserService {
static final String _baseUrl = ApiService.baseUrl;
Future<User?> userProfile(int userId) async {
String token = AuthService.instance.token ?? '';
if (token.isEmpty) {
print('Token non disponibile. Effettua il login prima.');
return null; // Gestisci il caso in cui il token non sia disponibile
}
try {
final url = Uri.parse('$_baseUrl/Test/cklogin');
final response = await http.get(
url,
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
// Decodifica la risposta JSON
final Map<String, dynamic> jsonMap = json.decode(response.body);
// Crea e restituisce un oggetto User usando il costruttore fromJson
return User.fromJson(jsonMap);
} else {
// Gestisci le risposte con stato diverso da 200 (es. 404, 500)
print('Errore: La richiesta non è andata a buon fine. Status code: ${response.statusCode}');
return null;
}
} catch (e) {
// Gestisci eventuali eccezioni (es. nessuna connessione, URL errato)
print('Errore durante il recupero dei dati: $e');
return null;
}
}
}
+125
View File
@@ -0,0 +1,125 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:local_auth/local_auth.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AuthService {
static final AuthService _instance = AuthService._internal();
static AuthService get instance => _instance;
AuthService._internal();
final _secureStorage = const FlutterSecureStorage(); // Per piattaforme mobili
// Non inizializzare SharedPreferences qui direttamente, perché è async
String? _token;
static const String _tokenKey = 'AuthToken'; // Chiave comune per storage
String? get token => _token;
// Questa funzione ora serve solo per la logica specifica mobile (es. biometrica)
// Non usarla per decidere dove salvare il token, usa kIsWeb direttamente
Future<bool> _isMobileOrDesktopPlatform() async {
if (kIsWeb) return false;
// Android, iOS, Windows, Linux, macOS
//final deviceInfo = DeviceInfoPlugin();
if (defaultTargetPlatform == TargetPlatform.android ||
defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.windows ||
defaultTargetPlatform == TargetPlatform.linux ||
defaultTargetPlatform == TargetPlatform.macOS) {
return true;
}
return false;
}
// Nuova funzione per salvare il token
Future<void> saveToken(String token) async {
_token = token; // Aggiorna il token in memoria
print('AuthToken: Tentativo di salvataggio token: $token');
if (kIsWeb) {
// Per Web: usa SharedPreferences (che su web usa localStorage)
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_tokenKey, token);
print('AuthToken: Token salvato in SharedPreferences (Web).');
} else if (await _isMobileOrDesktopPlatform()) {
// Per Mobile/Desktop: usa FlutterSecureStorage
await _secureStorage.write(key: _tokenKey, value: token);
print('AuthToken: Token salvato in FlutterSecureStorage (Mobile/Desktop).');
}
}
// Nuova funzione per caricare il token (senza biometria)
Future<String?> _loadTokenFromStorage() async {
if (kIsWeb) {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(_tokenKey);
} else if (await _isMobileOrDesktopPlatform()) {
return _secureStorage.read(key: _tokenKey);
}
return null; // Caso non supportato
}
Future<bool> loadTokenWithBiometric() async {
// Prima, prova sempre a caricare il token dallo storage generale
// Questo è il token che verra' utilizzato se la biometria fallisce o non è disponibile.
_token = await _loadTokenFromStorage();
if (_token != null && !await _isMobileOrDesktopPlatform()) {
// Se siamo su web e il token è stato caricato, l'autenticazione è implicita (no biometria)
print('AuthToken: Token caricato da storage (Web), biometria non applicabile.');
return true;
}
// Se non è una piattaforma mobile/desktop supportata per la biometria, o se il token non c'è,
// o se la biometria non è disponibile/non supportata, gestisci di conseguenza.
if (!await _isMobileOrDesktopPlatform()) {
print('AuthToken: Biometria non disponibile su questa piattaforma.');
return false;
}
try {
final auth = LocalAuthentication();
final canAuth = await auth.canCheckBiometrics || await auth.isDeviceSupported();
if (!canAuth) {
print('AuthToken: Dispositivo non supporta biometria.');
// Se la biometria non è supportata, ma un token esiste, consideralo loggato
return _token != null;
}
final authenticated = await auth.authenticate(
localizedReason: 'Autenticati per accedere',
options: const AuthenticationOptions(
biometricOnly: true,
stickyAuth: true,
),
);
if (authenticated) {
final stored = await _secureStorage.read(key: _tokenKey); // Rileggi da secure storage
_token = stored; // Aggiorna il token in memoria con quello autenticato biometricamente
print('AuthToken: Biometria riuscita, token da storage sicuro: $_token');
return stored != null;
} else {
print('AuthToken: Autenticazione biometrica fallita.');
_token = null; // Se la biometria fallisce, resetta il token in memoria
}
} catch (e) {
debugPrint('AuthToken: Errore autenticazione biometrica: $e');
_token = null; // In caso di errore, resetta il token
}
return false;
}
Future<void> clear() async {
_token = null;
print('AuthToken: Tentativo di cancellazione token.');
if (kIsWeb) {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_tokenKey);
print('AuthToken: Token cancellato da SharedPreferences (Web).');
} else if (await _isMobileOrDesktopPlatform()) {
await _secureStorage.delete(key: _tokenKey);
print('AuthToken: Token cancellato da FlutterSecureStorage (Mobile/Desktop).');
}
}
}
@@ -0,0 +1,40 @@
// utils/polygon_area_calculator.dart
import 'package:latlong2/latlong.dart';
import 'dart:math';
class PolygonAreaCalculatorService {
// Costante per il raggio medio della Terra in metri (WGS84 ellipsoid semi-major axis)
static const double _earthRadius = 6378137.0;
/// Calcola l'area di un poligono su una sfera (Terra) in ettari.
/// Implementa una versione della formula di Shoelace per coordinate geodetiche.
/// Restituisce 0.0 se i punti sono meno di 3.
static double calculateAreaInHectares(List<LatLng> points) {
if (points.length < 3) return 0.0;
double area = 0.0;
// La formula di Shoelace richiede che il poligono sia chiuso (primo punto = ultimo punto)
List<LatLng> closedPoints = List.from(points);
if (closedPoints.first != closedPoints.last) {
closedPoints.add(closedPoints.first);
}
for (int i = 0; i < closedPoints.length - 1; i++) {
LatLng p1 = closedPoints[i];
LatLng p2 = closedPoints[i + 1];
// Conversione delle latitudini e longitudini da gradi a radianti
double lat1Rad = p1.latitude * pi / 180.0;
double lon1Rad = p1.longitude * pi / 180.0;
double lat2Rad = p2.latitude * pi / 180.0;
double lon2Rad = p2.longitude * pi / 180.0;
// Formula per l'area di un segmento sferico
area += (lon2Rad - lon1Rad) * (2 + sin(lat1Rad) + sin(lat2Rad));
}
area = (area * _earthRadius * _earthRadius / 2.0).abs();
// Converti da metri quadrati a ettari (1 ettaro = 10000 m^2)
return area / 10000.0;
}
}
@@ -0,0 +1,40 @@
// utils/polygon_area_calculator.dart
import 'package:latlong2/latlong.dart';
import 'dart:math';
class PolygonAreaCalculator {
// Costante per il raggio medio della Terra in metri (WGS84 ellipsoid semi-major axis)
static const double _earthRadius = 6378137.0;
/// Calcola l'area di un poligono su una sfera (Terra) in ettari.
/// Implementa una versione della formula di Shoelace per coordinate geodetiche.
/// Restituisce 0.0 se i punti sono meno di 3.
static double calculateAreaInHectares(List<LatLng> points) {
if (points.length < 3) return 0.0;
double area = 0.0;
// La formula di Shoelace richiede che il poligono sia chiuso (primo punto = ultimo punto)
List<LatLng> closedPoints = List.from(points);
if (closedPoints.first != closedPoints.last) {
closedPoints.add(closedPoints.first);
}
for (int i = 0; i < closedPoints.length - 1; i++) {
LatLng p1 = closedPoints[i];
LatLng p2 = closedPoints[i + 1];
// Conversione delle latitudini e longitudini da gradi a radianti
double lat1Rad = p1.latitude * pi / 180.0;
double lon1Rad = p1.longitude * pi / 180.0;
double lat2Rad = p2.latitude * pi / 180.0;
double lon2Rad = p2.longitude * pi / 180.0;
// Formula per l'area di un segmento sferico
area += (lon2Rad - lon1Rad) * (2 + sin(lat1Rad) + sin(lat2Rad));
}
area = (area * _earthRadius * _earthRadius / 2.0).abs();
// Converti da metri quadrati a ettari (1 ettaro = 10000 m^2)
return area / 10000.0;
}
}
+90
View File
@@ -0,0 +1,90 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'src/models/dashboard_models/dashboard_card.model.dart';
final demoUsersList = List.generate(
20,
(i) => UsersModel.fromMap({
'id': i.toString(),
'avatar':
'https://cdn.dribbble.com/users/1500210/avatars/normal/ebcc769d2f155e72aa024bdafadc28cc.jpg?1629718724&resize=80x80',
'name': 'user $i',
'dateOfBirth': DateTime.now().toLocal(),
'gender': i.isEven ? "male" : "female",
'email': 'user$i@codestein.dev',
'phone': (Random.secure().nextInt(9999999) + 1999999).toString(),
'status': i.isEven,
}),
);
class UsersModel {
final String id;
final String avatar;
final String name;
final DateTime dateOfBirth;
final String gender;
final String email;
final String phone;
bool status;
UsersModel({
required this.id,
required this.avatar,
required this.name,
required this.dateOfBirth,
required this.gender,
required this.email,
required this.phone,
this.status = false,
});
factory UsersModel.fromMap(Map<String, dynamic> map) {
return UsersModel(
id: map['id'],
avatar: map['avatar'],
name: map['name'],
dateOfBirth: map['dateOfBirth'],
gender: map['gender'],
email: map['email'],
phone: map['phone'],
status: map['status'] ?? false,
);
}
}
// final dashboardCardModelValues = [
// DashboardCardModel.fromJson({
// 'name': 'Projects',
// 'icon': Icons.wine_bar,
// 'value': 327,
// 'persentage': 32.1,
// 'persentageValue': '2.1',
// 'notes': '8k social visitors',
// }),
// DashboardCardModel.fromJson({
// 'name': 'Stock Qty',
// 'icon': Icons.add_chart_rounded,
// 'value': 275,
// 'persentage': 64.1,
// 'persentageValue': '3.1',
// 'notes': 'Total 424,567 deliveries',
// }),
// DashboardCardModel.fromJson({
// 'name': 'C APEX',
// 'icon': Icons.apple_rounded,
// 'value': 648,
// 'persentage': 72.1,
// 'persentageValue': '12.1',
// 'notes': 'Counted in Millions',
// }),
// DashboardCardModel.fromJson({
// 'name': 'Saving',
// 'icon': Icons.data_saver_off_rounded,
// 'value': 18478,
// 'persentage': 24.1,
// 'persentageValue': '0.1',
// 'notes': 'Reports by states and ganders',
// }),
// ];
+50
View File
@@ -0,0 +1,50 @@
import 'src/classes/constents.class.dart';
import 'src/platform/platform_functions.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import 'src/classes/functions.class.dart';
import 'src/classes/routes.class.dart';
// void main() async {
// WidgetsFlutterBinding.ensureInitialized();
// PlatformFunctions.init();
// await initializeProviders();
// runApp(const MyApp());
// }
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Dashboard',
debugShowCheckedModeBanner: false,
getPages: appRoutes,
initialRoute: appRoutes.first.name,
scrollBehavior: const MaterialScrollBehavior().copyWith(
dragDevices: {
PointerDeviceKind.mouse,
PointerDeviceKind.touch,
PointerDeviceKind.stylus,
PointerDeviceKind.unknown
},
),
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: primaryColor).copyWith(
surfaceTint: Colors.transparent,
),
textSelectionTheme: TextSelectionThemeData(
cursorColor: primaryColor,
selectionColor: primaryColor.withOpacity(.3),
),
useMaterial3: true,
textTheme: GoogleFonts.poppinsTextTheme(),
),
);
}
}
@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
const Color primaryColor = Colors.blueAccent;
const Color navbarColor = Colors.white;
const Color drawerColor = Colors.white;
const bool toastAutoDissmiss = true;
const Duration toastDuration = Duration(milliseconds: 200);
const Duration toastDissmissDuration = Duration(seconds: 4);
// this is the maximum width the main container can take as width => in web called (fixed, fluid)
// it can be double.infinity or fixed double like 1600.0
const double maxContainerWidth = 1600;
// if true a BreadCampWidget will be showen at the top of the main container
// you can add or edit this widget as you like, you will find it in the /src/widgets/app_widgets.
const bool showBreadCamp = false;
const List<BoxShadow> cardShadow = [
BoxShadow(
color: Color(0x1F6E9AE6),
offset: Offset(0, 12),
blurRadius: 20,
spreadRadius: .05,
),
];
@@ -0,0 +1,9 @@
enum AlertType { primary, success, danger, warning, info }
enum ToastType { primary, success, danger, warning, info }
enum ScreenSizeType { desktop, tablet, mobile }
enum DissmissType { auto, click, swipe }
enum DrawerItemType { link, menu }
@@ -0,0 +1,165 @@
import 'dart:math';
import 'constents.class.dart';
import 'enums.class.dart';
import 'routes.class.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import '../providers/alert.provider.dart';
import '../providers/auth.provider.dart';
import '../providers/routes.provider.dart';
import '../providers/search.provider.dart';
import '../providers/toast.provider.dart';
String imgUrl(String url) {
if (kIsWeb) return 'images/$url';
return 'images/$url';
}
Widget svg(String name, {double size = 20, Color? color}) {
try {
final String assetName = 'images/svgs/$name.svg';
return SvgPicture.asset(
assetName,
width: size,
height: size,
colorFilter: ColorFilter.mode(color ?? primaryColor, BlendMode.srcIn),
);
} catch (e) {
//
}
return const SizedBox();
}
alert(
String message, {
AlertType type = AlertType.primary,
Duration autoDismissAfter = Duration.zero,
}) {
Get.find<AlertProvider>().setAlert(
message,
type: type,
autoDismissAfter: autoDismissAfter,
);
}
toast(
String? message, {
ToastType type = ToastType.primary,
VoidCallback? callback,
}) {
Get.find<ToastProvider>().addToast(message, type: type, callback: callback);
}
void showModel(String type) {
final r = Random.secure().nextInt(5);
switch (r) {
case 0:
alert(AlertType.primary.toString(), type: AlertType.primary);
break;
case 1:
alert(AlertType.success.toString(), type: AlertType.success);
break;
case 2:
alert(AlertType.warning.toString(), type: AlertType.warning);
break;
case 3:
alert(AlertType.danger.toString(), type: AlertType.danger);
break;
case 4:
alert(AlertType.info.toString(), type: AlertType.info);
break;
default:
alert(AlertType.primary.toString(), type: AlertType.primary);
}
// Get.defaultDialog(content: SelectableText(type));
}
Future<void> initializeProviders() async {
Get.put(AuthProvider(), permanent: true);
Get.put(AlertProvider(), permanent: true);
Get.put(RoutesProvider());
Get.put(SearchProvider());
Get.put(ToastProvider());
}
Future<void> removeProviders() async {
await Get.delete<RoutesProvider>(force: true);
await Get.delete<SearchProvider>(force: true);
await Get.delete<ToastProvider>(force: true);
}
closeDrawerMenu(String item) {
for (var child in drawerMenu) {
if (child.type == DrawerItemType.menu) {
child.isOpen = false;
for (var subChild in child.children) {
if (subChild.route == item) {
child.isOpen = true;
} else if (subChild.type == DrawerItemType.menu) {
subChild.isOpen = false;
for (var subsubChild in subChild.children) {
if (subsubChild.route == item) {
child.isOpen = true;
subChild.isOpen = true;
}
}
}
}
}
}
}
int menuIndex(String item) {
for (var child in drawerMenu) {
if (child.type == DrawerItemType.menu) {
for (var subChild in child.children) {
if (subChild.type == DrawerItemType.menu) {
for (var subsubChild in subChild.children) {
if (subsubChild.route == item) {
return drawerMenu.indexOf(child);
}
}
} else {
if (subChild.route == item) {
return drawerMenu.indexOf(child);
}
}
}
} else {
if (child.route == item) {
return drawerMenu.indexOf(child);
}
}
}
return 0;
}
void focusSearch() {
Get.find<SearchProvider>().focus();
}
String formatDateTime(DateTime value) {
int hours = value.hour;
String letters = 'AM';
if (hours > 12) {
hours -= 12;
letters = "PM";
}
String convertedDateTime = value.year.toString();
convertedDateTime += "-${value.month.toString().padLeft(2, '0')}";
convertedDateTime += "-${value.day.toString().padLeft(2, '0')}";
convertedDateTime += " ${hours.toString().padLeft(2, '0')}";
convertedDateTime += "-${value.minute.toString().padLeft(2, '0')} $letters";
return convertedDateTime;
}
String formatDate(DateTime value) {
String convertedDateTime = value.year.toString();
convertedDateTime += "-${value.month.toString().padLeft(2, '0')}";
convertedDateTime += "-${value.day.toString().padLeft(2, '0')}";
return convertedDateTime;
}
+157
View File
@@ -0,0 +1,157 @@
import 'package:u_vineyard/pages/login.page.dart';
import 'package:u_vineyard/pages/new.vineyard.page.dart';
import '../models/app_models/drawer_item.model.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../middlewares/auth.middleware.dart';
import '../screens/dashboard/dashboard.screen.dart';
import '../screens/main/main.screen.dart';
List<GetPage<dynamic>> appRoutes = [
GetPage(
title: 'Dashboard',
name: MainScreen.route,
page: () => const MainScreen(),
middlewares: [AuthMiddleware()],
),
GetPage(
title: 'Login',
name: LoginPage.route,
page: () => const LoginPage(),
middlewares: [GuestMiddleware()],
)
];
Map<String, Widget Function()> internalRoutes = {
'/dashboard': () => const DashboadScreen(),
'/vineyards/new-vineyard': () => const NewVineyardScreen(), //const SizedBox(child: Text('1')),
'/vineyards/list': () => const SizedBox(child: Text('2')),
'/vineyards/edit': () => const SizedBox(child: Text('3')),
'/settings/account': () => const SizedBox(child: Text('5')),
'/menu2/1': () => const SizedBox(child: Text('menu 2-1')),
'/menu2/2': () => const SizedBox(child: Text('menu 2-2')),
'/menu2/3': () => const SizedBox(child: Text('menu 2-3')),
'/menu2/4': () => const SizedBox(child: Text('menu 2-4')),
'/menu2/menu3/1': () => const SizedBox(child: Text('menu 2-3-1')),
'/menu2/menu3/2': () => const SizedBox(child: Text('menu 2-3-2')),
'/menu2/menu3/3': () => const SizedBox(child: Text('menu 2-3-3')),
'/menu2/menu3/4': () => const SizedBox(child: Text('menu 2-3-4')),
};
final List<Map<String, dynamic>> drawerMenuMap = [
{
'type': 'link',
'name': 'Dashboard',
'icon': 'dashboard',
'route': '/dashboard',
},
{
'type': 'menu',
'name': 'Vigne',
'icon': 'menu',
'route': '/vineyards',
'children': [
{
'type': 'link',
'name': 'Aggiungi Vigna',
'icon': 'dot',
'route': '/new-vineyard',
},
{
'type': 'link',
'name': 'Lista Vigne',
'icon': 'dot',
'route': '/list',
},
{
'type': 'link',
'name': 'Modifica Vigna',
'icon': 'dot',
'route': '/edit',
},
],
},
{
'type': 'menu',
'name': 'Menu2',
'icon': 'menu',
'route': '/menu2',
'children': [
{
'type': 'link',
'name': 'Menu2 Item 1',
'icon': 'dot',
'route': '/1',
},
{
'type': 'link',
'name': 'Menu2 Item 2',
'icon': 'dot',
'route': '/2',
},
{
'type': 'link',
'name': 'Menu2 Item 3',
'icon': 'dot',
'route': '/3',
},
{
'type': 'link',
'name': 'Menu2 Item 4',
'icon': 'dot',
'route': '/4',
},
{
'type': 'menu',
'name': 'Menu2 menu',
'icon': 'menu',
'route': '/menu3',
'children': [
{
'type': 'link',
'name': 'Menu3 Item 1',
'icon': 'dot',
'route': '/1',
},
{
'type': 'link',
'name': 'Menu3 Item 2',
'icon': 'dot',
'route': '/2',
},
{
'type': 'link',
'name': 'Menu3 Item 3',
'icon': 'dot',
'route': '/3',
},
{
'type': 'link',
'name': 'Menu3 Item 4',
'icon': 'dot',
'route': '/4',
},
],
},
],
},
{
'type': 'menu',
'name': 'Settings',
'icon': 'settings',
'route': '/settings',
'children': [
{
'type': 'link',
'name': 'Account',
'icon': 'account',
'route': '/account',
},
],
},
];
final List<DrawerItem> drawerMenu =
drawerMenuMap.map(DrawerItem.fromJson).toList();
Loaded 100 of 224 files, more files were not shown because too many files have changed in this diff. Show more