Unggah Project TA

This commit is contained in:
Sakti Bayu N 2025-06-24 11:27:31 +07:00
commit 299df351ea
208 changed files with 12796 additions and 0 deletions

43
.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
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
.metadata Normal file
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: "761747bfc538b5af34aa0d3fac380f1bc331ec49"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: android
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: ios
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: linux
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: macos
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: web
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: windows
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
# 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'

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Saklar Pintar Mesh-Net
Firmware perangkat dan aplikasi client menggunakan framework Flutter untuk perangkat saklar pintar berbasis Mesh Network (Mesh-Net).

1
analysis_options.yaml Normal file
View File

@ -0,0 +1 @@
include: package:flutter_lints/flutter.yaml

13
android/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

58
android/app/build.gradle Normal file
View File

@ -0,0 +1,58 @@
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"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader("UTF-8") { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) {
flutterVersionCode = "1"
}
def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) {
flutterVersionName = "1.0"
}
android {
namespace = "com.saklar_pintar.mesh_net"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.saklar_pintar.mesh_net"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
}
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.debug
}
}
}
flutter {
source = "../.."
}

View File

@ -0,0 +1,11 @@
<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"/>
<!-- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> -->
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> -->
<!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> -->
<!-- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> -->
</manifest>

View File

@ -0,0 +1,53 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:label="Mesh-Net App"
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>

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

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

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground>
<inset
android:drawable="@drawable/ic_launcher_foreground"
android:inset="16%" />
</foreground>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

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

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#5CE1E6</color>
</resources>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@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>

View File

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

18
android/build.gradle Normal file
View File

@ -0,0 +1,18 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true

View File

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

26
android/settings.gradle Normal file
View File

@ -0,0 +1,26 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return 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 "7.3.0" apply false
// id "org.jetbrains.kotlin.android" version "1.7.10" apply false
id "org.jetbrains.kotlin.android" version "1.8.0" apply false
}
include ":app"

34
ios/.gitignore vendored Normal file
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

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>

View File

@ -0,0 +1 @@
#include "Generated.xcconfig"

View File

@ -0,0 +1 @@
#include "Generated.xcconfig"

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.saklarPintarClient;
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.saklarPintarClient.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.saklarPintarClient.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.saklarPintarClient.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.saklarPintarClient;
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.saklarPintarClient;
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 */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

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

View File

@ -0,0 +1,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>

View File

@ -0,0 +1,98 @@
<?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"
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"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
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>

View File

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

View File

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

View File

@ -0,0 +1,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>

View File

@ -0,0 +1,13 @@
import Flutter
import UIKit
@UIApplicationMain
@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)
}
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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>

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
ios/Runner/Info.plist Normal file
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>Saklar Pintar Client</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>saklar_pintar_client</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>

View File

@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"

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.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
import '../../features/database/models/device.dart';
class DeviceArguments {
final BuildContext context;
final Device device;
final bool currentStatus;
final bool currentOnline;
final String currentRSSI;
DeviceArguments(
this.context,
this.device,
this.currentStatus,
this.currentOnline,
this.currentRSSI,
);
}

View File

@ -0,0 +1,13 @@
import 'package:flutter/material.dart';
import '../../features/database/models/device.dart';
class DevicesArguments {
final BuildContext context;
final List<Device> devices;
DevicesArguments(
this.context,
this.devices,
);
}

View File

@ -0,0 +1,150 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// Dependency Injection
import '../../../injections_container.dart';
// BLOC
import '../../features/database/bloc/device/device_bloc.dart';
import '../../features/database/bloc/device_schedule/device_schedule_bloc.dart';
import '../../features/database/bloc/mesh_network/mesh_network_bloc.dart';
import '../../features/mqtt/bloc/mqtt_bloc.dart';
// Pages
import '../../presentation/pages/developer_mode/developer_mode_page.dart';
import '../../presentation/pages/device_dashboard/device_dashboard.dart';
import '../../presentation/pages/device_provisioning/device_provisioning_page.dart';
import '../../presentation/pages/main_bnb/main_bnb_page.dart';
import '../../presentation/pages/splash/splash_screen.dart';
import '../../presentation/pages/view_devices/view_devices_page.dart';
// Arguments
import '../arguments/device_arguments.dart';
import '../arguments/devices_arguments.dart';
class AppRoutes {
static Route onGenerateRoutes(RouteSettings settings) {
switch (settings.name) {
// Splash Screen
case '/':
return _materialRoute(const SplashScreen());
// Home Section (Home Page and Setting Page)
case '/MainBNB':
final context = settings.arguments as BuildContext;
return _materialRoute(
MultiBlocProvider(
providers: [
BlocProvider.value(
value: BlocProvider.of<MQTTBloc>(context)
..add(
ProcessDeviceMessage(),
),
),
BlocProvider<MeshNetworkBloc>.value(
value: sl<MeshNetworkBloc>()
..add(
GetMeshNetworks(),
),
),
BlocProvider<DeviceBloc>.value(
value: sl<DeviceBloc>()
..add(
GetDevices(),
),
),
BlocProvider<DeviceScheduleBloc>.value(
value: sl<DeviceScheduleBloc>(),
),
],
child: const MainBNBPage(),
),
);
// Provisioning
case '/DeviceProvisioning':
final context = settings.arguments as BuildContext;
return _materialRoute(
MultiBlocProvider(
providers: [
BlocProvider.value(
value: BlocProvider.of<MQTTBloc>(context),
),
BlocProvider.value(
value: BlocProvider.of<MeshNetworkBloc>(context),
),
BlocProvider.value(
value: BlocProvider.of<DeviceBloc>(context),
),
],
child: const DeviceProvisioningPage(),
),
);
// Dashboard Details
case '/DeviceDashboard':
final args = settings.arguments as DeviceArguments;
return _materialRoute(
MultiBlocProvider(
providers: [
BlocProvider.value(
value: BlocProvider.of<MQTTBloc>(args.context),
),
BlocProvider.value(
value: BlocProvider.of<MeshNetworkBloc>(args.context),
),
BlocProvider.value(
value: BlocProvider.of<DeviceBloc>(args.context),
),
BlocProvider.value(
value: BlocProvider.of<DeviceScheduleBloc>(args.context)
..add(
GetDeviceSchedulesByDeviceId(deviceId: args.device.id!),
),
),
],
child: DeviceDashboardPage(
device: args.device,
currentStatus: args.currentStatus,
currentOnline: args.currentOnline,
currentRSSI: args.currentRSSI,
),
),
);
// Setting View All Devices
case '/ViewDevicesChart':
final args = settings.arguments as DevicesArguments;
return _materialRoute(
MultiBlocProvider(
providers: [
BlocProvider.value(
value: BlocProvider.of<DeviceBloc>(args.context),
),
],
child: ViewDevicesPage(
devices: args.devices,
),
),
);
// Developer Mode (Change MQTT Broker)
case '/DeveloperMode':
final context = settings.arguments as BuildContext;
return _materialRoute(
MultiBlocProvider(
providers: [
BlocProvider.value(
value: BlocProvider.of<MQTTBloc>(context),
),
],
child: const DeveloperSettingsPage(),
),
);
default:
return _materialRoute(const SplashScreen());
}
}
static MaterialPageRoute _materialRoute(Widget page) {
return MaterialPageRoute(builder: (context) => page);
}
}

View File

@ -0,0 +1,11 @@
import 'package:flutter/material.dart';
class ColorConstants {
static Color darkBlueAppColor = const Color(0xff2F9DCE);
static Color lightBlueAppColor = const Color(0xff5CE1E6);
// static Color lightBlueAppColor = const Color(0xffACE7FF);
// static Color darkBlueAppColor = const Color(0xff297274);
static Color cardBlueAppColor = const Color(0xFFB2F0FB);
static Color whiteAppColor = Colors.white;
static Color blackAppColor = Colors.black;
}

View File

@ -0,0 +1,6 @@
const String baseMQTTBroker = 'broker.emqx.io';
const String baseLocalMQTTBroker = '192.168.137.1';
const String baseClientID = 'flutter_test_uyabe';
const int baseMQTTPort = 1883;
// const String baseUsernameMQTT = 'emqx';
// const String basePasswordMQTT = 'public';

View File

@ -0,0 +1,125 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../data/database_helper.dart';
import '../../models/device.dart';
part 'device_event.dart';
part 'device_state.dart';
class DeviceBloc extends Bloc<DeviceEvent, DeviceState> {
final DatabaseHelper _database;
DeviceBloc(this._database) : super(DeviceInitial()) {
on<InsertDeviceWithMacRoot>(onInsertDeviceWithMacRoot);
on<GetDevices>(onGetDevices);
on<GetDeviceById>(onGetDeviceById);
on<UpdateDeviceName>(onUpdateDeviceName);
on<DeleteDevices>(onDeleteDevices);
on<DeleteDeviceById>(onDeleteDeviceById);
}
Future<void> onInsertDeviceWithMacRoot(
InsertDeviceWithMacRoot event,
Emitter<DeviceState> emit,
) async {
emit(DeviceLoading());
try {
final meshNetwork =
await _database.getMeshNetworkByMacRoot(macRoot: event.macRoot);
if (meshNetwork == null) {
emit(DeviceFailure('Mesh dengan MAC ${event.macRoot} tidak ditemukan'));
return;
}
await _database.insertDeviceWithMacRoot(
macRoot: event.macRoot,
nodeId: event.nodeId,
name: event.name,
role: event.role,
);
emit(SaveDeviceSuccess());
} catch (e) {
emit(DeviceFailure('Gagal menyimpan device: $e'));
}
}
Future<void> onGetDevices(
GetDevices event,
Emitter<DeviceState> emit,
) async {
emit(DeviceLoading());
try {
final devices = await _database.getDevices();
emit(DevicesLoaded(devices));
} catch (e) {
emit(DeviceFailure('Failed to load devices'));
}
}
Future<void> onGetDeviceById(
GetDeviceById event,
Emitter<DeviceState> emit,
) async {
emit(DeviceLoading());
try {
final device = await _database.getDeviceById(id: event.id);
if (device == null) {
emit(DeviceFailure('Device dengan id ${event.id} tidak ditemukan'));
return;
}
emit(DeviceLoaded(device));
} catch (e) {
emit(DeviceFailure('Failed to load Device: $e'));
}
}
Future<void> onUpdateDeviceName(
UpdateDeviceName event,
Emitter<DeviceState> emit,
) async {
emit(DeviceLoading());
try {
await _database.updateDeviceName(
id: event.id,
name: event.name,
);
emit(UpdateDeviceSuccess());
add(GetDevices());
} catch (e) {
emit(DeviceFailure('Failed to update Device: $e'));
}
}
Future<void> onDeleteDevices(
DeleteDevices event,
Emitter<DeviceState> emit,
) async {
emit(DeviceLoading());
try {
await _database.resetDeviceTable();
emit(DeleteDevicesSuccess());
} catch (e) {
emit(DeviceFailure('Failed to delete Devices: $e'));
}
}
Future<void> onDeleteDeviceById(
DeleteDeviceById event,
Emitter<DeviceState> emit,
) async {
emit(DeviceLoading());
try {
await _database.deleteDeviceById(id: event.id);
emit(DeleteDeviceSuccess());
} catch (e) {
emit(DeviceFailure('Failed to delete Device: $e'));
}
}
}

View File

@ -0,0 +1,66 @@
part of 'device_bloc.dart';
abstract class DeviceEvent extends Equatable {
@override
List<Object?> get props => [];
}
class InsertDeviceWithMacRoot extends DeviceEvent {
final String macRoot;
final String nodeId;
final String name;
final String role;
InsertDeviceWithMacRoot({
required this.macRoot,
required this.nodeId,
required this.name,
required this.role,
});
@override
List<Object?> get props => [
macRoot,
nodeId,
name,
role,
];
}
class GetDevices extends DeviceEvent {}
class GetDeviceById extends DeviceEvent {
final int id;
GetDeviceById({required this.id});
@override
List<Object?> get props => [id];
}
class UpdateDeviceName extends DeviceEvent {
final int id;
final String? name;
UpdateDeviceName({
required this.id,
this.name,
});
@override
List<Object?> get props => [
id,
name,
];
}
class DeleteDevices extends DeviceEvent {}
class DeleteDeviceById extends DeviceEvent {
final int id;
DeleteDeviceById({required this.id});
@override
List<Object?> get props => [id];
}

View File

@ -0,0 +1,45 @@
part of 'device_bloc.dart';
abstract class DeviceState extends Equatable {
@override
List<Object?> get props => [];
}
class DeviceInitial extends DeviceState {}
class DeviceLoading extends DeviceState {}
class DeviceFailure extends DeviceState {
final String message;
DeviceFailure(this.message);
@override
List<Object?> get props => [message];
}
class SaveDeviceSuccess extends DeviceState {}
class DevicesLoaded extends DeviceState {
final List<Device> devices;
DevicesLoaded(this.devices);
@override
List<Object?> get props => [devices];
}
class DeviceLoaded extends DeviceState {
final Device device;
DeviceLoaded(this.device);
@override
List<Object?> get props => [device];
}
class UpdateDeviceSuccess extends DeviceState {}
class DeleteDevicesSuccess extends DeviceState {}
class DeleteDeviceSuccess extends DeviceState {}

View File

@ -0,0 +1,86 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../data/database_helper.dart';
import '../../models/device_schedule.dart';
part 'device_schedule_event.dart';
part 'device_schedule_state.dart';
class DeviceScheduleBloc
extends Bloc<DeviceScheduleEvent, DeviceScheduleState> {
final DatabaseHelper _database;
DeviceScheduleBloc(this._database) : super(DeviceScheduleInitial()) {
on<GetDeviceSchedulesByDeviceId>(_onGetDeviceSchedulesByDeviceId);
on<InsertDeviceSchedulewithDeviceId>(_onInsertDeviceSchedulewithDeviceId);
on<UpdateDeviceScheduleEnabled>(_onUpdateDeviceScheduleEnabled);
on<DeleteDeviceSchedule>(_onDeleteDeviceSchedule);
}
Future<void> _onGetDeviceSchedulesByDeviceId(
GetDeviceSchedulesByDeviceId event,
Emitter<DeviceScheduleState> emit,
) async {
emit(DeviceScheduleLoading());
try {
final result = await _database.getSchedulesByDeviceId(
deviceId: event.deviceId,
);
emit(DeviceScheduleLoaded(result));
} catch (e) {
emit(DeviceScheduleFailure('Failed to load schedules'));
}
}
Future<void> _onInsertDeviceSchedulewithDeviceId(
InsertDeviceSchedulewithDeviceId event,
Emitter<DeviceScheduleState> emit,
) async {
emit(DeviceScheduleLoading());
try {
await _database.insertDeviceSchedulewithDeviceId(
deviceId: event.deviceId,
time: event.time,
state: event.state,
enabled: event.enabled,
);
emit(SaveDeviceScheduleSuccess());
add(GetDeviceSchedulesByDeviceId(deviceId: event.deviceId));
} catch (e) {
emit(DeviceScheduleFailure('Failed to add schedule'));
}
}
Future<void> _onUpdateDeviceScheduleEnabled(
UpdateDeviceScheduleEnabled event,
Emitter<DeviceScheduleState> emit,
) async {
emit(DeviceScheduleLoading());
try {
await _database.updateDeviceScheduleEnabled(
scheduleId: event.scheduleId,
enabled: event.enabled,
);
emit(UpdateDeviceScheduleSuccess());
} catch (e) {
emit(DeviceScheduleFailure('Failed to update schedule'));
}
}
Future<void> _onDeleteDeviceSchedule(
DeleteDeviceSchedule event,
Emitter<DeviceScheduleState> emit,
) async {
emit(DeviceScheduleLoading());
try {
await _database.deleteDeviceSchedule(
scheduleId: event.scheduleId,
);
emit(DeleteDeviceScheduleSuccess());
} catch (e) {
emit(DeviceScheduleFailure('Failed to delete schedule'));
}
}
}

View File

@ -0,0 +1,59 @@
part of 'device_schedule_bloc.dart';
abstract class DeviceScheduleEvent extends Equatable {
@override
List<Object?> get props => [];
}
class GetDeviceSchedulesByDeviceId extends DeviceScheduleEvent {
final int deviceId;
GetDeviceSchedulesByDeviceId({required this.deviceId});
@override
List<Object?> get props => [deviceId];
}
class InsertDeviceSchedulewithDeviceId extends DeviceScheduleEvent {
final int deviceId;
final String time;
final String state;
final bool enabled;
InsertDeviceSchedulewithDeviceId({
required this.deviceId,
required this.time,
required this.state,
required this.enabled,
});
@override
List<Object?> get props => [
deviceId,
time,
state,
enabled,
];
}
class UpdateDeviceScheduleEnabled extends DeviceScheduleEvent {
final int scheduleId;
final bool enabled;
UpdateDeviceScheduleEnabled({
required this.scheduleId,
required this.enabled,
});
@override
List<Object?> get props => [scheduleId, enabled];
}
class DeleteDeviceSchedule extends DeviceScheduleEvent {
final int scheduleId;
DeleteDeviceSchedule({required this.scheduleId});
@override
List<Object?> get props => [scheduleId];
}

View File

@ -0,0 +1,25 @@
part of 'device_schedule_bloc.dart';
abstract class DeviceScheduleState {}
class DeviceScheduleInitial extends DeviceScheduleState {}
class DeviceScheduleLoading extends DeviceScheduleState {}
class DeviceScheduleFailure extends DeviceScheduleState {
final String message;
DeviceScheduleFailure(this.message);
}
class SaveDeviceScheduleSuccess extends DeviceScheduleState {}
class DeviceScheduleLoaded extends DeviceScheduleState {
final List<DeviceSchedule> schedules;
DeviceScheduleLoaded(this.schedules);
}
class UpdateDeviceScheduleSuccess extends DeviceScheduleState {}
class DeleteDeviceScheduleSuccess extends DeviceScheduleState {}

View File

@ -0,0 +1,156 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../data/database_helper.dart';
import '../../models/mesh_network.dart';
part 'mesh_network_event.dart';
part 'mesh_network_state.dart';
class MeshNetworkBloc extends Bloc<MeshNetworkEvent, MeshNetworkState> {
final DatabaseHelper _database;
MeshNetworkBloc(this._database) : super(MeshNetworkInitial()) {
on<InsertMeshNetwork>(onInsertMeshNetwork);
on<GetMeshNetworks>(onGetMeshNetworks);
on<GetMeshNetworkById>(onGetMeshNetworkById);
on<GetMeshNetworkByMacRoot>(onGetMeshNetworkByMacRoot);
on<UpdateMeshNetworkName>(onUpdateMeshNetworkName);
on<DeleteMeshNetworks>(onDeleteMeshNetworks);
on<DeleteMeshNetworkById>(onDeleteMeshNetworkById);
on<DeleteAllMeshDeviceRelations>(onDeleteAllMeshDeviceRelations);
}
Future<void> onInsertMeshNetwork(
InsertMeshNetwork event,
Emitter<MeshNetworkState> emit,
) async {
emit(MeshNetworkLoading());
try {
await _database.insertMeshNetwork(
meshNetwork: MeshNetwork(
macRoot: event.macRoot,
name: event.meshName,
),
);
emit(SaveMeshNetworkSuccess());
} catch (e) {
emit(MeshNetworkFailure('Failed to insert Mesh Network: $e'));
}
}
Future<void> onGetMeshNetworks(
GetMeshNetworks event,
Emitter<MeshNetworkState> emit,
) async {
emit(MeshNetworkLoading());
try {
final meshNetworks = await _database.getMeshNetworks();
emit(MeshNetworksLoaded(meshNetworks));
} catch (e) {
emit(MeshNetworkFailure('Failed to load Mesh Networks: $e'));
}
}
Future<void> onGetMeshNetworkById(
GetMeshNetworkById event,
Emitter<MeshNetworkState> emit,
) async {
emit(MeshNetworkLoading());
try {
final meshNetwork = await _database.getMeshNetworkById(id: event.id);
if (meshNetwork == null) {
emit(MeshNetworkFailure('Mesh dengan MAC ${event.id} tidak ditemukan'));
return;
}
emit(MeshNetworkLoaded(meshNetwork));
} catch (e) {
emit(MeshNetworkFailure('Failed to load Mesh Network: $e'));
}
}
Future<void> onGetMeshNetworkByMacRoot(
GetMeshNetworkByMacRoot event,
Emitter<MeshNetworkState> emit,
) async {
emit(MeshNetworkLoading());
try {
final meshNetwork =
await _database.getMeshNetworkByMacRoot(macRoot: event.macRoot);
if (meshNetwork == null) {
emit(MeshNetworkFailure(
'Mesh dengan MAC ${event.macRoot} tidak ditemukan'));
return;
}
emit(MeshNetworkLoaded(meshNetwork));
} catch (e) {
emit(MeshNetworkFailure('Failed to load Mesh Network: $e'));
}
}
Future<void> onUpdateMeshNetworkName(
UpdateMeshNetworkName event,
Emitter<MeshNetworkState> emit,
) async {
emit(MeshNetworkLoading());
try {
await _database.updateMeshNetworkName(
id: event.id,
name: event.name,
);
emit(UpdateMeshNetworkSuccess());
add(GetMeshNetworks());
} catch (e) {
emit(MeshNetworkFailure('Failed to update Mesh Network: $e'));
}
}
Future<void> onDeleteMeshNetworks(
DeleteMeshNetworks event,
Emitter<MeshNetworkState> emit,
) async {
emit(MeshNetworkLoading());
try {
await _database.resetMeshNetworkTable();
emit(DeleteMeshNetworksSuccess());
} catch (e) {
emit(MeshNetworkFailure('Failed to delete Mesh Networks: $e'));
}
}
Future<void> onDeleteMeshNetworkById(
DeleteMeshNetworkById event,
Emitter<MeshNetworkState> emit,
) async {
emit(MeshNetworkLoading());
try {
await _database.deleteMeshNetworkById(id: event.id);
emit(DeleteMeshNetworkSuccess());
} catch (e) {
emit(MeshNetworkFailure('Failed to delete Mesh Network: $e'));
}
}
Future<void> onDeleteAllMeshDeviceRelations(
DeleteAllMeshDeviceRelations event,
Emitter<MeshNetworkState> emit,
) async {
emit(MeshNetworkLoading());
try {
await _database.resetAllTables();
emit(DeleteAllMeshDeviceRelationsSuccess());
add(GetMeshNetworks());
} catch (e) {
emit(
MeshNetworkFailure('Failed to delete All Mesh Device Relations: $e'));
}
}
}

View File

@ -0,0 +1,71 @@
part of 'mesh_network_bloc.dart';
abstract class MeshNetworkEvent extends Equatable {
@override
List<Object?> get props => [];
}
class InsertMeshNetwork extends MeshNetworkEvent {
final String macRoot;
final String meshName;
InsertMeshNetwork({
required this.macRoot,
required this.meshName,
});
@override
List<Object?> get props => [
macRoot,
meshName,
];
}
class GetMeshNetworks extends MeshNetworkEvent {}
class GetMeshNetworkByMacRoot extends MeshNetworkEvent {
final String macRoot;
GetMeshNetworkByMacRoot({required this.macRoot});
@override
List<Object?> get props => [macRoot];
}
class GetMeshNetworkById extends MeshNetworkEvent {
final int id;
GetMeshNetworkById({required this.id});
@override
List<Object?> get props => [id];
}
class UpdateMeshNetworkName extends MeshNetworkEvent {
final int id;
final String? name;
UpdateMeshNetworkName({
required this.id,
this.name,
});
@override
List<Object?> get props => [
id,
name,
];
}
class DeleteMeshNetworks extends MeshNetworkEvent {}
class DeleteMeshNetworkById extends MeshNetworkEvent {
final int id;
DeleteMeshNetworkById({required this.id});
@override
List<Object?> get props => [id];
}
class DeleteAllMeshDeviceRelations extends MeshNetworkEvent {}

View File

@ -0,0 +1,47 @@
part of 'mesh_network_bloc.dart';
abstract class MeshNetworkState extends Equatable {
@override
List<Object?> get props => [];
}
class MeshNetworkInitial extends MeshNetworkState {}
class MeshNetworkLoading extends MeshNetworkState {}
class MeshNetworkFailure extends MeshNetworkState {
final String message;
MeshNetworkFailure(this.message);
@override
List<Object?> get props => [message];
}
class SaveMeshNetworkSuccess extends MeshNetworkState {}
class MeshNetworksLoaded extends MeshNetworkState {
final List<MeshNetwork> meshNetworks;
MeshNetworksLoaded(this.meshNetworks);
@override
List<Object?> get props => [meshNetworks];
}
class MeshNetworkLoaded extends MeshNetworkState {
final MeshNetwork meshNetwork;
MeshNetworkLoaded(this.meshNetwork);
@override
List<Object?> get props => [meshNetwork];
}
class UpdateMeshNetworkSuccess extends MeshNetworkState {}
class DeleteMeshNetworksSuccess extends MeshNetworkState {}
class DeleteMeshNetworkSuccess extends MeshNetworkState {}
class DeleteAllMeshDeviceRelationsSuccess extends MeshNetworkState {}

View File

@ -0,0 +1,328 @@
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import '../models/device.dart';
import '../models/device_schedule.dart';
import '../models/mesh_network.dart';
class DatabaseHelper {
static final DatabaseHelper _instance = DatabaseHelper._internal();
factory DatabaseHelper() => _instance;
DatabaseHelper._internal();
Database? _database;
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDB();
return _database!;
}
Future<Database> _initDB() async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, 'client.db');
return await openDatabase(
path,
version: 1,
onOpen: (db) async {
await db.execute('PRAGMA foreign_keys = ON');
},
onCreate: (db, version) async {
await db.execute('''
CREATE TABLE mesh_networks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
macRoot TEXT NOT NULL,
name TEXT NOT NULL
)
''');
await db.execute('''
CREATE TABLE devices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nodeId TEXT NOT NULL,
name TEXT NOT NULL,
role TEXT NOT NULL,
meshId INTEGER NOT NULL,
FOREIGN KEY (meshId) REFERENCES mesh_networks(id) ON DELETE CASCADE
)
''');
await db.execute('''
CREATE TABLE device_schedules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
deviceId INTEGER NOT NULL,
time TEXT NOT NULL,
state TEXT NOT NULL,
enabled INTEGER NOT NULL DEFAULT 1,
FOREIGN KEY (deviceId) REFERENCES devices(id) ON DELETE CASCADE
)
''');
},
);
}
//// MESH
Future<int> insertMeshNetwork({required MeshNetwork meshNetwork}) async {
final db = await database;
return await db.insert('mesh_networks', meshNetwork.toMap());
}
Future<List<MeshNetwork>> getMeshNetworks() async {
final db = await database;
final result = await db.query('mesh_networks');
return result.map((e) => MeshNetwork.fromMap(e)).toList();
}
Future<MeshNetwork?> getMeshNetworkById({required int id}) async {
final db = await database;
final result = await db.query(
'mesh_networks',
where: 'id = ?',
whereArgs: [id],
limit: 1,
);
if (result.isNotEmpty) {
return MeshNetwork.fromMap(result.first);
} else {
return null;
}
}
Future<MeshNetwork?> getMeshNetworkByMacRoot(
{required String macRoot}) async {
final db = await database;
final result = await db.query(
'mesh_networks',
where: 'macRoot = ?',
whereArgs: [macRoot],
limit: 1,
);
if (result.isNotEmpty) {
return MeshNetwork.fromMap(result.first);
} else {
return null;
}
}
Future<int> updateMeshNetworkName({
required int id,
String? name,
}) async {
final db = await database;
Map<String, dynamic> values = {};
if (name != null) values['name'] = name;
return await db.update(
'mesh_networks',
values,
where: 'id = ?',
whereArgs: [id],
);
}
Future<int> deleteMeshNetworkById({required int id}) async {
final db = await database;
return await db.delete(
'mesh_networks',
where: 'id = ?',
whereArgs: [id],
);
}
Future<int> resetMeshNetworkTable() async {
final db = await database;
return await db.delete('mesh_networks');
}
//// DEVICE
Future<int?> insertDeviceWithMacRoot({
required String macRoot,
required String nodeId,
required String name,
required String role,
}) async {
final mesh = await getMeshNetworkByMacRoot(macRoot: macRoot);
if (mesh == null) {
// print('Mesh with MAC $macRoot not found');
return null;
}
final db = await database;
return await db.insert('devices', {
'nodeId': nodeId,
'name': name,
'role': role,
'meshId': mesh.id,
});
}
Future<List<Device>> getDevices() async {
final db = await database;
// final List<Map<String, dynamic>> result = await db.query('devices');
final List<Map<String, dynamic>> result = await db.rawQuery('''
SELECT
d.id AS idDevice, d.nodeId AS deviceIdentifier, d.name, d.role,
m.id AS idMesh, m.macRoot AS macIdentifier, m.name AS meshName
FROM devices d
INNER JOIN mesh_networks m ON d.meshId = m.id
''');
return result.map((e) => Device.fromMapWithMeshNetwork(e)).toList();
}
Future<Device?> getDeviceById({required int id}) async {
final db = await database;
final result = await db.rawQuery('''
SELECT
d.id AS idDevice,
d.nodeId AS deviceIdentifier,
d.name,
d.role,
m.id AS idMesh,
m.macRoot AS macIdentifier,
m.name AS meshName
FROM devices d
INNER JOIN mesh_networks m ON d.meshId = m.id
WHERE d.id = ?
LIMIT 1
''', [id]);
if (result.isNotEmpty) {
return Device.fromMapWithMeshNetwork(result.first);
} else {
return null;
}
}
Future<Device?> getDeviceByNodeId({required String nodeId}) async {
final db = await database;
final result = await db.rawQuery('''
SELECT
d.id AS idDevice,
d.nodeId AS deviceIdentifier,
d.name,
d.role,
m.id AS idMesh,
m.macRoot AS macIdentifier,
m.name AS meshName
FROM devices d
INNER JOIN mesh_networks m ON d.meshId = m.id
WHERE d.nodeId = ?
LIMIT 1
''', [nodeId]);
if (result.isNotEmpty) {
return Device.fromMapWithMeshNetwork(result.first);
} else {
return null;
}
}
Future<int> updateDeviceName({
required int id,
String? name,
}) async {
final db = await database;
Map<String, dynamic> values = {};
if (name != null) values['name'] = name;
return await db.update(
'devices',
values,
where: 'id = ?',
whereArgs: [id],
);
}
Future<int> deleteDeviceById({required int id}) async {
final db = await database;
return await db.delete(
'devices',
where: 'id = ?',
whereArgs: [id],
);
}
Future<int> resetDeviceTable() async {
final db = await database;
return await db.delete('devices');
}
//// SCHEDULE
Future<int> insertDeviceSchedulewithDeviceId({
required int deviceId,
required String time,
required String state,
required bool enabled,
}) async {
final db = await database;
return await db.insert(
'device_schedules',
{
'deviceId': deviceId,
'time': time,
'state': state,
'enabled': enabled ? 1 : 0,
},
);
}
Future<List<DeviceSchedule>> getSchedulesByDeviceId({
required int deviceId,
}) async {
final db = await database;
final List<Map<String, dynamic>> maps = await db.query(
'device_schedules',
where: 'deviceId = ?',
whereArgs: [deviceId],
);
return List.generate(maps.length, (i) {
return DeviceSchedule.fromMap(maps[i]);
});
}
Future<int> updateDeviceScheduleEnabled({
required int scheduleId,
required bool enabled,
}) async {
final db = await database;
return await db.update(
'device_schedules',
{'enabled': enabled ? 1 : 0},
where: 'id = ?',
whereArgs: [scheduleId],
);
}
Future<int> deleteDeviceSchedule({
required int scheduleId,
}) async {
final db = await database;
return await db.delete(
'device_schedules',
where: 'id = ?',
whereArgs: [scheduleId],
);
}
Future<int> resetScheduleTable() async {
final db = await database;
return await db.delete('device_schedules');
}
//// ALL
Future<void> resetAllTables() async {
final db = await database;
await db.delete('device_schedules');
await db.delete('devices');
await db.delete('mesh_networks');
}
}

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