ci: add keystore/key.properties to repo, fix NDK version, remove duplicate build.gradle
Build Release AAB / build (push) Failing after 6m58s

This commit is contained in:
andrew committed 2026-09-17 08:26:27 +07:00
1 parent e4c32f9def
commit 9239c77106
125 files changed
+5540 -5285

No files matched your search

+2 -17
View File
@@ -35,21 +35,6 @@ jobs:
- name: Run tests - name: Run tests
run: flutter test run: flutter test
- name: Decode keystore
if: env.KEYSTORE_BASE64 != ''
run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > siab-release.keystore
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
- name: Create key.properties
run: |
cat > android/key.properties <<EOF
storePassword=Store_sc4l3
keyPassword=Store_sc4l3
keyAlias=siab
storeFile=../siab-release.keystore
EOF
- name: Build App Bundle - name: Build App Bundle
run: | run: |
flutter build appbundle \ flutter build appbundle \
@@ -58,8 +43,8 @@ jobs:
--split-debug-info=build/debug-info \ --split-debug-info=build/debug-info \
--dart-define=SIAB_DEVICE_NAME=SIAB --dart-define=SIAB_DEVICE_NAME=SIAB
env: env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} KEYSTORE_PASSWORD: Store_sc4l3
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} KEY_PASSWORD: Store_sc4l3
- name: Upload AAB artifact - name: Upload AAB artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
-5
View File
@@ -42,8 +42,3 @@ app.*.map.json
/android/app/debug /android/app/debug
/android/app/profile /android/app/profile
/android/app/release /android/app/release
# Keystore and signing
*.keystore
*.jks
android/key.properties
+45 -45
View File
@@ -1,45 +1,45 @@
# This file tracks properties of this Flutter project. # This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc. # Used by Flutter tool to assess capabilities and perform upgrades etc.
# #
# This file should be version controlled and should not be manually edited. # This file should be version controlled and should not be manually edited.
version: version:
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2" revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
channel: "stable" channel: "stable"
project_type: app project_type: app
# Tracks metadata for the flutter migrate command # Tracks metadata for the flutter migrate command
migration: migration:
platforms: platforms:
- platform: root - platform: root
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
- platform: android - platform: android
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
- platform: ios - platform: ios
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
- platform: linux - platform: linux
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
- platform: macos - platform: macos
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
- platform: web - platform: web
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
- platform: windows - platform: windows
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2 base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
# User provided section # User provided section
# List of Local paths (relative to this file) that should be # List of Local paths (relative to this file) that should be
# ignored by the migrate tool. # ignored by the migrate tool.
# #
# Files that are not part of the templates will be ignored by default. # Files that are not part of the templates will be ignored by default.
unmanaged_files: unmanaged_files:
- 'lib/main.dart' - 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj' - 'ios/Runner.xcodeproj/project.pbxproj'
+93 -93
View File
@@ -1,93 +1,93 @@
# Android Setup Guide # Android Setup Guide
## Option 1: Use Physical Android Device (Recommended) ## Option 1: Use Physical Android Device (Recommended)
### Steps: ### Steps:
1. **Enable Developer Options on your Android device:** 1. **Enable Developer Options on your Android device:**
- Go to Settings > About Phone - Go to Settings > About Phone
- Tap "Build Number" 7 times - Tap "Build Number" 7 times
- Go back to Settings > Developer Options - Go back to Settings > Developer Options
- Enable "USB Debugging" - Enable "USB Debugging"
2. **Connect device via USB:** 2. **Connect device via USB:**
```bash ```bash
# Check if device is detected # Check if device is detected
adb devices adb devices
``` ```
3. **Run the app:** 3. **Run the app:**
```bash ```bash
cd flutter_siab_app cd flutter_siab_app
flutter run flutter run
``` ```
## Option 2: Use Android Emulator ## Option 2: Use Android Emulator
### Install Android Studio: ### Install Android Studio:
1. Download Android Studio: https://developer.android.com/studio 1. Download Android Studio: https://developer.android.com/studio
2. Install Android SDK and create an emulator: 2. Install Android SDK and create an emulator:
- Open Android Studio - Open Android Studio
- Tools > Device Manager - Tools > Device Manager
- Create Virtual Device - Create Virtual Device
- Choose a device (e.g., Pixel 5) - Choose a device (e.g., Pixel 5)
- Download a system image (API 30+ recommended) - Download a system image (API 30+ recommended)
- Finish setup - Finish setup
3. **Start the emulator:** 3. **Start the emulator:**
```bash ```bash
# List available emulators # List available emulators
flutter emulators flutter emulators
# Launch emulator (replace with your emulator name) # Launch emulator (replace with your emulator name)
flutter emulators --launch <emulator_id> flutter emulators --launch <emulator_id>
``` ```
4. **Run the app:** 4. **Run the app:**
```bash ```bash
cd flutter_siab_app cd flutter_siab_app
flutter run flutter run
``` ```
## Option 3: Build APK and Install Manually ## Option 3: Build APK and Install Manually
If you can't use USB debugging, build an APK: If you can't use USB debugging, build an APK:
```bash ```bash
cd flutter_siab_app cd flutter_siab_app
flutter build apk --release flutter build apk --release
``` ```
The APK will be at: `build/app/outputs/flutter-apk/app-release.apk` The APK will be at: `build/app/outputs/flutter-apk/app-release.apk`
Transfer to your Android device and install it. Transfer to your Android device and install it.
## Troubleshooting ## Troubleshooting
### "No devices found" ### "No devices found"
- Ensure USB debugging is enabled - Ensure USB debugging is enabled
- Try different USB cable/port - Try different USB cable/port
- Run `adb devices` to verify connection - Run `adb devices` to verify connection
- On Linux, you may need to add udev rules - On Linux, you may need to add udev rules
### "Permission denied" ### "Permission denied"
- Check USB debugging authorization on device - Check USB debugging authorization on device
- Try `adb kill-server && adb start-server` - Try `adb kill-server && adb start-server`
### Bluetooth not working on emulator ### Bluetooth not working on emulator
- Physical devices are recommended for Bluetooth testing - Physical devices are recommended for Bluetooth testing
- Some emulators don't support Bluetooth BLE - Some emulators don't support Bluetooth BLE
- Use a real Android device for best results - Use a real Android device for best results
## Required Permissions ## Required Permissions
The app needs these permissions (already configured): The app needs these permissions (already configured):
- Bluetooth - Bluetooth
- Bluetooth Admin - Bluetooth Admin
- Bluetooth Scan - Bluetooth Scan
- Bluetooth Connect - Bluetooth Connect
- Location (required for BLE scanning on Android 12+) - Location (required for BLE scanning on Android 12+)
Make sure to grant all permissions when the app requests them. Make sure to grant all permissions when the app requests them.
+78 -78
View File
@@ -1,78 +1,78 @@
# Quick Start Guide # Quick Start Guide
## Prerequisites ## Prerequisites
1. Install Flutter: https://flutter.dev/docs/get-started/install 1. Install Flutter: https://flutter.dev/docs/get-started/install
2. Install Android Studio or VS Code with Flutter extensions 2. Install Android Studio or VS Code with Flutter extensions
3. Enable developer options on your Android device 3. Enable developer options on your Android device
## Setup Steps ## Setup Steps
1. **Navigate to the app directory:** 1. **Navigate to the app directory:**
```bash ```bash
cd flutter_siab_app cd flutter_siab_app
``` ```
2. **Get Flutter dependencies:** 2. **Get Flutter dependencies:**
```bash ```bash
flutter pub get flutter pub get
``` ```
3. **Connect your Android device** (USB debugging enabled) or start an emulator 3. **Connect your Android device** (USB debugging enabled) or start an emulator
4. **Run the app:** 4. **Run the app:**
```bash ```bash
flutter run flutter run
``` ```
## First Run ## First Run
1. **Grant Permissions:** 1. **Grant Permissions:**
- The app will request Bluetooth and Location permissions - The app will request Bluetooth and Location permissions
- Grant all permissions (Location is required for BLE scanning on Android) - Grant all permissions (Location is required for BLE scanning on Android)
2. **Connect to SIAB Device:** 2. **Connect to SIAB Device:**
- Tap the blue floating action button (FAB) at bottom right - Tap the blue floating action button (FAB) at bottom right
- App will scan for devices named "SIAB" - App will scan for devices named "SIAB"
- Once found, it will connect automatically - Once found, it will connect automatically
- If no data arrives, it will try common start commands - If no data arrives, it will try common start commands
3. **View Data:** 3. **View Data:**
- Streamed data packets appear in real-time - Streamed data packets appear in real-time
- Tap any packet to see detailed information - Tap any packet to see detailed information
- View statistics at the top - View statistics at the top
## Features ## Features
- ✅ One-tap connect/disconnect - ✅ One-tap connect/disconnect
- ✅ Real-time data streaming - ✅ Real-time data streaming
- ✅ Detailed packet information - ✅ Detailed packet information
- ✅ Statistics (count, rate, duration) - ✅ Statistics (count, rate, duration)
- ✅ Automatic start command detection - ✅ Automatic start command detection
- ✅ Clean, Material Design UI - ✅ Clean, Material Design UI
## Troubleshooting ## Troubleshooting
### "No devices found" ### "No devices found"
- Ensure SIAB device is powered on - Ensure SIAB device is powered on
- Check device name matches "SIAB" (case-insensitive) - Check device name matches "SIAB" (case-insensitive)
- Verify Bluetooth is enabled on both devices - Verify Bluetooth is enabled on both devices
### "Permission denied" ### "Permission denied"
- Go to Android Settings > Apps > SIAB Bluetooth > Permissions - Go to Android Settings > Apps > SIAB Bluetooth > Permissions
- Enable Location permission (required for BLE) - Enable Location permission (required for BLE)
### "No data received" ### "No data received"
- App automatically tries start commands - App automatically tries start commands
- Check device documentation for correct command - Check device documentation for correct command
- Device may need specific initialization sequence - Device may need specific initialization sequence
## Building APK ## Building APK
To build a release APK: To build a release APK:
```bash ```bash
flutter build apk --release flutter build apk --release
``` ```
APK location: `build/app/outputs/flutter-apk/app-release.apk` APK location: `build/app/outputs/flutter-apk/app-release.apk`
+37 -28
View File
@@ -1,28 +1,37 @@
# This file configures the analyzer, which statically analyzes Dart code to # This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints. # check for errors, warnings, and lints.
# #
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled # 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 # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`. # invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps, # The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices. # packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml analyzer:
exclude:
linter: - build/**
# The lint rules applied to this project can be customized in the - android/**
# section below to disable rules from the `package:flutter_lints/flutter.yaml` - ios/**
# included above or to enable additional rules. A list of all available lints - web/**
# and their documentation is published at https://dart.dev/lints. - windows/**
# - macos/**
# Instead of disabling a lint rule for the entire project in the - linux/**
# section below, it can also be suppressed for a single line of code include: package:flutter_lints/flutter.yaml
# 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 linter:
# producing the lint. # The lint rules applied to this project can be customized in the
rules: # section below to disable rules from the `package:flutter_lints/flutter.yaml`
# avoid_print: false # Uncomment to disable the `avoid_print` rule # included above or to enable additional rules. A list of all available lints
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # and their documentation is published at https://dart.dev/lints.
#
# Additional information about this file can be found at # Instead of disabling a lint rule for the entire project in the
# https://dart.dev/guides/language/analysis-options # 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 -14
View File
@@ -1,14 +1,14 @@
gradle-wrapper.jar gradle-wrapper.jar
/.gradle /.gradle
/captures/ /captures/
/gradlew /gradlew
/gradlew.bat /gradlew.bat
/local.properties /local.properties
GeneratedPluginRegistrant.java GeneratedPluginRegistrant.java
.cxx/ .cxx/
# Remember to never publicly share your keystore. # Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore # See https://flutter.dev/to/reference-keystore
key.properties key.properties
**/*.keystore **/*.keystore
**/*.jks **/*.jks
-80
View File
@@ -1,80 +0,0 @@
plugins {
id "com.android.application"
id "kotlin-android"
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'
}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
namespace "id.ptsemangat.siab_scale"
compileSdk 36
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
applicationId "id.ptsemangat.siab_scale"
minSdkVersion flutter.minSdkVersion
targetSdk 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
signingConfigs {
release {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
flutter {
source '../..'
}
dependencies {}
+1 -1
View File
@@ -14,7 +14,7 @@ if (keystorePropertiesFile.exists()) {
android { android {
namespace = "id.ptsemangat.siab_scale" namespace = "id.ptsemangat.siab_scale"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = "27.0.12077973"
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_11 sourceCompatibility = JavaVersion.VERSION_11
+7
View File
@@ -6,6 +6,12 @@
-keep class io.flutter.** { *; } -keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; } -keep class io.flutter.plugins.** { *; }
# Play Core deferred components
-dontwarn com.google.android.play.core.**
-dontwarn com.google.android.play.core.splitcompat.**
-dontwarn com.google.android.play.core.splitinstall.**
-dontwarn com.google.android.play.core.tasks.**
# SIAB Scale app # SIAB Scale app
-keep class id.ptsemangat.siab_scale.** { *; } -keep class id.ptsemangat.siab_scale.** { *; }
@@ -14,3 +20,4 @@
# sqflite # sqflite
-keep class com.tekartik.sqflite.** { *; } -keep class com.tekartik.sqflite.** { *; }
+7 -7
View File
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically, <!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
</manifest> </manifest>
+37 -37
View File
@@ -1,37 +1,37 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <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_COARSE_LOCATION"/>
<!-- Storage permissions for saving CSV to Downloads on older Android versions --> <!-- Storage permissions for saving CSV to Downloads on older Android versions -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29"/>
<application <application
android:label="SIAB Scale" android:label="SIAB Scale"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<meta-data <meta-data
android:name="io.flutter.embedding.android.NormalTheme" android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme"
/> />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<meta-data <meta-data
android:name="flutterEmbedding" android:name="flutterEmbedding"
android:value="2" /> android:value="2" />
</application> </application>
</manifest> </manifest>
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen --> <!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" /> <item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here --> <!-- You can insert your own image assets here -->
<!-- <item> <!-- <item>
<bitmap <bitmap
android:gravity="center" android:gravity="center"
android:src="@mipmap/launch_image" /> android:src="@mipmap/launch_image" />
</item> --> </item> -->
</layer-list> </layer-list>
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen --> <!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" /> <item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here --> <!-- You can insert your own image assets here -->
<!-- <item> <!-- <item>
<bitmap <bitmap
android:gravity="center" android:gravity="center"
android:src="@mipmap/launch_image" /> android:src="@mipmap/launch_image" />
</item> --> </item> -->
</layer-list> </layer-list>
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on --> <!-- 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"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its Flutter UI initializes, as well as behind your Flutter UI while its
running. running.
This Theme is only used starting with V2 of Flutter's Android embedding. --> This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item> <item name="android:windowBackground">?android:colorBackground</item>
</style> </style>
</resources> </resources>
+18 -18
View File
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off --> <!-- 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"> <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its Flutter UI initializes, as well as behind your Flutter UI while its
running. running.
This Theme is only used starting with V2 of Flutter's Android embedding. --> This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar"> <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item> <item name="android:windowBackground">?android:colorBackground</item>
</style> </style>
</resources> </resources>
+7 -7
View File
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically, <!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
</manifest> </manifest>
-31
View File
@@ -1,31 +0,0 @@
buildscript {
ext.kotlin_version = '2.0.0'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
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
}
+24 -24
View File
@@ -1,24 +1,24 @@
allprojects { allprojects {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
} }
} }
val newBuildDir: Directory = val newBuildDir: Directory =
rootProject.layout.buildDirectory rootProject.layout.buildDirectory
.dir("../../build") .dir("../../build")
.get() .get()
rootProject.layout.buildDirectory.value(newBuildDir) rootProject.layout.buildDirectory.value(newBuildDir)
subprojects { subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir) project.layout.buildDirectory.value(newSubprojectBuildDir)
} }
subprojects { subprojects {
project.evaluationDependsOn(":app") project.evaluationDependsOn(":app")
} }
tasks.register<Delete>("clean") { tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory) delete(rootProject.layout.buildDirectory)
} }
+5 -5
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip
+26 -26
View File
@@ -1,26 +1,26 @@
pluginManagement { pluginManagement {
val flutterSdkPath = val flutterSdkPath =
run { run {
val properties = java.util.Properties() val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) } file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk") val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath flutterSdkPath
} }
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
} }
} }
plugins { plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.9.1" apply false id("com.android.application") version "9.0.0" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false id("org.jetbrains.kotlin.android") version "2.2.20" apply false
} }
include(":app") include(":app")
Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 432 432" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-11247.479417,-220.878492)">
<g transform="matrix(3.556675,0,0,1,2063.451047,0)">
<g transform="matrix(0.134003,0,0,0.476604,2271.742994,75.055391)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:rgb(0,214,156);"/>
</g>
<g transform="matrix(0.959532,0,0,0.959532,-7272.887866,171.062992)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171Z" style="fill:rgb(6,29,132);"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 432 432" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-11876.484028,-220.878492)">
<g transform="matrix(3.556675,0,0,1,2063.451047,0)">
<g transform="matrix(0.134003,0,0,0.476604,2448.59488,75.055391)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:white;"/>
</g>
<g transform="matrix(0.959532,0,0,0.959532,-7272.887866,171.062992)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171Z" style="fill:rgb(6,29,132);"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 432 432" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-10629.023523,-220.878492)">
<g transform="matrix(3.556675,0,0,1,2063.451047,0)">
<g transform="matrix(0.84375,0,0,0.84375,-299.008261,-854.902758)">
<g transform="matrix(0.103708,0,0,0.368856,2971.190037,1118.626194)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:white;"/>
</g>
<g transform="matrix(0.152391,0,0,0.542006,1685.662521,1198.800036)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084Z" style="fill:rgb(0,214,156);"/>
</g>
<g transform="matrix(0.281162,0,0,1,-580.163012,0)">
<path d="M13654.154,1424.909C13653.821,1422.761 13654.447,1420.574 13655.866,1418.927C13657.284,1417.279 13659.354,1416.337 13661.528,1416.348L13676.126,1416.42C13679.774,1416.439 13682.868,1419.104 13683.427,1422.708L13684.752,1431.264C13685.508,1436.146 13689.711,1439.747 13694.651,1439.747L13767.522,1439.747C13772.399,1439.747 13776.567,1436.235 13777.394,1431.429L13779.489,1422.245C13780.261,1418.858 13783.278,1416.46 13786.752,1416.471L13800.868,1416.518C13803.053,1416.525 13805.124,1417.494 13806.529,1419.168C13807.935,1420.841 13808.531,1423.048 13808.161,1425.202L13806.234,1436.394C13802.99,1455.24 13786.645,1469.012 13767.522,1469.012L13694.651,1469.012C13675.278,1469.012 13658.798,1454.888 13655.832,1435.744L13654.154,1424.909Z" style="fill:rgb(6,29,132);"/>
</g>
<g transform="matrix(0.281162,0,0,1,-580.163012,0)">
<path d="M13817.591,1578.978C13820.443,1595.544 13815.838,1612.524 13805.007,1625.379C13794.176,1638.233 13778.223,1645.652 13761.414,1645.652L13701.897,1645.652C13685.255,1645.652 13669.444,1638.379 13658.614,1625.743C13647.784,1613.106 13643.018,1596.368 13645.565,1579.921L13653.84,1526.509C13657.953,1499.965 13680.803,1480.382 13707.664,1480.382L13754.728,1480.382C13781.244,1480.382 13803.906,1499.477 13808.405,1525.608L13817.591,1578.978ZM13780.755,1537.49C13777.986,1521.402 13764.033,1509.646 13747.708,1509.646L13714.804,1509.646C13698.267,1509.646 13684.198,1521.703 13681.667,1538.045L13674.732,1582.806C13673.43,1591.208 13675.866,1599.76 13681.399,1606.216C13686.932,1612.672 13695.01,1616.388 13703.513,1616.388L13759.771,1616.388C13768.359,1616.388 13776.509,1612.598 13782.043,1606.03C13787.576,1599.462 13789.929,1590.787 13788.472,1582.324L13780.755,1537.49Z" style="fill:rgb(6,29,132);"/>
</g>
<g transform="matrix(0.281162,0,0,1,-580.163012,0)">
<path d="M13759.719,1547.897C13760.639,1546.977 13761.96,1546.58 13763.234,1546.842C13764.509,1547.103 13765.568,1547.987 13766.052,1549.195C13767.808,1553.539 13768.776,1558.285 13768.776,1563.255C13768.776,1583.963 13751.964,1600.776 13731.255,1600.776C13710.547,1600.776 13693.735,1583.963 13693.735,1563.255C13693.735,1542.546 13710.547,1525.734 13731.255,1525.734C13736.226,1525.734 13740.971,1526.702 13745.314,1528.461C13746.521,1528.944 13747.405,1530.002 13747.666,1531.276C13747.927,1532.55 13747.531,1533.871 13746.611,1534.79C13741.819,1539.585 13733.612,1547.793 13728.718,1552.686C13726.5,1554.904 13726.501,1558.5 13728.718,1560.717L13733.793,1565.792C13736.01,1568.01 13739.606,1568.01 13741.824,1565.792L13759.719,1547.897Z" style="fill:rgb(6,29,132);"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 432 432" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-10052.182314,-215.925716)">
<g transform="matrix(3.556675,0,0,1,2063.451047,0)">
<g transform="matrix(0.134003,0,0,0.476604,1935.671456,70.102616)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:rgb(6,29,132);"/>
</g>
<g transform="matrix(0.646902,0,0,0.646902,822.275361,112.266714)">
<g transform="matrix(1.483273,0,0,1.483273,-12513.742858,90.889027)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538Z" style="fill:white;"/>
</g>
<g transform="matrix(0.837848,0,0,0.837848,563.311523,258.627883)">
<g transform="matrix(0.764685,0,0,0.764685,1814.51336,-94.801291)">
<g transform="matrix(0.843817,0,0,1,973.42738,670.673266)">
<path d="M996.456,815.382C1010.891,886.141 987.579,958.668 932.752,1013.576C877.925,1068.484 797.174,1100.174 712.085,1100.174C614.422,1100.174 508.13,1100.174 410.814,1100.174C326.571,1100.174 246.534,1069.108 191.713,1015.131C136.893,961.155 112.765,889.659 125.662,819.41C139.686,743.025 154.576,661.927 167.549,591.266C188.366,477.884 304.034,394.237 440.005,394.237C516.746,394.237 601.794,394.237 678.242,394.237C812.464,394.237 927.183,475.799 949.952,587.417C964.298,657.739 980.831,738.787 996.456,815.382ZM809.991,638.17C795.972,569.452 725.344,519.237 642.709,519.237C589.643,519.237 529.429,519.237 476.147,519.237C392.435,519.237 321.222,570.735 308.406,640.54C297.616,699.31 284.584,770.291 273.304,831.73C266.715,867.62 279.042,904.148 307.05,931.725C335.058,959.302 375.949,975.174 418.99,975.174C507.403,975.174 614.937,975.174 703.769,975.174C747.242,975.174 788.498,958.983 816.51,930.93C844.521,902.878 856.431,865.823 849.056,829.672C836.451,767.879 821.939,696.744 809.991,638.17Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.843817,0,0,-1,973.42738,1410.581134)">
<path d="M169.137,582.616C167.452,591.793 170.619,601.132 177.801,608.169C184.983,615.205 195.46,619.231 206.465,619.185C230.149,619.085 258.821,618.965 280.361,618.874C298.825,618.797 314.488,607.413 317.315,592.016C320.486,574.745 324.024,555.473 324.024,555.473C327.852,534.621 349.125,519.237 374.132,519.237L743.005,519.237C767.69,519.237 788.789,534.237 792.976,554.765C792.976,554.765 798.715,575.995 803.581,593.996C807.492,608.461 822.764,618.705 840.347,618.656C860.96,618.6 888.653,618.523 911.802,618.459C922.863,618.429 933.347,614.288 940.46,607.14C947.573,599.993 950.594,590.564 948.718,581.365C944.059,558.529 938.966,533.56 938.966,533.56C922.544,453.06 839.808,394.237 743.005,394.237L374.132,394.237C276.068,394.237 192.647,454.564 177.634,536.336C177.634,536.336 173.216,560.398 169.137,582.616Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.923041,-0,0,0.923041,854.504081,621.345248)">
<path d="M771.961,792.978C776.219,788.719 782.332,786.884 788.231,788.093C794.131,789.302 799.029,793.394 801.268,798.984C809.395,819.084 813.877,841.045 813.877,864.045C813.877,959.873 736.076,1037.674 640.248,1037.674C544.419,1037.674 466.619,959.873 466.619,864.045C466.619,768.216 544.419,690.416 640.248,690.416C663.247,690.416 685.208,694.897 705.305,703.034C710.892,705.272 714.981,710.167 716.189,716.063C717.398,721.96 715.564,728.068 711.308,732.324C689.133,754.513 651.152,792.493 628.507,815.139C618.244,825.402 618.244,842.041 628.507,852.303C635.961,859.758 644.535,868.331 651.989,875.786C662.252,886.048 678.891,886.048 689.153,875.786C711.799,853.14 749.779,815.16 771.961,792.978Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 432 432" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-13047.92582,-215.925716)">
<g transform="matrix(3.556675,0,0,1,2063.451047,0)">
<g transform="matrix(0.134003,0,0,0.476604,2777.959223,70.102616)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:none;"/>
</g>
<g transform="matrix(0.646902,0,0,0.646902,822.275361,112.266714)">
<g transform="matrix(1.483273,0,0,1.483273,-12513.742858,90.889027)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538Z" style="fill:white;"/>
</g>
<g transform="matrix(0.837848,0,0,0.837848,563.311523,258.627883)">
<g transform="matrix(0.764685,0,0,0.764685,1814.51336,-94.801291)">
<g transform="matrix(0.843817,0,0,1,973.42738,670.673266)">
<path d="M996.456,815.382C1010.891,886.141 987.579,958.668 932.752,1013.576C877.925,1068.484 797.174,1100.174 712.085,1100.174C614.422,1100.174 508.13,1100.174 410.814,1100.174C326.571,1100.174 246.534,1069.108 191.713,1015.131C136.893,961.155 112.765,889.659 125.662,819.41C139.686,743.025 154.576,661.927 167.549,591.266C188.366,477.884 304.034,394.237 440.005,394.237C516.746,394.237 601.794,394.237 678.242,394.237C812.464,394.237 927.183,475.799 949.952,587.417C964.298,657.739 980.831,738.787 996.456,815.382ZM809.991,638.17C795.972,569.452 725.344,519.237 642.709,519.237C589.643,519.237 529.429,519.237 476.147,519.237C392.435,519.237 321.222,570.735 308.406,640.54C297.616,699.31 284.584,770.291 273.304,831.73C266.715,867.62 279.042,904.148 307.05,931.725C335.058,959.302 375.949,975.174 418.99,975.174C507.403,975.174 614.937,975.174 703.769,975.174C747.242,975.174 788.498,958.983 816.51,930.93C844.521,902.878 856.431,865.823 849.056,829.672C836.451,767.879 821.939,696.744 809.991,638.17Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.843817,0,0,-1,973.42738,1410.581134)">
<path d="M169.137,582.616C167.452,591.793 170.619,601.132 177.801,608.169C184.983,615.205 195.46,619.231 206.465,619.185C230.149,619.085 258.821,618.965 280.361,618.874C298.825,618.797 314.488,607.413 317.315,592.016C320.486,574.745 324.024,555.473 324.024,555.473C327.852,534.621 349.125,519.237 374.132,519.237L743.005,519.237C767.69,519.237 788.789,534.237 792.976,554.765C792.976,554.765 798.715,575.995 803.581,593.996C807.492,608.461 822.764,618.705 840.347,618.656C860.96,618.6 888.653,618.523 911.802,618.459C922.863,618.429 933.347,614.288 940.46,607.14C947.573,599.993 950.594,590.564 948.718,581.365C944.059,558.529 938.966,533.56 938.966,533.56C922.544,453.06 839.808,394.237 743.005,394.237L374.132,394.237C276.068,394.237 192.647,454.564 177.634,536.336C177.634,536.336 173.216,560.398 169.137,582.616Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.923041,-0,0,0.923041,854.504081,621.345248)">
<path d="M771.961,792.978C776.219,788.719 782.332,786.884 788.231,788.093C794.131,789.302 799.029,793.394 801.268,798.984C809.395,819.084 813.877,841.045 813.877,864.045C813.877,959.873 736.076,1037.674 640.248,1037.674C544.419,1037.674 466.619,959.873 466.619,864.045C466.619,768.216 544.419,690.416 640.248,690.416C663.247,690.416 685.208,694.897 705.305,703.034C710.892,705.272 714.981,710.167 716.189,716.063C717.398,721.96 715.564,728.068 711.308,732.324C689.133,754.513 651.152,792.493 628.507,815.139C618.244,825.402 618.244,842.041 628.507,852.303C635.961,859.758 644.535,868.331 651.989,875.786C662.252,886.048 678.891,886.048 689.153,875.786C711.799,853.14 749.779,815.16 771.961,792.978Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 432 432" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-12479.308577,-215.925716)">
<g transform="matrix(3.556675,0,0,1,2063.451047,0)">
<g transform="matrix(0.134003,0,0,0.476604,2618.08594,70.102616)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:white;"/>
</g>
<g transform="matrix(0.646902,0,0,0.646902,822.275361,112.266714)">
<g transform="matrix(1.483273,0,0,1.483273,-12513.742858,90.889027)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538Z" style="fill:white;"/>
</g>
<g transform="matrix(0.837848,0,0,0.837848,563.311523,258.627883)">
<g transform="matrix(0.764685,0,0,0.764685,1814.51336,-94.801291)">
<g transform="matrix(0.843817,0,0,1,973.42738,670.673266)">
<path d="M996.456,815.382C1010.891,886.141 987.579,958.668 932.752,1013.576C877.925,1068.484 797.174,1100.174 712.085,1100.174C614.422,1100.174 508.13,1100.174 410.814,1100.174C326.571,1100.174 246.534,1069.108 191.713,1015.131C136.893,961.155 112.765,889.659 125.662,819.41C139.686,743.025 154.576,661.927 167.549,591.266C188.366,477.884 304.034,394.237 440.005,394.237C516.746,394.237 601.794,394.237 678.242,394.237C812.464,394.237 927.183,475.799 949.952,587.417C964.298,657.739 980.831,738.787 996.456,815.382ZM809.991,638.17C795.972,569.452 725.344,519.237 642.709,519.237C589.643,519.237 529.429,519.237 476.147,519.237C392.435,519.237 321.222,570.735 308.406,640.54C297.616,699.31 284.584,770.291 273.304,831.73C266.715,867.62 279.042,904.148 307.05,931.725C335.058,959.302 375.949,975.174 418.99,975.174C507.403,975.174 614.937,975.174 703.769,975.174C747.242,975.174 788.498,958.983 816.51,930.93C844.521,902.878 856.431,865.823 849.056,829.672C836.451,767.879 821.939,696.744 809.991,638.17Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.843817,0,0,-1,973.42738,1410.581134)">
<path d="M169.137,582.616C167.452,591.793 170.619,601.132 177.801,608.169C184.983,615.205 195.46,619.231 206.465,619.185C230.149,619.085 258.821,618.965 280.361,618.874C298.825,618.797 314.488,607.413 317.315,592.016C320.486,574.745 324.024,555.473 324.024,555.473C327.852,534.621 349.125,519.237 374.132,519.237L743.005,519.237C767.69,519.237 788.789,534.237 792.976,554.765C792.976,554.765 798.715,575.995 803.581,593.996C807.492,608.461 822.764,618.705 840.347,618.656C860.96,618.6 888.653,618.523 911.802,618.459C922.863,618.429 933.347,614.288 940.46,607.14C947.573,599.993 950.594,590.564 948.718,581.365C944.059,558.529 938.966,533.56 938.966,533.56C922.544,453.06 839.808,394.237 743.005,394.237L374.132,394.237C276.068,394.237 192.647,454.564 177.634,536.336C177.634,536.336 173.216,560.398 169.137,582.616Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.923041,-0,0,0.923041,854.504081,621.345248)">
<path d="M771.961,792.978C776.219,788.719 782.332,786.884 788.231,788.093C794.131,789.302 799.029,793.394 801.268,798.984C809.395,819.084 813.877,841.045 813.877,864.045C813.877,959.873 736.076,1037.674 640.248,1037.674C544.419,1037.674 466.619,959.873 466.619,864.045C466.619,768.216 544.419,690.416 640.248,690.416C663.247,690.416 685.208,694.897 705.305,703.034C710.892,705.272 714.981,710.167 716.189,716.063C717.398,721.96 715.564,728.068 711.308,732.324C689.133,754.513 651.152,792.493 628.507,815.139C618.244,825.402 618.244,842.041 628.507,852.303C635.961,859.758 644.535,868.331 651.989,875.786C662.252,886.048 678.891,886.048 689.153,875.786C711.799,853.14 749.779,815.16 771.961,792.978Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-11169.931337,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,9861.276207,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:rgb(6,29,132);"/>
</g>
<g transform="matrix(0.646902,0,0,0.646902,822.275361,112.266714)">
<g transform="matrix(1.483273,0,0,1.483273,-12513.742858,90.889027)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538Z" style="fill:white;"/>
</g>
<g transform="matrix(0.837848,0,0,0.837848,563.311523,258.627883)">
<g transform="matrix(0.764685,0,0,0.764685,1814.51336,-94.801291)">
<g transform="matrix(0.843817,0,0,1,973.42738,670.673266)">
<path d="M996.456,815.382C1010.891,886.141 987.579,958.668 932.752,1013.576C877.925,1068.484 797.174,1100.174 712.085,1100.174C614.422,1100.174 508.13,1100.174 410.814,1100.174C326.571,1100.174 246.534,1069.108 191.713,1015.131C136.893,961.155 112.765,889.659 125.662,819.41C139.686,743.025 154.576,661.927 167.549,591.266C188.366,477.884 304.034,394.237 440.005,394.237C516.746,394.237 601.794,394.237 678.242,394.237C812.464,394.237 927.183,475.799 949.952,587.417C964.298,657.739 980.831,738.787 996.456,815.382ZM809.991,638.17C795.972,569.452 725.344,519.237 642.709,519.237C589.643,519.237 529.429,519.237 476.147,519.237C392.435,519.237 321.222,570.735 308.406,640.54C297.616,699.31 284.584,770.291 273.304,831.73C266.715,867.62 279.042,904.148 307.05,931.725C335.058,959.302 375.949,975.174 418.99,975.174C507.403,975.174 614.937,975.174 703.769,975.174C747.242,975.174 788.498,958.983 816.51,930.93C844.521,902.878 856.431,865.823 849.056,829.672C836.451,767.879 821.939,696.744 809.991,638.17Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.843817,0,0,-1,973.42738,1410.581134)">
<path d="M169.137,582.616C167.452,591.793 170.619,601.132 177.801,608.169C184.983,615.205 195.46,619.231 206.465,619.185C230.149,619.085 258.821,618.965 280.361,618.874C298.825,618.797 314.488,607.413 317.315,592.016C320.486,574.745 324.024,555.473 324.024,555.473C327.852,534.621 349.125,519.237 374.132,519.237L743.005,519.237C767.69,519.237 788.789,534.237 792.976,554.765C792.976,554.765 798.715,575.995 803.581,593.996C807.492,608.461 822.764,618.705 840.347,618.656C860.96,618.6 888.653,618.523 911.802,618.459C922.863,618.429 933.347,614.288 940.46,607.14C947.573,599.993 950.594,590.564 948.718,581.365C944.059,558.529 938.966,533.56 938.966,533.56C922.544,453.06 839.808,394.237 743.005,394.237L374.132,394.237C276.068,394.237 192.647,454.564 177.634,536.336C177.634,536.336 173.216,560.398 169.137,582.616Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.923041,-0,0,0.923041,854.504081,621.345248)">
<path d="M771.961,792.978C776.219,788.719 782.332,786.884 788.231,788.093C794.131,789.302 799.029,793.394 801.268,798.984C809.395,819.084 813.877,841.045 813.877,864.045C813.877,959.873 736.076,1037.674 640.248,1037.674C544.419,1037.674 466.619,959.873 466.619,864.045C466.619,768.216 544.419,690.416 640.248,690.416C663.247,690.416 685.208,694.897 705.305,703.034C710.892,705.272 714.981,710.167 716.189,716.063C717.398,721.96 715.564,728.068 711.308,732.324C689.133,754.513 651.152,792.493 628.507,815.139C618.244,825.402 618.244,842.041 628.507,852.303C635.961,859.758 644.535,868.331 651.989,875.786C662.252,886.048 678.891,886.048 689.153,875.786C711.799,853.14 749.779,815.16 771.961,792.978Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-9924.644661,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,8615.989531,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:none;"/>
</g>
<g transform="matrix(0.646902,0,0,0.646902,822.275361,112.266714)">
<g transform="matrix(1.483273,0,0,1.483273,-12513.742858,90.889027)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538Z" style="fill:white;"/>
</g>
<g transform="matrix(0.837848,0,0,0.837848,563.311523,258.627883)">
<g transform="matrix(0.764685,0,0,0.764685,1814.51336,-94.801291)">
<g transform="matrix(0.843817,0,0,1,973.42738,670.673266)">
<path d="M996.456,815.382C1010.891,886.141 987.579,958.668 932.752,1013.576C877.925,1068.484 797.174,1100.174 712.085,1100.174C614.422,1100.174 508.13,1100.174 410.814,1100.174C326.571,1100.174 246.534,1069.108 191.713,1015.131C136.893,961.155 112.765,889.659 125.662,819.41C139.686,743.025 154.576,661.927 167.549,591.266C188.366,477.884 304.034,394.237 440.005,394.237C516.746,394.237 601.794,394.237 678.242,394.237C812.464,394.237 927.183,475.799 949.952,587.417C964.298,657.739 980.831,738.787 996.456,815.382ZM809.991,638.17C795.972,569.452 725.344,519.237 642.709,519.237C589.643,519.237 529.429,519.237 476.147,519.237C392.435,519.237 321.222,570.735 308.406,640.54C297.616,699.31 284.584,770.291 273.304,831.73C266.715,867.62 279.042,904.148 307.05,931.725C335.058,959.302 375.949,975.174 418.99,975.174C507.403,975.174 614.937,975.174 703.769,975.174C747.242,975.174 788.498,958.983 816.51,930.93C844.521,902.878 856.431,865.823 849.056,829.672C836.451,767.879 821.939,696.744 809.991,638.17Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.843817,0,0,-1,973.42738,1410.581134)">
<path d="M169.137,582.616C167.452,591.793 170.619,601.132 177.801,608.169C184.983,615.205 195.46,619.231 206.465,619.185C230.149,619.085 258.821,618.965 280.361,618.874C298.825,618.797 314.488,607.413 317.315,592.016C320.486,574.745 324.024,555.473 324.024,555.473C327.852,534.621 349.125,519.237 374.132,519.237L743.005,519.237C767.69,519.237 788.789,534.237 792.976,554.765C792.976,554.765 798.715,575.995 803.581,593.996C807.492,608.461 822.764,618.705 840.347,618.656C860.96,618.6 888.653,618.523 911.802,618.459C922.863,618.429 933.347,614.288 940.46,607.14C947.573,599.993 950.594,590.564 948.718,581.365C944.059,558.529 938.966,533.56 938.966,533.56C922.544,453.06 839.808,394.237 743.005,394.237L374.132,394.237C276.068,394.237 192.647,454.564 177.634,536.336C177.634,536.336 173.216,560.398 169.137,582.616Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.923041,-0,0,0.923041,854.504081,621.345248)">
<path d="M771.961,792.978C776.219,788.719 782.332,786.884 788.231,788.093C794.131,789.302 799.029,793.394 801.268,798.984C809.395,819.084 813.877,841.045 813.877,864.045C813.877,959.873 736.076,1037.674 640.248,1037.674C544.419,1037.674 466.619,959.873 466.619,864.045C466.619,768.216 544.419,690.416 640.248,690.416C663.247,690.416 685.208,694.897 705.305,703.034C710.892,705.272 714.981,710.167 716.189,716.063C717.398,721.96 715.564,728.068 711.308,732.324C689.133,754.513 651.152,792.493 628.507,815.139C618.244,825.402 618.244,842.041 628.507,852.303C635.961,859.758 644.535,868.331 651.989,875.786C662.252,886.048 678.891,886.048 689.153,875.786C711.799,853.14 749.779,815.16 771.961,792.978Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-10529.681152,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,9221.026021,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:white;"/>
</g>
<g transform="matrix(0.646902,0,0,0.646902,822.275361,112.266714)">
<g transform="matrix(1.483273,0,0,1.483273,-12513.742858,90.889027)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538Z" style="fill:white;"/>
</g>
<g transform="matrix(0.837848,0,0,0.837848,563.311523,258.627883)">
<g transform="matrix(0.764685,0,0,0.764685,1814.51336,-94.801291)">
<g transform="matrix(0.843817,0,0,1,973.42738,670.673266)">
<path d="M996.456,815.382C1010.891,886.141 987.579,958.668 932.752,1013.576C877.925,1068.484 797.174,1100.174 712.085,1100.174C614.422,1100.174 508.13,1100.174 410.814,1100.174C326.571,1100.174 246.534,1069.108 191.713,1015.131C136.893,961.155 112.765,889.659 125.662,819.41C139.686,743.025 154.576,661.927 167.549,591.266C188.366,477.884 304.034,394.237 440.005,394.237C516.746,394.237 601.794,394.237 678.242,394.237C812.464,394.237 927.183,475.799 949.952,587.417C964.298,657.739 980.831,738.787 996.456,815.382ZM809.991,638.17C795.972,569.452 725.344,519.237 642.709,519.237C589.643,519.237 529.429,519.237 476.147,519.237C392.435,519.237 321.222,570.735 308.406,640.54C297.616,699.31 284.584,770.291 273.304,831.73C266.715,867.62 279.042,904.148 307.05,931.725C335.058,959.302 375.949,975.174 418.99,975.174C507.403,975.174 614.937,975.174 703.769,975.174C747.242,975.174 788.498,958.983 816.51,930.93C844.521,902.878 856.431,865.823 849.056,829.672C836.451,767.879 821.939,696.744 809.991,638.17Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.843817,0,0,-1,973.42738,1410.581134)">
<path d="M169.137,582.616C167.452,591.793 170.619,601.132 177.801,608.169C184.983,615.205 195.46,619.231 206.465,619.185C230.149,619.085 258.821,618.965 280.361,618.874C298.825,618.797 314.488,607.413 317.315,592.016C320.486,574.745 324.024,555.473 324.024,555.473C327.852,534.621 349.125,519.237 374.132,519.237L743.005,519.237C767.69,519.237 788.789,534.237 792.976,554.765C792.976,554.765 798.715,575.995 803.581,593.996C807.492,608.461 822.764,618.705 840.347,618.656C860.96,618.6 888.653,618.523 911.802,618.459C922.863,618.429 933.347,614.288 940.46,607.14C947.573,599.993 950.594,590.564 948.718,581.365C944.059,558.529 938.966,533.56 938.966,533.56C922.544,453.06 839.808,394.237 743.005,394.237L374.132,394.237C276.068,394.237 192.647,454.564 177.634,536.336C177.634,536.336 173.216,560.398 169.137,582.616Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.923041,-0,0,0.923041,854.504081,621.345248)">
<path d="M771.961,792.978C776.219,788.719 782.332,786.884 788.231,788.093C794.131,789.302 799.029,793.394 801.268,798.984C809.395,819.084 813.877,841.045 813.877,864.045C813.877,959.873 736.076,1037.674 640.248,1037.674C544.419,1037.674 466.619,959.873 466.619,864.045C466.619,768.216 544.419,690.416 640.248,690.416C663.247,690.416 685.208,694.897 705.305,703.034C710.892,705.272 714.981,710.167 716.189,716.063C717.398,721.96 715.564,728.068 711.308,732.324C689.133,754.513 651.152,792.493 628.507,815.139C618.244,825.402 618.244,842.041 628.507,852.303C635.961,859.758 644.535,868.331 651.989,875.786C662.252,886.048 678.891,886.048 689.153,875.786C711.799,853.14 749.779,815.16 771.961,792.978Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-16148.147117,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,14839.491987,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:rgb(0,214,156);"/>
</g>
<g transform="matrix(0.959532,0,0,0.959532,-7272.887866,171.062992)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171Z" style="fill:rgb(6,29,132);"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-14943.31376,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,13634.65863,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:none;"/>
</g>
<g transform="matrix(0.959532,0,0,0.959532,-7272.887866,171.062992)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171Z" style="fill:rgb(6,29,132);"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-15515.751862,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,14207.096732,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:white;"/>
</g>
<g transform="matrix(0.959532,0,0,0.959532,-7272.887866,171.062992)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171Z" style="fill:rgb(6,29,132);"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-14156.761195,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,12848.106064,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:rgb(6,29,132);"/>
</g>
<g transform="matrix(0.959532,0,0,0.959532,-7272.887866,171.062992)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-13013.456547,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,11704.801417,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:none;"/>
</g>
<g transform="matrix(0.959532,0,0,0.959532,-7272.887866,171.062992)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-13532.302289,726.774609)">
<g transform="matrix(0.564865,0,0,0.564865,12223.647158,-899.601987)">
<g transform="matrix(0.652999,0,0,0.652999,821.447853,29.128352)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:white;"/>
</g>
<g transform="matrix(0.959532,0,0,0.959532,-7272.887866,171.062992)">
<path d="M10755.151,468.538L10755.151,757.28C10755.151,836.961 10690.46,901.651 10610.78,901.651L10322.037,901.651C10242.357,901.651 10177.666,836.961 10177.666,757.28L10177.666,468.538C10177.666,388.857 10242.357,324.166 10322.037,324.166L10610.78,324.166C10690.46,324.166 10755.151,388.857 10755.151,468.538ZM10323.418,417.171L10326.515,437.161C10331.987,472.482 10362.392,498.54 10398.135,498.54L10532.582,498.54C10567.865,498.54 10598.02,473.132 10604.006,438.36L10607.56,417.711C10608.244,413.738 10607.143,409.665 10604.55,406.578C10601.958,403.491 10598.137,401.702 10594.105,401.689L10568.061,401.604C10561.653,401.583 10556.086,406.008 10554.661,412.256L10550.796,429.201C10549.269,438.068 10541.579,444.547 10532.582,444.547L10398.135,444.547C10389.02,444.547 10381.267,437.902 10379.871,428.895L10377.426,413.111C10376.396,406.46 10370.687,401.543 10363.957,401.51L10337.023,401.375C10333.012,401.355 10329.194,403.094 10326.576,406.134C10323.958,409.173 10322.804,413.207 10323.418,417.171ZM10624.96,701.428L10608.01,602.96C10599.711,554.748 10557.898,519.518 10508.977,519.518L10422.144,519.518C10372.585,519.518 10330.426,555.648 10322.839,604.623L10307.572,703.169C10302.871,733.512 10311.666,764.394 10331.647,787.709C10351.628,811.024 10380.799,824.442 10411.505,824.442L10521.312,824.442C10552.325,824.442 10581.758,810.754 10601.741,787.037C10621.724,763.32 10630.221,731.992 10624.96,701.428ZM10556.997,624.883L10571.236,707.601C10573.924,723.216 10569.583,739.222 10559.373,751.339C10549.163,763.456 10534.126,770.45 10518.281,770.45L10414.485,770.45C10398.797,770.45 10383.893,763.594 10373.685,751.682C10363.476,739.771 10358.983,723.993 10361.385,708.49L10374.179,625.907C10378.85,595.755 10404.806,573.511 10435.317,573.511L10496.026,573.511C10526.145,573.511 10551.887,595.201 10556.997,624.883ZM10518.185,644.084L10485.169,677.1C10481.077,681.192 10474.443,681.192 10470.352,677.1L10460.989,667.737C10456.897,663.646 10456.897,657.012 10460.989,652.92C10470.018,643.891 10485.161,628.748 10494.002,619.902C10495.699,618.205 10496.43,615.769 10495.948,613.418C10495.466,611.068 10493.836,609.116 10491.609,608.224C10483.596,604.979 10474.84,603.193 10465.67,603.193C10427.463,603.193 10396.444,634.212 10396.444,672.419C10396.444,710.626 10427.463,741.645 10465.67,741.645C10503.877,741.645 10534.896,710.626 10534.896,672.419C10534.896,663.249 10533.11,654.493 10529.869,646.479C10528.976,644.25 10527.024,642.619 10524.672,642.137C10522.319,641.655 10519.882,642.386 10518.185,644.084Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-12501.456547,726.774609)">
<g transform="matrix(1,0,0,1,-151.472291,0)">
<g transform="matrix(0.683604,0,0,0.683604,10912.013984,-1075.663646)">
<g transform="matrix(0.764685,0,0,0.764685,1814.51336,-94.801291)">
<g transform="matrix(0.843817,0,0,1,973.42738,670.673266)">
<path d="M996.456,815.382C1010.891,886.141 987.579,958.668 932.752,1013.576C877.925,1068.484 797.174,1100.174 712.085,1100.174C614.422,1100.174 508.13,1100.174 410.814,1100.174C326.571,1100.174 246.534,1069.108 191.713,1015.131C136.893,961.155 112.765,889.659 125.662,819.41C139.686,743.025 154.576,661.927 167.549,591.266C188.366,477.884 304.034,394.237 440.005,394.237C516.746,394.237 601.794,394.237 678.242,394.237C812.464,394.237 927.183,475.799 949.952,587.417C964.298,657.739 980.831,738.787 996.456,815.382ZM809.991,638.17C795.972,569.452 725.344,519.237 642.709,519.237C589.643,519.237 529.429,519.237 476.147,519.237C392.435,519.237 321.222,570.735 308.406,640.54C297.616,699.31 284.584,770.291 273.304,831.73C266.715,867.62 279.042,904.148 307.05,931.725C335.058,959.302 375.949,975.174 418.99,975.174C507.403,975.174 614.937,975.174 703.769,975.174C747.242,975.174 788.498,958.983 816.51,930.93C844.521,902.878 856.431,865.823 849.056,829.672C836.451,767.879 821.939,696.744 809.991,638.17Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.843817,0,0,-1,973.42738,1410.581134)">
<path d="M169.137,582.616C167.452,591.793 170.619,601.132 177.801,608.169C184.983,615.205 195.46,619.231 206.465,619.185C230.149,619.085 258.821,618.965 280.361,618.874C298.825,618.797 314.488,607.413 317.315,592.016C320.486,574.745 324.024,555.473 324.024,555.473C327.852,534.621 349.125,519.237 374.132,519.237L743.005,519.237C767.69,519.237 788.789,534.237 792.976,554.765C792.976,554.765 798.715,575.995 803.581,593.996C807.492,608.461 822.764,618.705 840.347,618.656C860.96,618.6 888.653,618.523 911.802,618.459C922.863,618.429 933.347,614.288 940.46,607.14C947.573,599.993 950.594,590.564 948.718,581.365C944.059,558.529 938.966,533.56 938.966,533.56C922.544,453.06 839.808,394.237 743.005,394.237L374.132,394.237C276.068,394.237 192.647,454.564 177.634,536.336C177.634,536.336 173.216,560.398 169.137,582.616Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.923041,-0,0,0.923041,854.504081,621.345248)">
<path d="M771.961,792.978C776.219,788.719 782.332,786.884 788.231,788.093C794.131,789.302 799.029,793.394 801.268,798.984C809.395,819.084 813.877,841.045 813.877,864.045C813.877,959.873 736.076,1037.674 640.248,1037.674C544.419,1037.674 466.619,959.873 466.619,864.045C466.619,768.216 544.419,690.416 640.248,690.416C663.247,690.416 685.208,694.897 705.305,703.034C710.892,705.272 714.981,710.167 716.189,716.063C717.398,721.96 715.564,728.068 711.308,732.324C689.133,754.513 651.152,792.493 628.507,815.139C618.244,825.402 618.244,842.041 628.507,852.303C635.961,859.758 644.535,868.331 651.989,875.786C662.252,886.048 678.891,886.048 689.153,875.786C711.799,853.14 749.779,815.16 771.961,792.978Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
<g transform="matrix(0.368856,0,0,0.368856,11808.280456,-883.148415)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:none;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-11884.181719,726.774609)">
<g transform="matrix(1,0,0,1,86.762524,160.29105)">
<g transform="matrix(0.30616,0,0,0.30616,11159.078973,-901.97185)">
<g transform="matrix(0.764685,0,0,0.764685,1814.51336,-94.801291)">
<g transform="matrix(0.843817,0,0,1,973.42738,670.673266)">
<path d="M996.456,815.382C1010.891,886.141 987.579,958.668 932.752,1013.576C877.925,1068.484 797.174,1100.174 712.085,1100.174C614.422,1100.174 508.13,1100.174 410.814,1100.174C326.571,1100.174 246.534,1069.108 191.713,1015.131C136.893,961.155 112.765,889.659 125.662,819.41C139.686,743.025 154.576,661.927 167.549,591.266C188.366,477.884 304.034,394.237 440.005,394.237C516.746,394.237 601.794,394.237 678.242,394.237C812.464,394.237 927.183,475.799 949.952,587.417C964.298,657.739 980.831,738.787 996.456,815.382ZM809.991,638.17C795.972,569.452 725.344,519.237 642.709,519.237C589.643,519.237 529.429,519.237 476.147,519.237C392.435,519.237 321.222,570.735 308.406,640.54C297.616,699.31 284.584,770.291 273.304,831.73C266.715,867.62 279.042,904.148 307.05,931.725C335.058,959.302 375.949,975.174 418.99,975.174C507.403,975.174 614.937,975.174 703.769,975.174C747.242,975.174 788.498,958.983 816.51,930.93C844.521,902.878 856.431,865.823 849.056,829.672C836.451,767.879 821.939,696.744 809.991,638.17Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.843817,0,0,-1,973.42738,1410.581134)">
<path d="M169.137,582.616C167.452,591.793 170.619,601.132 177.801,608.169C184.983,615.205 195.46,619.231 206.465,619.185C230.149,619.085 258.821,618.965 280.361,618.874C298.825,618.797 314.488,607.413 317.315,592.016C320.486,574.745 324.024,555.473 324.024,555.473C327.852,534.621 349.125,519.237 374.132,519.237L743.005,519.237C767.69,519.237 788.789,534.237 792.976,554.765C792.976,554.765 798.715,575.995 803.581,593.996C807.492,608.461 822.764,618.705 840.347,618.656C860.96,618.6 888.653,618.523 911.802,618.459C922.863,618.429 933.347,614.288 940.46,607.14C947.573,599.993 950.594,590.564 948.718,581.365C944.059,558.529 938.966,533.56 938.966,533.56C922.544,453.06 839.808,394.237 743.005,394.237L374.132,394.237C276.068,394.237 192.647,454.564 177.634,536.336C177.634,536.336 173.216,560.398 169.137,582.616Z" style="fill:rgb(23,66,255);"/>
</g>
<g transform="matrix(0.923041,-0,0,0.923041,854.504081,621.345248)">
<path d="M771.961,792.978C776.219,788.719 782.332,786.884 788.231,788.093C794.131,789.302 799.029,793.394 801.268,798.984C809.395,819.084 813.877,841.045 813.877,864.045C813.877,959.873 736.076,1037.674 640.248,1037.674C544.419,1037.674 466.619,959.873 466.619,864.045C466.619,768.216 544.419,690.416 640.248,690.416C663.247,690.416 685.208,694.897 705.305,703.034C710.892,705.272 714.981,710.167 716.189,716.063C717.398,721.96 715.564,728.068 711.308,732.324C689.133,754.513 651.152,792.493 628.507,815.139C618.244,825.402 618.244,842.041 628.507,852.303C635.961,859.758 644.535,868.331 651.989,875.786C662.252,886.048 678.891,886.048 689.153,875.786C711.799,853.14 749.779,815.16 771.961,792.978Z" style="fill:rgb(0,214,156);"/>
</g>
</g>
</g>
<g transform="matrix(0.368856,0,0,0.368856,10952.770812,-1043.439465)">
<rect x="2289.913" y="423.943" width="1388.075" height="1388.075" style="fill:none;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

+34 -34
View File
@@ -1,34 +1,34 @@
**/dgph **/dgph
*.mode1v3 *.mode1v3
*.mode2v3 *.mode2v3
*.moved-aside *.moved-aside
*.pbxuser *.pbxuser
*.perspectivev3 *.perspectivev3
**/*sync/ **/*sync/
.sconsign.dblite .sconsign.dblite
.tags* .tags*
**/.vagrant/ **/.vagrant/
**/DerivedData/ **/DerivedData/
Icon? Icon?
**/Pods/ **/Pods/
**/.symlinks/ **/.symlinks/
profile profile
xcuserdata xcuserdata
**/.generated/ **/.generated/
Flutter/App.framework Flutter/App.framework
Flutter/Flutter.framework Flutter/Flutter.framework
Flutter/Flutter.podspec Flutter/Flutter.podspec
Flutter/Generated.xcconfig Flutter/Generated.xcconfig
Flutter/ephemeral/ Flutter/ephemeral/
Flutter/app.flx Flutter/app.flx
Flutter/app.zip Flutter/app.zip
Flutter/flutter_assets/ Flutter/flutter_assets/
Flutter/flutter_export_environment.sh Flutter/flutter_export_environment.sh
ServiceDefinitions.json ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.* Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules. # Exceptions to above rules.
!default.mode1v3 !default.mode1v3
!default.mode2v3 !default.mode2v3
!default.pbxuser !default.pbxuser
!default.perspectivev3 !default.perspectivev3
+26 -26
View File
@@ -1,26 +1,26 @@
<?xml version="1.0" encoding="UTF-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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>App</string> <string>App</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string> <string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>App</string> <string>App</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0</string> <string>1.0</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>13.0</string> <string>13.0</string>
</dict> </dict>
</plist> </plist>
+1 -1
View File
@@ -1 +1 @@
#include "Generated.xcconfig" #include "Generated.xcconfig"
+1 -1
View File
@@ -1 +1 @@
#include "Generated.xcconfig" #include "Generated.xcconfig"
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "self:"> location = "self:">
</FileRef> </FileRef>
</Workspace> </Workspace>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>IDEDidComputeMac32BitWarning</key> <key>IDEDidComputeMac32BitWarning</key>
<true/> <true/>
</dict> </dict>
</plist> </plist>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>PreviewsEnabled</key> <key>PreviewsEnabled</key>
<false/> <false/>
</dict> </dict>
</plist> </plist>
@@ -1,101 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1510" LastUpgradeVersion = "1510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"> buildImplicitDependencies = "YES">
<BuildActionEntries> <BuildActionEntries>
<BuildActionEntry <BuildActionEntry
buildForTesting = "YES" buildForTesting = "YES"
buildForRunning = "YES" buildForRunning = "YES"
buildForProfiling = "YES" buildForProfiling = "YES"
buildForArchiving = "YES" buildForArchiving = "YES"
buildForAnalyzing = "YES"> buildForAnalyzing = "YES">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D" BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app" BuildableName = "Runner.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildActionEntry> </BuildActionEntry>
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D" BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app" BuildableName = "Runner.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<Testables> <Testables>
<TestableReference <TestableReference
skipped = "NO" skipped = "NO"
parallelizable = "YES"> parallelizable = "YES">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5" BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest" BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests" BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</TestableReference> </TestableReference>
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal" debugServiceExtension = "internal"
enableGPUValidationMode = "1" enableGPUValidationMode = "1"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<BuildableProductRunnable <BuildableProductRunnable
runnableDebuggingMode = "0"> runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D" BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app" BuildableName = "Runner.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Profile" buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<BuildableProductRunnable <BuildableProductRunnable
runnableDebuggingMode = "0"> runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D" BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app" BuildableName = "Runner.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction
buildConfiguration = "Debug"> buildConfiguration = "Debug">
</AnalyzeAction> </AnalyzeAction>
<ArchiveAction <ArchiveAction
buildConfiguration = "Release" buildConfiguration = "Release"
revealArchiveInOrganizer = "YES"> revealArchiveInOrganizer = "YES">
</ArchiveAction> </ArchiveAction>
</Scheme> </Scheme>
+7 -7
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
</Workspace> </Workspace>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>IDEDidComputeMac32BitWarning</key> <key>IDEDidComputeMac32BitWarning</key>
<true/> <true/>
</dict> </dict>
</plist> </plist>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>PreviewsEnabled</key> <key>PreviewsEnabled</key>
<false/> <false/>
</dict> </dict>
</plist> </plist>
+13 -13
View File
@@ -1,13 +1,13 @@
import Flutter import Flutter
import UIKit import UIKit
@main @main
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate {
override func application( override func application(
_ application: UIApplication, _ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool { ) -> Bool {
GeneratedPluginRegistrant.register(with: self) GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions) return super.application(application, didFinishLaunchingWithOptions: launchOptions)
} }
} }
@@ -1,122 +1,122 @@
{ {
"images" : [ "images" : [
{ {
"size" : "20x20", "size" : "20x20",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png", "filename" : "Icon-App-20x20@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "20x20", "size" : "20x20",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png", "filename" : "Icon-App-20x20@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png", "filename" : "Icon-App-29x29@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png", "filename" : "Icon-App-29x29@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png", "filename" : "Icon-App-29x29@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "40x40", "size" : "40x40",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png", "filename" : "Icon-App-40x40@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "40x40", "size" : "40x40",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png", "filename" : "Icon-App-40x40@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "60x60", "size" : "60x60",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png", "filename" : "Icon-App-60x60@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "60x60", "size" : "60x60",
"idiom" : "iphone", "idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png", "filename" : "Icon-App-60x60@3x.png",
"scale" : "3x" "scale" : "3x"
}, },
{ {
"size" : "20x20", "size" : "20x20",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png", "filename" : "Icon-App-20x20@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "20x20", "size" : "20x20",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png", "filename" : "Icon-App-20x20@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png", "filename" : "Icon-App-29x29@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "29x29", "size" : "29x29",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png", "filename" : "Icon-App-29x29@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "40x40", "size" : "40x40",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png", "filename" : "Icon-App-40x40@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "40x40", "size" : "40x40",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png", "filename" : "Icon-App-40x40@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "76x76", "size" : "76x76",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png", "filename" : "Icon-App-76x76@1x.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "76x76", "size" : "76x76",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png", "filename" : "Icon-App-76x76@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "83.5x83.5", "size" : "83.5x83.5",
"idiom" : "ipad", "idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png", "filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "1024x1024", "size" : "1024x1024",
"idiom" : "ios-marketing", "idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png", "filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x" "scale" : "1x"
} }
], ],
"info" : { "info" : {
"version" : 1, "version" : 1,
"author" : "xcode" "author" : "xcode"
} }
} }
+23 -23
View File
@@ -1,23 +1,23 @@
{ {
"images" : [ "images" : [
{ {
"idiom" : "universal", "idiom" : "universal",
"filename" : "LaunchImage.png", "filename" : "LaunchImage.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"idiom" : "universal", "idiom" : "universal",
"filename" : "LaunchImage@2x.png", "filename" : "LaunchImage@2x.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "universal", "idiom" : "universal",
"filename" : "LaunchImage@3x.png", "filename" : "LaunchImage@3x.png",
"scale" : "3x" "scale" : "3x"
} }
], ],
"info" : { "info" : {
"version" : 1, "version" : 1,
"author" : "xcode" "author" : "xcode"
} }
} }
+4 -4
View File
@@ -1,5 +1,5 @@
# Launch Screen Assets # Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory. 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. 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.
+37 -37
View File
@@ -1,37 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?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"> <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> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--View Controller--> <!--View Controller-->
<scene sceneID="EHf-IW-A2E"> <scene sceneID="EHf-IW-A2E">
<objects> <objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController"> <viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides> <layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/> <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/> <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"> <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView> </imageView>
</subviews> </subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/> <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"/> <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints> </constraints>
</view> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="53" y="375"/> <point key="canvasLocation" x="53" y="375"/>
</scene> </scene>
</scenes> </scenes>
<resources> <resources>
<image name="LaunchImage" width="168" height="185"/> <image name="LaunchImage" width="168" height="185"/>
</resources> </resources>
</document> </document>
+26 -26
View File
@@ -1,26 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?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"> <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> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--Flutter View Controller--> <!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu"> <scene sceneID="tne-QT-ifu">
<objects> <objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController"> <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides> <layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/> <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects> </objects>
</scene> </scene>
</scenes> </scenes>
</document> </document>
+1 -1
View File
@@ -1 +1 @@
#import "GeneratedPluginRegistrant.h" #import "GeneratedPluginRegistrant.h"
+12 -12
View File
@@ -1,12 +1,12 @@
import Flutter import Flutter
import UIKit import UIKit
import XCTest import XCTest
class RunnerTests: XCTestCase { class RunnerTests: XCTestCase {
func testExample() { func testExample() {
// If you add code to the Runner application, consider adding tests here. // 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. // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
} }
} }
+93 -93
View File
@@ -1,93 +1,93 @@
import 'package:path/path.dart'; import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart'; import 'package:sqflite/sqflite.dart';
import '../models/registered_device.dart'; import '../models/registered_device.dart';
const _tableName = 'siab_devices'; const _tableName = 'siab_devices';
class SiabDatabase { class SiabDatabase {
static Database? _db; static Database? _db;
static Future<Database> get database async { static Future<Database> get database async {
if (_db != null) return _db!; if (_db != null) return _db!;
_db = await _init(); _db = await _init();
return _db!; return _db!;
} }
static Future<Database> _init() async { static Future<Database> _init() async {
final dbPath = await getDatabasesPath(); final dbPath = await getDatabasesPath();
final path = join(dbPath, 'siab_devices.db'); final path = join(dbPath, 'siab_devices.db');
return openDatabase( return openDatabase(
path, path,
version: 2, version: 2,
onCreate: (db, version) async { onCreate: (db, version) async {
await db.execute(''' await db.execute('''
CREATE TABLE $_tableName ( CREATE TABLE $_tableName (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
uuid TEXT NOT NULL UNIQUE, uuid TEXT NOT NULL UNIQUE,
label TEXT NOT NULL label TEXT NOT NULL
) )
'''); ''');
}, },
onUpgrade: (db, oldVersion, newVersion) async { onUpgrade: (db, oldVersion, newVersion) async {
// Simple destructive migration: drop old table and recreate with new schema. // Simple destructive migration: drop old table and recreate with new schema.
if (oldVersion < 2) { if (oldVersion < 2) {
await db.execute('DROP TABLE IF EXISTS $_tableName'); await db.execute('DROP TABLE IF EXISTS $_tableName');
await db.execute(''' await db.execute('''
CREATE TABLE $_tableName ( CREATE TABLE $_tableName (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
uuid TEXT NOT NULL UNIQUE, uuid TEXT NOT NULL UNIQUE,
label TEXT NOT NULL label TEXT NOT NULL
) )
'''); ''');
} }
}, },
); );
} }
Future<int> insert(RegisteredDevice device) async { Future<int> insert(RegisteredDevice device) async {
final db = await database; final db = await database;
return db.insert( return db.insert(
_tableName, _tableName,
device.toMap(), device.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace, conflictAlgorithm: ConflictAlgorithm.replace,
); );
} }
Future<List<RegisteredDevice>> getAll() async { Future<List<RegisteredDevice>> getAll() async {
final db = await database; final db = await database;
final maps = await db.query(_tableName, orderBy: 'label ASC'); final maps = await db.query(_tableName, orderBy: 'label ASC');
return maps.map(RegisteredDevice.fromMap).toList(); return maps.map(RegisteredDevice.fromMap).toList();
} }
Future<RegisteredDevice?> getByUuid(String uuid) async { Future<RegisteredDevice?> getByUuid(String uuid) async {
final db = await database; final db = await database;
final maps = await db.query( final maps = await db.query(
_tableName, _tableName,
where: 'uuid = ?', where: 'uuid = ?',
whereArgs: [uuid], whereArgs: [uuid],
); );
if (maps.isEmpty) return null; if (maps.isEmpty) return null;
return RegisteredDevice.fromMap(maps.first); return RegisteredDevice.fromMap(maps.first);
} }
Future<int> update(RegisteredDevice device) async { Future<int> update(RegisteredDevice device) async {
if (device.id == null) return 0; if (device.id == null) return 0;
final db = await database; final db = await database;
return db.update( return db.update(
_tableName, _tableName,
device.toMap(), device.toMap(),
where: 'id = ?', where: 'id = ?',
whereArgs: [device.id], whereArgs: [device.id],
); );
} }
Future<int> delete(int id) async { Future<int> delete(int id) async {
final db = await database; final db = await database;
return db.delete(_tableName, where: 'id = ?', whereArgs: [id]); return db.delete(_tableName, where: 'id = ?', whereArgs: [id]);
} }
Future<int> deleteByUuid(String uuid) async { Future<int> deleteByUuid(String uuid) async {
final db = await database; final db = await database;
return db.delete(_tableName, where: 'uuid = ?', whereArgs: [uuid]); return db.delete(_tableName, where: 'uuid = ?', whereArgs: [uuid]);
} }
} }
+97 -97
View File
@@ -1,97 +1,97 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'services/ble_service.dart'; import 'services/ble_service.dart';
import 'screens/main_shell.dart'; import 'screens/main_shell.dart';
void main() { void main() {
runApp(const SIABApp()); runApp(const SIABApp());
} }
class SIABApp extends StatelessWidget { class SIABApp extends StatelessWidget {
const SIABApp({super.key}); const SIABApp({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final colorScheme = ColorScheme.fromSeed( final colorScheme = ColorScheme.fromSeed(
seedColor: const Color(0xFF2563EB), seedColor: const Color(0xFF2563EB),
brightness: Brightness.light, brightness: Brightness.light,
); );
return ChangeNotifierProvider( return ChangeNotifierProvider(
create: (_) => BLEService(), create: (_) => BLEService(),
child: MaterialApp( child: MaterialApp(
title: 'SIAB Scale', title: 'SIAB Scale',
theme: ThemeData( theme: ThemeData(
colorScheme: colorScheme, colorScheme: colorScheme,
scaffoldBackgroundColor: const Color(0xFFF4F8FF), scaffoldBackgroundColor: const Color(0xFFF4F8FF),
useMaterial3: true, useMaterial3: true,
appBarTheme: const AppBarTheme( appBarTheme: const AppBarTheme(
centerTitle: false, centerTitle: false,
backgroundColor: Color(0xFFF8FBFF), backgroundColor: Color(0xFFF8FBFF),
foregroundColor: Color(0xFF0F172A), foregroundColor: Color(0xFF0F172A),
elevation: 0, elevation: 0,
surfaceTintColor: Colors.transparent, surfaceTintColor: Colors.transparent,
), ),
cardTheme: CardThemeData( cardTheme: CardThemeData(
color: Colors.white, color: Colors.white,
elevation: 0, elevation: 0,
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18), borderRadius: BorderRadius.circular(18),
), ),
), ),
filledButtonTheme: FilledButtonThemeData( filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom( style: FilledButton.styleFrom(
backgroundColor: const Color(0xFF2563EB), backgroundColor: const Color(0xFF2563EB),
foregroundColor: Colors.white, foregroundColor: Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
), ),
), ),
), ),
elevatedButtonTheme: ElevatedButtonThemeData( elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF2563EB), backgroundColor: const Color(0xFF2563EB),
foregroundColor: Colors.white, foregroundColor: Colors.white,
elevation: 0, elevation: 0,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
), ),
), ),
), ),
outlinedButtonTheme: OutlinedButtonThemeData( outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
foregroundColor: const Color(0xFF2563EB), foregroundColor: const Color(0xFF2563EB),
side: const BorderSide(color: Color(0x663B82F6)), side: const BorderSide(color: Color(0x663B82F6)),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
), ),
), ),
), ),
textButtonTheme: TextButtonThemeData( textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: const Color(0xFF2563EB), foregroundColor: const Color(0xFF2563EB),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14), borderRadius: BorderRadius.circular(14),
), ),
), ),
), ),
snackBarTheme: SnackBarThemeData( snackBarTheme: SnackBarThemeData(
behavior: SnackBarBehavior.floating, behavior: SnackBarBehavior.floating,
backgroundColor: const Color(0xFF0F172A), backgroundColor: const Color(0xFF0F172A),
contentTextStyle: const TextStyle( contentTextStyle: const TextStyle(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
), ),
), ),
), ),
themeMode: ThemeMode.light, themeMode: ThemeMode.light,
home: const MainShell(), home: const MainShell(),
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
), ),
); );
} }
} }
+41 -41
View File
@@ -1,41 +1,41 @@
/// A SIAB device registered in local SQLite with a user-assigned label. /// A SIAB device registered in local SQLite with a user-assigned label.
/// Stores only a user label (\"Label ID\") and the device UUID. /// Stores only a user label (\"Label ID\") and the device UUID.
class RegisteredDevice { class RegisteredDevice {
final int? id; final int? id;
final String uuid; final String uuid;
final String label; final String label;
RegisteredDevice({ RegisteredDevice({
this.id, this.id,
required this.uuid, required this.uuid,
required this.label, required this.label,
}); });
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
if (id != null) 'id': id, if (id != null) 'id': id,
'uuid': uuid, 'uuid': uuid,
'label': label, 'label': label,
}; };
} }
static RegisteredDevice fromMap(Map<String, dynamic> map) { static RegisteredDevice fromMap(Map<String, dynamic> map) {
return RegisteredDevice( return RegisteredDevice(
id: map['id'] as int?, id: map['id'] as int?,
uuid: map['uuid'] as String, uuid: map['uuid'] as String,
label: map['label'] as String, label: map['label'] as String,
); );
} }
RegisteredDevice copyWith({ RegisteredDevice copyWith({
int? id, int? id,
String? uuid, String? uuid,
String? label, String? label,
}) { }) {
return RegisteredDevice( return RegisteredDevice(
id: id ?? this.id, id: id ?? this.id,
uuid: uuid ?? this.uuid, uuid: uuid ?? this.uuid,
label: label ?? this.label, label: label ?? this.label,
); );
} }
} }
+318 -318
View File
@@ -1,318 +1,318 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../database/siab_database.dart'; import '../database/siab_database.dart';
import '../models/registered_device.dart'; import '../models/registered_device.dart';
import '../services/ble_service.dart'; import '../services/ble_service.dart';
import '../siab_config.dart'; import '../siab_config.dart';
class DevicesScreen extends StatefulWidget { class DevicesScreen extends StatefulWidget {
const DevicesScreen({super.key}); const DevicesScreen({super.key});
@override @override
State<DevicesScreen> createState() => _DevicesScreenState(); State<DevicesScreen> createState() => _DevicesScreenState();
} }
class _DevicesScreenState extends State<DevicesScreen> { class _DevicesScreenState extends State<DevicesScreen> {
final _db = SiabDatabase(); final _db = SiabDatabase();
List<RegisteredDevice> _saved = []; List<RegisteredDevice> _saved = [];
List<SiabScanResult> _scanResults = []; List<SiabScanResult> _scanResults = [];
bool _loading = false; bool _loading = false;
Future<void> _loadSaved() async { Future<void> _loadSaved() async {
setState(() => _loading = true); setState(() => _loading = true);
_saved = await _db.getAll(); _saved = await _db.getAll();
setState(() => _loading = false); setState(() => _loading = false);
} }
Future<void> _scan() async { Future<void> _scan() async {
final ble = context.read<BLEService>(); final ble = context.read<BLEService>();
setState(() => _scanResults = []); setState(() => _scanResults = []);
final list = await ble.scanForAllSiabDevices(); final list = await ble.scanForAllSiabDevices();
setState(() => _scanResults = list); setState(() => _scanResults = list);
} }
Future<void> _register( SiabScanResult result, String label) async { Future<void> _register( SiabScanResult result, String label) async {
await _db.insert(RegisteredDevice( await _db.insert(RegisteredDevice(
uuid: result.address, uuid: result.address,
label: label.isEmpty ? result.address : label, label: label.isEmpty ? result.address : label,
)); ));
await _loadSaved(); await _loadSaved();
} }
Future<void> _connectToScanResult(SiabScanResult result) async { Future<void> _connectToScanResult(SiabScanResult result) async {
final ble = context.read<BLEService>(); final ble = context.read<BLEService>();
final ok = await ble.connectToDevice(result.device); final ok = await ble.connectToDevice(result.device);
if (mounted && !ok) { if (mounted && !ok) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Connection failed'), backgroundColor: Colors.red), const SnackBar(content: Text('Connection failed'), backgroundColor: Colors.red),
); );
} else if (mounted && ok) { } else if (mounted && ok) {
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 2));
if (mounted && ble.packetCount == 0) ble.tryStartCommands(); if (mounted && ble.packetCount == 0) ble.tryStartCommands();
await _loadSaved(); await _loadSaved();
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Connected'), backgroundColor: Colors.green), const SnackBar(content: Text('Connected'), backgroundColor: Colors.green),
); );
} }
} }
} }
Future<void> _connectToSaved(RegisteredDevice device) async { Future<void> _connectToSaved(RegisteredDevice device) async {
final ble = context.read<BLEService>(); final ble = context.read<BLEService>();
final ok = await ble.connectToAddress(device.uuid); final ok = await ble.connectToAddress(device.uuid);
if (mounted && !ok) { if (mounted && !ok) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Device not found or connection failed'), backgroundColor: Colors.red), const SnackBar(content: Text('Device not found or connection failed'), backgroundColor: Colors.red),
); );
} else if (mounted && ok) { } else if (mounted && ok) {
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 2));
if (mounted && ble.packetCount == 0) ble.tryStartCommands(); if (mounted && ble.packetCount == 0) ble.tryStartCommands();
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Connected'), backgroundColor: Colors.green), const SnackBar(content: Text('Connected'), backgroundColor: Colors.green),
); );
} }
} }
} }
Future<void> _unregisterDevice(RegisteredDevice device) async { Future<void> _unregisterDevice(RegisteredDevice device) async {
final confirmed = await showDialog<bool>( final confirmed = await showDialog<bool>(
context: context, context: context,
builder: (ctx) => AlertDialog( builder: (ctx) => AlertDialog(
title: const Text('Unregister device'), title: const Text('Unregister device'),
content: Text( content: Text(
'Remove "${device.label}" (${device.uuid}) from registered devices?', 'Remove "${device.label}" (${device.uuid}) from registered devices?',
), ),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.pop(ctx, false), onPressed: () => Navigator.pop(ctx, false),
child: const Text('Cancel'), child: const Text('Cancel'),
), ),
FilledButton( FilledButton(
onPressed: () => Navigator.pop(ctx, true), onPressed: () => Navigator.pop(ctx, true),
child: const Text('Unregister'), child: const Text('Unregister'),
), ),
], ],
), ),
); );
if (confirmed != true) return; if (confirmed != true) return;
if (device.id != null) { if (device.id != null) {
await _db.delete(device.id!); await _db.delete(device.id!);
} else { } else {
await _db.deleteByUuid(device.uuid); await _db.deleteByUuid(device.uuid);
} }
await _loadSaved(); await _loadSaved();
} }
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_loadSaved(); _loadSaved();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('SIAB SCALE'), title: const Text('SIAB SCALE'),
actions: [ actions: [
IconButton( IconButton(
onPressed: _loading ? null : _loadSaved, onPressed: _loading ? null : _loadSaved,
icon: const Icon(Icons.refresh), icon: const Icon(Icons.refresh),
), ),
], ],
), ),
body: Consumer<BLEService>( body: Consumer<BLEService>(
builder: (context, ble, _) { builder: (context, ble, _) {
return ListView( return ListView(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
children: [ children: [
// Scan section at top // Scan section at top
const Text('Daftar Timbangan (scan)', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), const Text('Daftar Timbangan (scan)', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
const SizedBox(height: 8), const SizedBox(height: 8),
OutlinedButton.icon( OutlinedButton.icon(
onPressed: ble.isScanning ? null : () async { await _scan(); }, onPressed: ble.isScanning ? null : () async { await _scan(); },
icon: ble.isScanning icon: ble.isScanning
? const SizedBox( ? const SizedBox(
width: 18, width: 18,
height: 18, height: 18,
child: CircularProgressIndicator(strokeWidth: 2), child: CircularProgressIndicator(strokeWidth: 2),
) )
: const Icon(Icons.bluetooth_searching, size: 20), : const Icon(Icons.bluetooth_searching, size: 20),
label: Text(ble.isScanning ? 'Scanning...' : 'Scan Timbangan'), label: Text(ble.isScanning ? 'Scanning...' : 'Scan Timbangan'),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
if (_scanResults.isEmpty && !ble.isScanning) if (_scanResults.isEmpty && !ble.isScanning)
const Card(child: Padding( const Card(child: Padding(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),
child: Text('Tap "Scan Timbangan" lihat melihat timbangan di sekitar.'), child: Text('Tap "Scan Timbangan" lihat melihat timbangan di sekitar.'),
)) ))
else else
..._scanResults.map((r) { ..._scanResults.map((r) {
RegisteredDevice? registered; RegisteredDevice? registered;
for (final d in _saved) { for (final d in _saved) {
if (d.uuid == r.address) { registered = d; break; } if (d.uuid == r.address) { registered = d; break; }
} }
final labelId = registered?.label; final labelId = registered?.label;
final hasLabel = labelId != null && labelId.isNotEmpty; final hasLabel = labelId != null && labelId.isNotEmpty;
return Card( return Card(
margin: const EdgeInsets.only(bottom: 8), margin: const EdgeInsets.only(bottom: 8),
child: Padding( child: Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_ListRow(label: 'NAMA', value: labelId ?? '—'), _ListRow(label: 'NAMA', value: labelId ?? '—'),
_ListRow(label: 'ID', value: r.device.remoteId.toString()), _ListRow(label: 'ID', value: r.device.remoteId.toString()),
const SizedBox(height: 8), const SizedBox(height: 8),
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
if (!hasLabel) if (!hasLabel)
Padding( Padding(
padding: const EdgeInsets.only(right: 8), padding: const EdgeInsets.only(right: 8),
child: TextButton.icon( child: TextButton.icon(
onPressed: () => _showRegisterDialog(r), onPressed: () => _showRegisterDialog(r),
icon: const Icon(Icons.app_registration, size: 18), icon: const Icon(Icons.app_registration, size: 18),
label: const Text('Register'), label: const Text('Register'),
), ),
), ),
TextButton.icon( TextButton.icon(
onPressed: ble.isConnecting ? null : () => _connectToScanResult(r), onPressed: ble.isConnecting ? null : () => _connectToScanResult(r),
icon: const Icon(Icons.link, size: 18), icon: const Icon(Icons.link, size: 18),
label: const Text('Connect'), label: const Text('Connect'),
), ),
], ],
), ),
], ],
), ),
), ),
); );
}), }),
const SizedBox(height: 24), const SizedBox(height: 24),
// Registered devices below scan // Registered devices below scan
const Text('Registered devices (saved)', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), const Text('Registered devices (saved)', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
const SizedBox(height: 8), const SizedBox(height: 8),
if (_loading) if (_loading)
const Center(child: CircularProgressIndicator()) const Center(child: CircularProgressIndicator())
else if (_saved.isEmpty) else if (_saved.isEmpty)
const Card(child: Padding( const Card(child: Padding(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),
child: Text('No registered devices. Scan and register above.'), child: Text('No registered devices. Scan and register above.'),
)) ))
else else
..._saved.map((d) => Card( ..._saved.map((d) => Card(
margin: const EdgeInsets.only(bottom: 8), margin: const EdgeInsets.only(bottom: 8),
child: Padding( child: Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_ListRow(label: 'NAMA', value: d.label), _ListRow(label: 'NAMA', value: d.label),
_ListRow(label: 'ID', value: d.uuid), _ListRow(label: 'ID', value: d.uuid),
const SizedBox(height: 8), const SizedBox(height: 8),
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
TextButton.icon( TextButton.icon(
onPressed: () => _unregisterDevice(d), onPressed: () => _unregisterDevice(d),
icon: const Icon(Icons.delete_outline, size: 18), icon: const Icon(Icons.delete_outline, size: 18),
label: const Text('Unregister'), label: const Text('Unregister'),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
if (ble.isConnected && ble.deviceAddress == d.uuid) if (ble.isConnected && ble.deviceAddress == d.uuid)
const Icon(Icons.bluetooth_connected, color: Colors.green, size: 28) const Icon(Icons.bluetooth_connected, color: Colors.green, size: 28)
else else
TextButton.icon( TextButton.icon(
onPressed: ble.isConnecting ? null : () => _connectToSaved(d), onPressed: ble.isConnecting ? null : () => _connectToSaved(d),
icon: const Icon(Icons.link, size: 18), icon: const Icon(Icons.link, size: 18),
label: const Text('Connect'), label: const Text('Connect'),
), ),
], ],
), ),
], ],
), ),
), ),
)), )),
], ],
); );
}, },
), ),
); );
} }
void _showRegisterDialog(SiabScanResult result) { void _showRegisterDialog(SiabScanResult result) {
final controller = TextEditingController( final controller = TextEditingController(
text: result.name.isNotEmpty ? result.name : SiabConfig.deviceName, text: result.name.isNotEmpty ? result.name : SiabConfig.deviceName,
); );
showDialog<void>( showDialog<void>(
context: context, context: context,
builder: (ctx) => AlertDialog( builder: (ctx) => AlertDialog(
title: const Text('Register device'), title: const Text('Register device'),
content: TextField( content: TextField(
controller: controller, controller: controller,
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Nama', labelText: 'Nama',
hintText: 'contoh : Scale 1, TIMBANGAN 1', hintText: 'contoh : Scale 1, TIMBANGAN 1',
), ),
autofocus: true, autofocus: true,
), ),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.pop(ctx), onPressed: () => Navigator.pop(ctx),
child: const Text('Cancel'), child: const Text('Cancel'),
), ),
FilledButton( FilledButton(
onPressed: () async { onPressed: () async {
final label = controller.text.trim(); final label = controller.text.trim();
await _register(result, label.isEmpty ? result.address : label); await _register(result, label.isEmpty ? result.address : label);
if (mounted) Navigator.pop(ctx); if (ctx.mounted) Navigator.pop(ctx);
}, },
child: const Text('Save'), child: const Text('Save'),
), ),
], ],
), ),
); );
} }
} }
class _ListRow extends StatelessWidget { class _ListRow extends StatelessWidget {
final String label; final String label;
final String value; final String value;
const _ListRow({required this.label, required this.value}); const _ListRow({required this.label, required this.value});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 2), padding: const EdgeInsets.symmetric(vertical: 2),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox( SizedBox(
width: 110, width: 110,
child: Text( child: Text(
'$label:', '$label:',
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.8), color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.8),
fontSize: 13, fontSize: 13,
), ),
), ),
), ),
Expanded( Expanded(
child: SelectableText( child: SelectableText(
value, value,
style: const TextStyle(fontSize: 13), style: const TextStyle(fontSize: 13),
), ),
), ),
], ],
), ),
); );
} }
} }
+144 -143
View File
@@ -1,143 +1,144 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../services/ble_service.dart'; import '../services/ble_service.dart';
import '../widgets/data_packet_card.dart'; import '../widgets/data_packet_card.dart';
import '../widgets/statistics_card.dart'; import '../widgets/statistics_card.dart';
import '../widgets/connection_card.dart'; import '../widgets/connection_card.dart';
class HomeScreen extends StatefulWidget { class HomeScreen extends StatefulWidget {
const HomeScreen({super.key}); const HomeScreen({super.key});
@override @override
State<HomeScreen> createState() => _HomeScreenState(); State<HomeScreen> createState() => _HomeScreenState();
} }
class _HomeScreenState extends State<HomeScreen> { class _HomeScreenState extends State<HomeScreen> {
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
@override @override
void dispose() { void dispose() {
_scrollController.dispose(); _scrollController.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('SIAB Scale'), title: const Text('SIAB Scale'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary, backgroundColor: Theme.of(context).colorScheme.inversePrimary,
actions: [ actions: [
Consumer<BLEService>( Consumer<BLEService>(
builder: (context, ble, _) { builder: (context, ble, _) {
if (ble.isConnected) { if (ble.isConnected) {
return IconButton( return IconButton(
icon: const Icon(Icons.delete_outline), icon: const Icon(Icons.delete_outline),
tooltip: 'Clear Data', tooltip: 'Clear Data',
onPressed: () { onPressed: () {
ble.clearData(); ble.clearData();
}, },
); );
} }
return const SizedBox.shrink(); return const SizedBox.shrink();
}, },
), ),
], ],
), ),
body: Consumer<BLEService>( body: Consumer<BLEService>(
builder: (context, ble, _) { builder: (context, ble, _) {
return Column( return Column(
children: [ children: [
// Connection Card // Connection Card
ConnectionCard(ble: ble), ConnectionCard(ble: ble),
// Statistics Card // Statistics Card
if (ble.isConnected) StatisticsCard(ble: ble), if (ble.isConnected) StatisticsCard(ble: ble),
// Data Packets List // Data Packets List
Expanded( Expanded(
child: ble.isConnected && ble.dataPackets.isNotEmpty child: ble.isConnected && ble.dataPackets.isNotEmpty
? ListView.builder( ? ListView.builder(
controller: _scrollController, controller: _scrollController,
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
itemCount: ble.dataPackets.length, itemCount: ble.dataPackets.length,
reverse: true, // Show newest first reverse: true, // Show newest first
itemBuilder: (context, index) { itemBuilder: (context, index) {
final packet = ble.dataPackets[ble.dataPackets.length - 1 - index]; final packet = ble.dataPackets[ble.dataPackets.length - 1 - index];
return DataPacketCard(packet: packet); return DataPacketCard(packet: packet);
}, },
) )
: Center( : Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( Icon(
ble.isConnected ble.isConnected
? Icons.bluetooth_connected ? Icons.bluetooth_connected
: Icons.bluetooth_disabled, : Icons.bluetooth_disabled,
size: 64, size: 64,
color: Colors.grey, color: Colors.grey,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
ble.isConnected ble.isConnected
? 'Waiting for data...' ? 'Waiting for data...'
: 'Not connected', : 'Not connected',
style: Theme.of(context).textTheme.titleLarge?.copyWith( style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Colors.grey, color: Colors.grey,
), ),
), ),
if (ble.isConnected) ...[ if (ble.isConnected) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
const Text( const Text(
'Data packets will appear here', 'Data packets will appear here',
style: TextStyle(color: Colors.grey), style: TextStyle(color: Colors.grey),
), ),
], ],
], ],
), ),
), ),
), ),
], ],
); );
}, },
), ),
floatingActionButton: Consumer<BLEService>( floatingActionButton: Consumer<BLEService>(
builder: (context, ble, _) { builder: (_, ble, __) {
if (ble.isConnecting || ble.isScanning) { if (ble.isConnecting || ble.isScanning) {
return const FloatingActionButton( return const FloatingActionButton(
onPressed: null, onPressed: null,
child: CircularProgressIndicator(color: Colors.white), child: CircularProgressIndicator(color: Colors.white),
); );
} }
if (ble.isConnected) { if (ble.isConnected) {
return FloatingActionButton( return FloatingActionButton(
onPressed: () async { onPressed: () async {
await ble.disconnect(); await ble.disconnect();
ble.clearData(); ble.clearData();
}, },
backgroundColor: Colors.red, backgroundColor: Colors.red,
child: const Icon(Icons.bluetooth_disabled), child: const Icon(Icons.bluetooth_disabled),
); );
} }
return FloatingActionButton( return FloatingActionButton(
onPressed: () async { onPressed: () async {
final success = await ble.autoConnect(); final scaffoldMessenger = ScaffoldMessenger.of(context);
if (!success && mounted) { final success = await ble.autoConnect();
ScaffoldMessenger.of(context).showSnackBar( if (!success && mounted) {
const SnackBar( scaffoldMessenger.showSnackBar(
content: Text('Koneksi ke timbangan gagal'), const SnackBar(
backgroundColor: Colors.red, content: Text('Koneksi ke timbangan gagal'),
), backgroundColor: Colors.red,
); ),
} );
}, }
child: const Icon(Icons.bluetooth_searching), },
); child: const Icon(Icons.bluetooth_searching),
}, );
), },
); ),
} );
} }
}
+206 -206
View File
@@ -1,206 +1,206 @@
import 'dart:ui' show ImageFilter; import 'dart:ui' show ImageFilter;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'devices_screen.dart'; import 'devices_screen.dart';
import 'timbang_screen.dart'; import 'timbang_screen.dart';
/// Root scaffold with bottom nav: Devices and Timbang (scale display). /// Root scaffold with bottom nav: Devices and Timbang (scale display).
class MainShell extends StatefulWidget { class MainShell extends StatefulWidget {
const MainShell({super.key}); const MainShell({super.key});
@override @override
State<MainShell> createState() => _MainShellState(); State<MainShell> createState() => _MainShellState();
} }
class _MainShellState extends State<MainShell> { class _MainShellState extends State<MainShell> {
int _index = 0; int _index = 0;
static const _tabs = [ static const _tabs = [
(label: 'Devices', icon: Icons.list_alt), (label: 'Devices', icon: Icons.list_alt),
(label: 'Timbang', icon: Icons.monitor_weight), (label: 'Timbang', icon: Icons.monitor_weight),
]; ];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
extendBody: true, extendBody: true,
body: IndexedStack( body: IndexedStack(
index: _index, index: _index,
children: const [ children: const [
DevicesScreen(), DevicesScreen(),
TimbangScreen(), TimbangScreen(),
], ],
), ),
bottomNavigationBar: _FloatingGlassNavigationBar( bottomNavigationBar: _FloatingGlassNavigationBar(
currentIndex: _index, currentIndex: _index,
tabs: _tabs, tabs: _tabs,
onTap: (i) => setState(() => _index = i), onTap: (i) => setState(() => _index = i),
), ),
); );
} }
} }
class _FloatingGlassNavigationBar extends StatelessWidget { class _FloatingGlassNavigationBar extends StatelessWidget {
const _FloatingGlassNavigationBar({ const _FloatingGlassNavigationBar({
required this.currentIndex, required this.currentIndex,
required this.tabs, required this.tabs,
required this.onTap, required this.onTap,
}); });
final int currentIndex; final int currentIndex;
final List<({String label, IconData icon})> tabs; final List<({String label, IconData icon})> tabs;
final ValueChanged<int> onTap; final ValueChanged<int> onTap;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SafeArea( return SafeArea(
minimum: const EdgeInsets.fromLTRB(20, 0, 20, 18), minimum: const EdgeInsets.fromLTRB(20, 0, 20, 18),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(32), borderRadius: BorderRadius.circular(32),
child: BackdropFilter( child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 24, sigmaY: 24), filter: ImageFilter.blur(sigmaX: 24, sigmaY: 24),
child: Container( child: Container(
height: 72, height: 72,
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
Colors.white.withValues(alpha: 0.84), Colors.white.withValues(alpha: 0.84),
Colors.white.withValues(alpha: 0.62), Colors.white.withValues(alpha: 0.62),
], ],
), ),
borderRadius: BorderRadius.circular(32), borderRadius: BorderRadius.circular(32),
border: Border.all(color: Colors.white.withValues(alpha: 0.9)), border: Border.all(color: Colors.white.withValues(alpha: 0.9)),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: const Color(0xFF0F172A).withValues(alpha: 0.13), color: const Color(0xFF0F172A).withValues(alpha: 0.13),
blurRadius: 34, blurRadius: 34,
offset: const Offset(0, 18), offset: const Offset(0, 18),
), ),
BoxShadow( BoxShadow(
color: const Color(0xFF38BDF8).withValues(alpha: 0.1), color: const Color(0xFF38BDF8).withValues(alpha: 0.1),
blurRadius: 24, blurRadius: 24,
offset: const Offset(0, -6), offset: const Offset(0, -6),
), ),
], ],
), ),
child: Row( child: Row(
children: [ children: [
for (var i = 0; i < tabs.length; i++) for (var i = 0; i < tabs.length; i++)
Expanded( Expanded(
child: _GlassNavigationItem( child: _GlassNavigationItem(
icon: tabs[i].icon, icon: tabs[i].icon,
label: tabs[i].label, label: tabs[i].label,
isSelected: i == currentIndex, isSelected: i == currentIndex,
onTap: () => onTap(i), onTap: () => onTap(i),
), ),
), ),
], ],
), ),
), ),
), ),
), ),
); );
} }
} }
class _GlassNavigationItem extends StatelessWidget { class _GlassNavigationItem extends StatelessWidget {
const _GlassNavigationItem({ const _GlassNavigationItem({
required this.icon, required this.icon,
required this.label, required this.label,
required this.isSelected, required this.isSelected,
required this.onTap, required this.onTap,
}); });
final IconData icon; final IconData icon;
final String label; final String label;
final bool isSelected; final bool isSelected;
final VoidCallback onTap; final VoidCallback onTap;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const activeColor = Color(0xFF2563EB); const activeColor = Color(0xFF2563EB);
const inactiveColor = Color(0xFF64748B); const inactiveColor = Color(0xFF64748B);
return Material( return Material(
color: Colors.transparent, color: Colors.transparent,
child: InkWell( child: InkWell(
onTap: onTap, onTap: onTap,
borderRadius: BorderRadius.circular(26), borderRadius: BorderRadius.circular(26),
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 220), duration: const Duration(milliseconds: 220),
curve: Curves.easeOutCubic, curve: Curves.easeOutCubic,
alignment: Alignment.center, alignment: Alignment.center,
margin: const EdgeInsets.symmetric(horizontal: 2), margin: const EdgeInsets.symmetric(horizontal: 2),
padding: const EdgeInsets.symmetric(horizontal: 10), padding: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: isSelected gradient: isSelected
? LinearGradient( ? LinearGradient(
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
Colors.white.withValues(alpha: 0.95), Colors.white.withValues(alpha: 0.95),
activeColor.withValues(alpha: 0.12), activeColor.withValues(alpha: 0.12),
], ],
) )
: null, : null,
color: isSelected ? null : Colors.transparent, color: isSelected ? null : Colors.transparent,
borderRadius: BorderRadius.circular(26), borderRadius: BorderRadius.circular(26),
border: Border.all( border: Border.all(
color: isSelected color: isSelected
? Colors.white.withValues(alpha: 0.96) ? Colors.white.withValues(alpha: 0.96)
: Colors.transparent, : Colors.transparent,
), ),
boxShadow: isSelected boxShadow: isSelected
? [ ? [
BoxShadow( BoxShadow(
color: activeColor.withValues(alpha: 0.16), color: activeColor.withValues(alpha: 0.16),
blurRadius: 18, blurRadius: 18,
offset: const Offset(0, 8), offset: const Offset(0, 8),
), ),
] ]
: null, : null,
), ),
child: AnimatedScale( child: AnimatedScale(
duration: const Duration(milliseconds: 180), duration: const Duration(milliseconds: 180),
curve: Curves.easeOutCubic, curve: Curves.easeOutCubic,
scale: isSelected ? 1 : 0.96, scale: isSelected ? 1 : 0.96,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon( Icon(
icon, icon,
color: isSelected ? activeColor : inactiveColor, color: isSelected ? activeColor : inactiveColor,
size: 22, size: 22,
), ),
AnimatedSize( AnimatedSize(
duration: const Duration(milliseconds: 220), duration: const Duration(milliseconds: 220),
curve: Curves.easeOutCubic, curve: Curves.easeOutCubic,
child: isSelected child: isSelected
? Row( ? Row(
children: [ children: [
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
label, label,
style: const TextStyle( style: const TextStyle(
color: Color(0xFF2563EB), color: Color(0xFF2563EB),
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
), ),
), ),
], ],
) )
: const SizedBox.shrink(), : const SizedBox.shrink(),
), ),
], ],
), ),
), ),
), ),
), ),
); );
} }
} }
File diff suppressed because it is too large. Load diff
+14 -14
View File
@@ -1,14 +1,14 @@
/// Central configuration for SIAB-related constants. /// Central configuration for SIAB-related constants.
/// ///
/// The [deviceName] can be overridden at build time using: /// The [deviceName] can be overridden at build time using:
/// `--dart-define=SIAB_DEVICE_NAME=YourDeviceName`. /// `--dart-define=SIAB_DEVICE_NAME=YourDeviceName`.
class SiabConfig { class SiabConfig {
const SiabConfig._(); const SiabConfig._();
/// Logical Bluetooth name to search for when scanning SIAB devices. /// Logical Bluetooth name to search for when scanning SIAB devices.
static const String deviceName = String.fromEnvironment( static const String deviceName = String.fromEnvironment(
'SIAB_DEVICE_NAME', 'SIAB_DEVICE_NAME',
defaultValue: 'SIAB', defaultValue: 'SIAB',
); );
} }
+79 -79
View File
@@ -1,79 +1,79 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../services/ble_service.dart'; import '../services/ble_service.dart';
import '../siab_config.dart'; import '../siab_config.dart';
class ConnectionCard extends StatelessWidget { class ConnectionCard extends StatelessWidget {
final BLEService ble; final BLEService ble;
const ConnectionCard({super.key, required this.ble}); const ConnectionCard({super.key, required this.ble});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Card( return Card(
margin: const EdgeInsets.all(8), margin: const EdgeInsets.all(8),
child: Padding( child: Padding(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
children: [ children: [
Icon( Icon(
ble.isConnected ble.isConnected
? Icons.bluetooth_connected ? Icons.bluetooth_connected
: Icons.bluetooth_disabled, : Icons.bluetooth_disabled,
color: ble.isConnected ? Colors.green : Colors.grey, color: ble.isConnected ? Colors.green : Colors.grey,
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
ble.isConnected ? 'Connected' : 'Disconnected', ble.isConnected ? 'Connected' : 'Disconnected',
style: Theme.of(context).textTheme.titleLarge, style: Theme.of(context).textTheme.titleLarge,
), ),
const Spacer(), const Spacer(),
if (ble.isScanning || ble.isConnecting) if (ble.isScanning || ble.isConnecting)
const SizedBox( const SizedBox(
width: 20, width: 20,
height: 20, height: 20,
child: CircularProgressIndicator(strokeWidth: 2), child: CircularProgressIndicator(strokeWidth: 2),
), ),
], ],
), ),
if (ble.isConnected) ...[ if (ble.isConnected) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
if (ble.deviceName != null) if (ble.deviceName != null)
Text('Device: ${ble.deviceName}'), Text('Device: ${ble.deviceName}'),
if (ble.deviceAddress != null) if (ble.deviceAddress != null)
Text( Text(
'Address: ${ble.deviceAddress}', 'Address: ${ble.deviceAddress}',
style: Theme.of(context).textTheme.bodySmall, style: Theme.of(context).textTheme.bodySmall,
), ),
], ],
if (!ble.isConnected && !ble.isScanning && !ble.isConnecting) ...[ if (!ble.isConnected && !ble.isScanning && !ble.isConnecting) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
child: ElevatedButton.icon( child: ElevatedButton.icon(
onPressed: () async { onPressed: () async {
final success = await ble.autoConnect(); final success = await ble.autoConnect();
if (!success && context.mounted) { if (!success && context.mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( const SnackBar(
content: Text( content: Text(
'Failed to find ${SiabConfig.deviceName} device', 'Failed to find ${SiabConfig.deviceName} device',
), ),
backgroundColor: Colors.orange, backgroundColor: Colors.orange,
), ),
); );
} }
}, },
icon: const Icon(Icons.search), icon: const Icon(Icons.search),
label: const Text('Scan & Connect'), label: const Text('Scan & Connect'),
), ),
), ),
], ],
], ],
), ),
), ),
); );
} }
} }
+126 -126
View File
@@ -1,126 +1,126 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../services/ble_service.dart'; import '../services/ble_service.dart';
class DataPacketCard extends StatelessWidget { class DataPacketCard extends StatelessWidget {
final DataPacket packet; final DataPacket packet;
const DataPacketCard({super.key, required this.packet}); const DataPacketCard({super.key, required this.packet});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final timeStr = '${packet.timestamp.hour.toString().padLeft(2, '0')}:' final timeStr = '${packet.timestamp.hour.toString().padLeft(2, '0')}:'
'${packet.timestamp.minute.toString().padLeft(2, '0')}:' '${packet.timestamp.minute.toString().padLeft(2, '0')}:'
'${packet.timestamp.second.toString().padLeft(2, '0')}'; '${packet.timestamp.second.toString().padLeft(2, '0')}';
return Card( return Card(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: ExpansionTile( child: ExpansionTile(
leading: CircleAvatar( leading: CircleAvatar(
backgroundColor: Theme.of(context).primaryColor, backgroundColor: Theme.of(context).primaryColor,
child: Text( child: Text(
'#${packet.packetNumber}', '#${packet.packetNumber}',
style: const TextStyle(color: Colors.white, fontSize: 12), style: const TextStyle(color: Colors.white, fontSize: 12),
), ),
), ),
title: Text( title: Text(
packet.hexString, packet.hexString,
style: const TextStyle(fontFamily: 'monospace', fontSize: 14), style: const TextStyle(fontFamily: 'monospace', fontSize: 14),
), ),
subtitle: Text('$timeStr • ${packet.data.length} bytes'), subtitle: Text('$timeStr • ${packet.data.length} bytes'),
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildSection('Hex', packet.hexString), _buildSection('Hex', packet.hexString),
const SizedBox(height: 8), const SizedBox(height: 8),
// 'timbang' style: bytes shown in decimal (matching Python output) // 'timbang' style: bytes shown in decimal (matching Python output)
_buildSection('timbang', packet.bytesString), _buildSection('timbang', packet.bytesString),
const SizedBox(height: 16), const SizedBox(height: 16),
if (packet.value32BitUnsigned != null) ...[ if (packet.value32BitUnsigned != null) ...[
_buildValueRow( _buildValueRow(
'32-bit Unsigned (BE)', '32-bit Unsigned (BE)',
packet.value32BitUnsigned.toString(), packet.value32BitUnsigned.toString(),
), ),
_buildValueRow( _buildValueRow(
'32-bit Signed (BE)', '32-bit Signed (BE)',
packet.value32BitSigned.toString(), packet.value32BitSigned.toString(),
), ),
if (packet.value32BitUnsigned! > 0) ...[ if (packet.value32BitUnsigned! > 0) ...[
_buildValueRow( _buildValueRow(
'As Float (÷100)', 'As Float (÷100)',
(packet.value32BitUnsigned! / 100.0).toStringAsFixed(2), (packet.value32BitUnsigned! / 100.0).toStringAsFixed(2),
), ),
_buildValueRow( _buildValueRow(
'As Float (÷1000)', 'As Float (÷1000)',
(packet.value32BitUnsigned! / 1000.0).toStringAsFixed(3), (packet.value32BitUnsigned! / 1000.0).toStringAsFixed(3),
), ),
], ],
], ],
if (packet.value16BitUnsigned != null) ...[ if (packet.value16BitUnsigned != null) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
_buildValueRow( _buildValueRow(
'16-bit Unsigned (BE)', '16-bit Unsigned (BE)',
packet.value16BitUnsigned.toString(), packet.value16BitUnsigned.toString(),
), ),
_buildValueRow( _buildValueRow(
'16-bit Signed (BE)', '16-bit Signed (BE)',
packet.value16BitSigned.toString(), packet.value16BitSigned.toString(),
), ),
], ],
if (packet.asciiString != null) ...[ if (packet.asciiString != null) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
_buildSection('ASCII', packet.asciiString!), _buildSection('ASCII', packet.asciiString!),
], ],
], ],
), ),
), ),
], ],
), ),
); );
} }
Widget _buildSection(String label, String value) { Widget _buildSection(String label, String value) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
label, label,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 12, fontSize: 12,
color: Colors.grey, color: Colors.grey,
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
SelectableText( SelectableText(
value, value,
style: const TextStyle(fontFamily: 'monospace', fontSize: 14), style: const TextStyle(fontFamily: 'monospace', fontSize: 14),
), ),
], ],
); );
} }
Widget _buildValueRow(String label, String value) { Widget _buildValueRow(String label, String value) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 2), padding: const EdgeInsets.symmetric(vertical: 2),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
label, label,
style: const TextStyle(fontSize: 12, color: Colors.grey), style: const TextStyle(fontSize: 12, color: Colors.grey),
), ),
Text( Text(
value, value,
style: const TextStyle( style: const TextStyle(
fontFamily: 'monospace', fontFamily: 'monospace',
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
], ],
), ),
); );
} }
} }
+76 -76
View File
@@ -1,76 +1,76 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../services/ble_service.dart'; import '../services/ble_service.dart';
class StatisticsCard extends StatelessWidget { class StatisticsCard extends StatelessWidget {
final BLEService ble; final BLEService ble;
const StatisticsCard({super.key, required this.ble}); const StatisticsCard({super.key, required this.ble});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final duration = ble.streamingDuration; final duration = ble.streamingDuration;
final durationStr = duration != null final durationStr = duration != null
? '${duration.inMinutes}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}' ? '${duration.inMinutes}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}'
: '0:00'; : '0:00';
return Card( return Card(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: Padding( child: Padding(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
_StatItem( _StatItem(
icon: Icons.data_usage, icon: Icons.data_usage,
label: 'Packets', label: 'Packets',
value: '${ble.packetCount}', value: '${ble.packetCount}',
), ),
_StatItem( _StatItem(
icon: Icons.speed, icon: Icons.speed,
label: 'Rate', label: 'Rate',
value: '${ble.packetsPerSecond.toStringAsFixed(2)}/s', value: '${ble.packetsPerSecond.toStringAsFixed(2)}/s',
), ),
_StatItem( _StatItem(
icon: Icons.timer, icon: Icons.timer,
label: 'Duration', label: 'Duration',
value: durationStr, value: durationStr,
), ),
], ],
), ),
), ),
); );
} }
} }
class _StatItem extends StatelessWidget { class _StatItem extends StatelessWidget {
final IconData icon; final IconData icon;
final String label; final String label;
final String value; final String value;
const _StatItem({ const _StatItem({
required this.icon, required this.icon,
required this.label, required this.label,
required this.value, required this.value,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon(icon, size: 24, color: Theme.of(context).primaryColor), Icon(icon, size: 24, color: Theme.of(context).primaryColor),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
value, value,
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text( Text(
label, label,
style: Theme.of(context).textTheme.bodySmall, style: Theme.of(context).textTheme.bodySmall,
), ),
], ],
); );
} }
} }
+1 -1
View File
@@ -1 +1 @@
flutter/ephemeral flutter/ephemeral
+88 -88
View File
@@ -1,88 +1,88 @@
# This file controls Flutter-level build steps. It should not be edited. # This file controls Flutter-level build steps. It should not be edited.
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool. # Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake) include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See # TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146. # https://github.com/flutter/flutter/issues/57146.
# Serves the same purpose as list(TRANSFORM ... PREPEND ...), # Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10. # which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX) function(list_prepend LIST_NAME PREFIX)
set(NEW_LIST "") set(NEW_LIST "")
foreach(element ${${LIST_NAME}}) foreach(element ${${LIST_NAME}})
list(APPEND NEW_LIST "${PREFIX}${element}") list(APPEND NEW_LIST "${PREFIX}${element}")
endforeach(element) endforeach(element)
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction() endfunction()
# === Flutter Library === # === Flutter Library ===
# System-level dependencies. # System-level dependencies.
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
# Published to parent scope for install step. # Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS list(APPEND FLUTTER_LIBRARY_HEADERS
"fl_basic_message_channel.h" "fl_basic_message_channel.h"
"fl_binary_codec.h" "fl_binary_codec.h"
"fl_binary_messenger.h" "fl_binary_messenger.h"
"fl_dart_project.h" "fl_dart_project.h"
"fl_engine.h" "fl_engine.h"
"fl_json_message_codec.h" "fl_json_message_codec.h"
"fl_json_method_codec.h" "fl_json_method_codec.h"
"fl_message_codec.h" "fl_message_codec.h"
"fl_method_call.h" "fl_method_call.h"
"fl_method_channel.h" "fl_method_channel.h"
"fl_method_codec.h" "fl_method_codec.h"
"fl_method_response.h" "fl_method_response.h"
"fl_plugin_registrar.h" "fl_plugin_registrar.h"
"fl_plugin_registry.h" "fl_plugin_registry.h"
"fl_standard_message_codec.h" "fl_standard_message_codec.h"
"fl_standard_method_codec.h" "fl_standard_method_codec.h"
"fl_string_codec.h" "fl_string_codec.h"
"fl_value.h" "fl_value.h"
"fl_view.h" "fl_view.h"
"flutter_linux.h" "flutter_linux.h"
) )
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE) add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}" "${EPHEMERAL_DIR}"
) )
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE target_link_libraries(flutter INTERFACE
PkgConfig::GTK PkgConfig::GTK
PkgConfig::GLIB PkgConfig::GLIB
PkgConfig::GIO PkgConfig::GIO
) )
add_dependencies(flutter flutter_assemble) add_dependencies(flutter flutter_assemble)
# === Flutter tool backend === # === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time, # _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the # since currently there's no way to get a full input/output list from the
# flutter tool. # flutter tool.
add_custom_command( add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/_phony_ ${CMAKE_CURRENT_BINARY_DIR}/_phony_
COMMAND ${CMAKE_COMMAND} -E env COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT} ${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
VERBATIM VERBATIM
) )
add_custom_target(flutter_assemble DEPENDS add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}" "${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS} ${FLUTTER_LIBRARY_HEADERS}
) )
+26 -26
View File
@@ -1,26 +1,26 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(runner LANGUAGES CXX) project(runner LANGUAGES CXX)
# Define the application target. To change its name, change BINARY_NAME in the # Define the application target. To change its name, change BINARY_NAME in the
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
# work. # work.
# #
# Any new source files that you add to the application should be added here. # Any new source files that you add to the application should be added here.
add_executable(${BINARY_NAME} add_executable(${BINARY_NAME}
"main.cc" "main.cc"
"my_application.cc" "my_application.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
) )
# Apply the standard set of build settings. This can be removed for applications # Apply the standard set of build settings. This can be removed for applications
# that need different build settings. # that need different build settings.
apply_standard_settings(${BINARY_NAME}) apply_standard_settings(${BINARY_NAME})
# Add preprocessor definitions for the application ID. # Add preprocessor definitions for the application ID.
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
# Add dependency libraries. Add any application-specific dependencies here. # Add dependency libraries. Add any application-specific dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter) target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
+6 -6
View File
@@ -1,6 +1,6 @@
#include "my_application.h" #include "my_application.h"
int main(int argc, char** argv) { int main(int argc, char** argv) {
g_autoptr(MyApplication) app = my_application_new(); g_autoptr(MyApplication) app = my_application_new();
return g_application_run(G_APPLICATION(app), argc, argv); return g_application_run(G_APPLICATION(app), argc, argv);
} }
+18 -18
View File
@@ -1,18 +1,18 @@
#ifndef FLUTTER_MY_APPLICATION_H_ #ifndef FLUTTER_MY_APPLICATION_H_
#define FLUTTER_MY_APPLICATION_H_ #define FLUTTER_MY_APPLICATION_H_
#include <gtk/gtk.h> #include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
GtkApplication) GtkApplication)
/** /**
* my_application_new: * my_application_new:
* *
* Creates a new Flutter-based application. * Creates a new Flutter-based application.
* *
* Returns: a new #MyApplication. * Returns: a new #MyApplication.
*/ */
MyApplication* my_application_new(); MyApplication* my_application_new();
#endif // FLUTTER_MY_APPLICATION_H_ #endif // FLUTTER_MY_APPLICATION_H_
+7 -7
View File
@@ -1,7 +1,7 @@
# Flutter-related # Flutter-related
**/Flutter/ephemeral/ **/Flutter/ephemeral/
**/Pods/ **/Pods/
# Xcode-related # Xcode-related
**/dgph **/dgph
**/xcuserdata/ **/xcuserdata/
+1 -1
View File
@@ -1 +1 @@
#include "ephemeral/Flutter-Generated.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig"
+1 -1
View File
@@ -1 +1 @@
#include "ephemeral/Flutter-Generated.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig"
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>IDEDidComputeMac32BitWarning</key> <key>IDEDidComputeMac32BitWarning</key>
<true/> <true/>
</dict> </dict>
</plist> </plist>
@@ -1,99 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1510" LastUpgradeVersion = "1510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"> buildImplicitDependencies = "YES">
<BuildActionEntries> <BuildActionEntries>
<BuildActionEntry <BuildActionEntry
buildForTesting = "YES" buildForTesting = "YES"
buildForRunning = "YES" buildForRunning = "YES"
buildForProfiling = "YES" buildForProfiling = "YES"
buildForArchiving = "YES" buildForArchiving = "YES"
buildForAnalyzing = "YES"> buildForAnalyzing = "YES">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045" BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "siab_bluetooth_app.app" BuildableName = "siab_bluetooth_app.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildActionEntry> </BuildActionEntry>
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045" BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "siab_bluetooth_app.app" BuildableName = "siab_bluetooth_app.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<Testables> <Testables>
<TestableReference <TestableReference
skipped = "NO" skipped = "NO"
parallelizable = "YES"> parallelizable = "YES">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "331C80D4294CF70F00263BE5" BlueprintIdentifier = "331C80D4294CF70F00263BE5"
BuildableName = "RunnerTests.xctest" BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests" BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</TestableReference> </TestableReference>
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal" debugServiceExtension = "internal"
enableGPUValidationMode = "1" enableGPUValidationMode = "1"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<BuildableProductRunnable <BuildableProductRunnable
runnableDebuggingMode = "0"> runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045" BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "siab_bluetooth_app.app" BuildableName = "siab_bluetooth_app.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Profile" buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<BuildableProductRunnable <BuildableProductRunnable
runnableDebuggingMode = "0"> runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045" BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "siab_bluetooth_app.app" BuildableName = "siab_bluetooth_app.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction
buildConfiguration = "Debug"> buildConfiguration = "Debug">
</AnalyzeAction> </AnalyzeAction>
<ArchiveAction <ArchiveAction
buildConfiguration = "Release" buildConfiguration = "Release"
revealArchiveInOrganizer = "YES"> revealArchiveInOrganizer = "YES">
</ArchiveAction> </ArchiveAction>
</Scheme> </Scheme>
+7 -7
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
</Workspace> </Workspace>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>IDEDidComputeMac32BitWarning</key> <key>IDEDidComputeMac32BitWarning</key>
<true/> <true/>
</dict> </dict>
</plist> </plist>
+13 -13
View File
@@ -1,13 +1,13 @@
import Cocoa import Cocoa
import FlutterMacOS import FlutterMacOS
@main @main
class AppDelegate: FlutterAppDelegate { class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true return true
} }
override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
return true return true
} }
} }
@@ -1,68 +1,68 @@
{ {
"images" : [ "images" : [
{ {
"size" : "16x16", "size" : "16x16",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_16.png", "filename" : "app_icon_16.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "16x16", "size" : "16x16",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_32.png", "filename" : "app_icon_32.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "32x32", "size" : "32x32",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_32.png", "filename" : "app_icon_32.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "32x32", "size" : "32x32",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_64.png", "filename" : "app_icon_64.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "128x128", "size" : "128x128",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_128.png", "filename" : "app_icon_128.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "128x128", "size" : "128x128",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_256.png", "filename" : "app_icon_256.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "256x256", "size" : "256x256",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_256.png", "filename" : "app_icon_256.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "256x256", "size" : "256x256",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_512.png", "filename" : "app_icon_512.png",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"size" : "512x512", "size" : "512x512",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_512.png", "filename" : "app_icon_512.png",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"size" : "512x512", "size" : "512x512",
"idiom" : "mac", "idiom" : "mac",
"filename" : "app_icon_1024.png", "filename" : "app_icon_1024.png",
"scale" : "2x" "scale" : "2x"
} }
], ],
"info" : { "info" : {
"version" : 1, "version" : 1,
"author" : "xcode" "author" : "xcode"
} }
} }
Loaded 100 of 125 files, more files were not shown because too many files have changed in this diff. Show more