Compare commits
298 Commits
Author | SHA1 | Date | |
---|---|---|---|
51f01a661a | |||
|
0331605e1e | ||
|
11b040ae9e | ||
|
1f1bc63bc1 | ||
|
e5f1c55993 | ||
|
596abc850c | ||
|
b6699831d7 | ||
|
371421a049 | ||
|
1b508f3200 | ||
|
dadb6275fc | ||
|
c00dae0b97 | ||
|
01ba5f624f | ||
|
e41f2ba530 | ||
|
1dfa1574c8 | ||
|
095205d047 | ||
|
648eac7298 | ||
|
a1f2a778a2 | ||
|
7f892df3c8 | ||
|
9c64993cff | ||
|
097295f393 | ||
|
bb2564efdd | ||
|
85379a148a | ||
|
8d5daf3edd | ||
|
45a9a8348f | ||
|
3ee40b811a | ||
|
b7b9141682 | ||
|
9194c8a41a | ||
|
2faa7d7aab | ||
|
663ad161fd | ||
|
9d2409cc9d | ||
|
b28c6994f7 | ||
|
c018fa3dd1 | ||
|
be5e4fbdf3 | ||
|
a71de46804 | ||
|
4b34f81555 | ||
|
2f500a344e | ||
|
fa640e005d | ||
|
54cfee18c3 | ||
|
a57a23d4e0 | ||
|
6f7a69d50d | ||
|
a40ce7c080 | ||
|
590e542b34 | ||
|
76eba1e3e9 | ||
|
4913c2fe92 | ||
|
5d8da79941 | ||
|
68a0f4d2df | ||
|
848ae5cbb6 | ||
|
4ee616f67c | ||
|
3da2041963 | ||
|
5fea5fc017 | ||
|
59af5d9e3e | ||
|
1ffc18d001 | ||
|
80a5cbdcca | ||
|
537d2ed9e4 | ||
|
c450c71d05 | ||
|
c45e1fc77e | ||
|
ea47695847 | ||
|
cbbd343f71 | ||
|
bf2c0b2d04 | ||
|
90e642f4b2 | ||
|
539b79a20e | ||
|
2853af8f61 | ||
|
44300dbe23 | ||
|
c0fae98895 | ||
|
bbab178465 | ||
|
28734b7f1f | ||
|
00e3dcc234 | ||
|
3ce1d3a68d | ||
|
6e3d94eece | ||
|
3d9d15c5a0 | ||
|
824f4a1ff1 | ||
|
a6c99352e6 | ||
|
74b536b366 | ||
|
91c8cb9760 | ||
|
3533369066 | ||
|
432becb17a | ||
|
66840b9300 | ||
|
28ebe79ad2 | ||
|
cc6e1649d1 | ||
|
e34479ccd8 | ||
|
7c76fc9c09 | ||
|
8daa4c112e | ||
|
5b6cd2d8b5 | ||
|
cbde677283 | ||
|
d7ac853653 | ||
|
1f27c303e9 | ||
|
fc23212912 | ||
|
9045b5d8fd | ||
|
d710a9718a | ||
|
c2d33ac9d3 | ||
|
9e4d457339 | ||
|
a056373207 | ||
|
de6c18a42d | ||
|
07bd69ac77 | ||
|
a3594470cd | ||
|
93b0ed57cb | ||
|
d856f91a93 | ||
|
d2062cd2a4 | ||
|
7feafe35b8 | ||
|
eb0534106f | ||
|
66ca833c58 | ||
|
2887de4704 | ||
|
5b595c3f31 | ||
|
1c853b1c39 | ||
|
04be1daf42 | ||
|
97cb83733c | ||
|
395fa12ad0 | ||
|
c4f4c1a05a | ||
|
00847778f5 | ||
|
e974ce8ca0 | ||
|
24d08a69e9 | ||
|
c071798b02 | ||
|
5d7f14fd17 | ||
|
7f786610a7 | ||
|
94afbb1bcf | ||
|
616f5ace91 | ||
|
76ff50d09a | ||
|
0805da1b37 | ||
|
8c3ef002a8 | ||
|
d783d706e1 | ||
|
b188e77449 | ||
|
a8f0b43c99 | ||
|
a2a5eef138 | ||
|
5b37a65f14 | ||
|
48e9b5fc25 | ||
|
758a58b93d | ||
|
310dcd918b | ||
|
0cff2e5ecc | ||
|
505b0a2054 | ||
|
170bf6b13b | ||
|
1b07243f25 | ||
|
2185a02c46 | ||
|
26e82be9f3 | ||
|
cac0944d32 | ||
|
dff396283f | ||
|
f10786ed82 | ||
|
b0f0b0084e | ||
|
34bdef3db0 | ||
|
6a0eb051e6 | ||
|
8ac60d46a8 | ||
|
4d5347013c | ||
|
ef7b99c992 | ||
|
105073480a | ||
|
431a17dc1d | ||
|
0fa3a344c9 | ||
|
bbd6a68731 | ||
|
79631cd91d | ||
|
c4e34edfd2 | ||
|
8f2625bc23 | ||
|
fdaabec9f3 | ||
|
dce9138640 | ||
|
5065002bce | ||
|
27613c6922 | ||
|
a04d8bbb71 | ||
|
31ec04dea9 | ||
|
509487f789 | ||
|
8a29d67096 | ||
|
a38f564411 | ||
|
6523ec320b | ||
|
c7f00c8d32 | ||
|
ab7ce7bcd6 | ||
|
e440b29276 | ||
|
efc98ee6cc | ||
|
3987d8ea7d | ||
|
5c72a83def | ||
|
43d463a9b4 | ||
|
a132e97916 | ||
|
345f73f048 | ||
|
bc21f55d62 | ||
|
b0337152fa | ||
|
b430fc4f1b | ||
|
25d468e3eb | ||
|
c05c92b442 | ||
|
fa1c4bb52e | ||
|
9ff9527b84 | ||
|
fc60942b66 | ||
|
d369891d1e | ||
|
14afe90485 | ||
|
56d85a87fd | ||
|
994a454587 | ||
|
f2408b936c | ||
|
5c79438bf2 | ||
|
aad94222e8 | ||
|
43a1e801b8 | ||
|
bb580d5d78 | ||
|
472fdd4ced | ||
|
76fb0f7d1a | ||
|
d77055d340 | ||
|
ce767b7155 | ||
|
a9e4e12ee7 | ||
|
ac10dc36f8 | ||
|
b6e35f6f92 | ||
|
7318ce7d9a | ||
|
1274130ca1 | ||
|
9b4d7cc226 | ||
|
fe83fc0c5d | ||
|
d3e7e7e606 | ||
|
4492f9e4ee | ||
|
34e49a0808 | ||
|
8b0ed00787 | ||
|
35070ad8a0 | ||
|
23a1741722 | ||
|
8a09f54d5c | ||
|
479e0838e8 | ||
|
46125abf7f | ||
|
a387ca18db | ||
|
e30e2ebf48 | ||
|
9e4cd6ee7d | ||
|
be5b5fc9a6 | ||
|
11ee06f9ef | ||
|
eec8c58d88 | ||
|
6ad95e23e0 | ||
|
c2be9688db | ||
|
6c0d9806cc | ||
|
6ce11de7d4 | ||
|
ddf5e54089 | ||
|
38dc787e27 | ||
|
fbd6bdaa9b | ||
|
57cda296e6 | ||
|
18e3cb731e | ||
|
50240ba0c2 | ||
|
5f978091bd | ||
|
f1be3a4a37 | ||
|
c819bcfdef | ||
|
863afcae4f | ||
|
253c6b2075 | ||
|
c50cecded3 | ||
|
92c60ce18a | ||
|
c689fd60e7 | ||
|
e5a8da9b57 | ||
|
bcd7842e40 | ||
|
f08e3f9cb9 | ||
|
853d16aa11 | ||
|
330206079a | ||
|
4c3583cf6e | ||
|
0c255bec9a | ||
|
1a51d2e906 | ||
|
50d4bac794 | ||
|
0f2e2afd9b | ||
|
8b55cca3a0 | ||
|
b90108fa92 | ||
|
c6eec34922 | ||
|
110766d516 | ||
|
3080f8d867 | ||
|
e09aa3d1b8 | ||
|
f786e3f5dc | ||
|
11aad53f71 | ||
|
96734a070f | ||
|
3e6df3e8b0 | ||
|
7a64e91d28 | ||
|
289edfcde4 | ||
|
7906e6ba36 | ||
|
068d7daf9d | ||
|
b1084d8542 | ||
|
4661f6997c | ||
|
cda6d7cbaa | ||
|
042cb6425a | ||
|
d0196a458c | ||
|
70fd472ca1 | ||
|
eb6149454c | ||
|
cb75f13005 | ||
|
384bf83e35 | ||
|
567eb38bea | ||
|
edec65121b | ||
|
a1af24f7d4 | ||
|
6de8bf931f | ||
|
4608eecb30 | ||
|
ead7c75beb | ||
|
8050060b7e | ||
|
d4d27751eb | ||
|
92038ed12a | ||
|
92635d88e3 | ||
|
aacb37575e | ||
|
4c09c20b3b | ||
|
1ff80a1859 | ||
|
493215583c | ||
|
6e5a715283 | ||
|
24f5f8487d | ||
|
8bd8403840 | ||
|
9a9ccff85c | ||
|
61e93029d7 | ||
|
d2b44a4dc6 | ||
|
e30f5de874 | ||
|
77b03a29a5 | ||
|
f81797dda1 | ||
|
849923d739 | ||
|
13073d4e02 | ||
|
a0e1e99223 | ||
|
7324760129 | ||
|
9c2c93ea91 | ||
|
ce4fea8364 | ||
|
64b9136518 | ||
|
5abdc22102 | ||
|
602c506452 | ||
|
2106da96ab | ||
|
4fe946e587 | ||
|
008a09ac05 | ||
|
1eae15a1a8 |
1
.gitignore
vendored
@ -33,7 +33,6 @@ desktop.ini
|
|||||||
/build/
|
/build/
|
||||||
|
|
||||||
# Web related
|
# Web related
|
||||||
lib/generated_plugin_registrant.dart
|
|
||||||
|
|
||||||
# Symbolication related
|
# Symbolication related
|
||||||
app.*.symbols
|
app.*.symbols
|
||||||
|
29
.metadata
@ -1,11 +1,11 @@
|
|||||||
# 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.
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
revision: "efbf63d9c66b9f6ec30e9ad4611189aa80003d31"
|
||||||
channel: beta
|
channel: "stable"
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
|
|
||||||
@ -13,26 +13,11 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||||
base_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||||
- platform: android
|
|
||||||
create_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
base_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
- platform: ios
|
|
||||||
create_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
base_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
- platform: linux
|
|
||||||
create_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
base_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
- platform: macos
|
|
||||||
create_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
base_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
- platform: web
|
- platform: web
|
||||||
create_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||||
base_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||||
- platform: windows
|
|
||||||
create_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
base_revision: 75927305ff855f76a9ef704f9b4a86fa2fce7292
|
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
25
README.md
@ -23,32 +23,17 @@ To try the app you can download it from your favorite app store:
|
|||||||
|
|
||||||
If you're new to Flutter the first thing you'll need is to follow the [setup instructions](https://flutter.dev/docs/get-started/install).
|
If you're new to Flutter the first thing you'll need is to follow the [setup instructions](https://flutter.dev/docs/get-started/install).
|
||||||
|
|
||||||
Once Flutter is setup, you can use the latest `beta` channel:
|
Once Flutter is setup, you can use the latest `stable` channel:
|
||||||
* `flutter channel beta`
|
* `flutter channel stable`
|
||||||
* `flutter upgrade`
|
* `flutter upgrade`
|
||||||
|
|
||||||
Once on `beta` you're ready to run the app on your local device or simulator:
|
Once on `stable` you're ready to run the app on your local device or simulator:
|
||||||
* `flutter run -d ios`
|
* `flutter run -d ios`
|
||||||
* `flutter run -d android`
|
* `flutter run -d android`
|
||||||
|
|
||||||
### Impeller Rendering Layer
|
### Impeller Rendering
|
||||||
|
|
||||||
Impeller is Flutter's next-generation rendering layer, that takes full advantage of modern hardware-accelerated graphics APIs. It is currently available as an **early adopter preview**, but is not yet feature-complete or fully optimized.
|
This app uses the new [Impeller Runtime](https://docs.flutter.dev/perf/impeller) by default on iOS.
|
||||||
|
|
||||||
The version of Wonderous available in the iOS app store uses Impeller, but by default this code base does not. If you'd like to enable Impeller for iOS, follow these steps:
|
|
||||||
|
|
||||||
Edit the `Info.plist` file and set `FLTEnableImpeller` to `true`:
|
|
||||||
```
|
|
||||||
<key>FLTEnableImpeller</key>
|
|
||||||
<true/>
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, switch to the `master` channel and build as normal:
|
|
||||||
* `flutter channel master`
|
|
||||||
* `flutter upgrade`
|
|
||||||
* `flutter run -d ios`
|
|
||||||
|
|
||||||
**Note:** Currently, when Impeller is enabled testing in Simulator will not work, you will need to test on a physical device.
|
|
||||||
|
|
||||||
# About gskinner
|
# About gskinner
|
||||||
We build innovative digital experiences for smart clients, and we love how Flutter unleashes our creativity when building multi-platform apps. Don't hesitate to [stop by our site](https://gskinner.com/) to learn more about what we do, or check out other [innovative Flutter projects](https://flutter.gskinner.com) we've built. We'd love to hear from you!
|
We build innovative digital experiences for smart clients, and we love how Flutter unleashes our creativity when building multi-platform apps. Don't hesitate to [stop by our site](https://gskinner.com/) to learn more about what we do, or check out other [innovative Flutter projects](https://flutter.gskinner.com) we've built. We'd love to hear from you!
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
# packages, and plugins designed to encourage good coding practices.
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
errors:
|
||||||
|
prefer_const_constructors: ignore
|
||||||
|
unused_element: ignore # mostly because of super.key
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
# The lint rules applied to this project can be customized in the
|
# The lint rules applied to this project can be customized in the
|
||||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
@ -22,9 +27,8 @@ linter:
|
|||||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
# producing the lint.
|
# producing the lint.
|
||||||
rules:
|
rules:
|
||||||
always_declare_return_types: true
|
- always_declare_return_types
|
||||||
always_use_package_imports: true
|
- always_use_package_imports
|
||||||
prefer_const_constructors: false
|
- prefer_single_quotes
|
||||||
prefer_single_quotes: true
|
|
||||||
# Additional information about this file can be found at
|
# Additional information about this file can be found at
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
@ -33,7 +33,7 @@ apply plugin: 'kotlin-android'
|
|||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion flutter.compileSdkVersion
|
compileSdkVersion 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
configurations.all {
|
configurations.all {
|
||||||
@ -47,17 +47,9 @@ android {
|
|||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
|
||||||
release {
|
|
||||||
keyAlias keystoreProperties['keyAlias']
|
|
||||||
keyPassword keystoreProperties['keyPassword']
|
|
||||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
|
||||||
storePassword keystoreProperties['storePassword']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.debug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.gskinner.flutter.wonders">
|
package="com.gskinner.flutter.wonders">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<application
|
<application
|
||||||
android:label="Wonderous"
|
android:label="Wonderous"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 11 KiB |
BIN
android/app/src/main/res/drawable-night-hdpi/android12splash.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
android/app/src/main/res/drawable-night-mdpi/android12splash.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 70 B After Width: | Height: | Size: 69 B |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 70 B After Width: | Height: | Size: 69 B |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
21
android/app/src/main/res/values-night-v31/styles.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||||
|
<item name="android:windowSplashScreenBackground">#272625</item>
|
||||||
|
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||||
|
</style>
|
||||||
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
This theme determines the color of the Android Window while your
|
||||||
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
|
running.
|
||||||
|
|
||||||
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
|
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
@ -5,6 +5,10 @@
|
|||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
Flutter draws its first frame -->
|
Flutter draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</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
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<item name="android:forceDarkAllowed">false</item>
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
<item name="android:windowFullscreen">false</item>
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||||
<item name="android:windowSplashScreenBackground">#272625</item>
|
<item name="android:windowSplashScreenBackground">#272625</item>
|
||||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
<item name="android:forceDarkAllowed">false</item>
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
<item name="android:windowFullscreen">false</item>
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</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.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.6.10'
|
ext.kotlin_version = '1.9.10'
|
||||||
ext.maps_version = '18.1.0'
|
ext.maps_version = '18.1.0'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@ -8,7 +8,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,6 +28,6 @@ subprojects {
|
|||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 3.0 KiB |
BIN
assets/images/_common/texture/2.0x/roller-1-white.gif
Normal file
After Width: | Height: | Size: 170 KiB |
BIN
assets/images/_common/texture/2.0x/roller-2-white.gif
Normal file
After Width: | Height: | Size: 285 KiB |
BIN
assets/images/_common/texture/3.0x/roller-1-white.gif
Normal file
After Width: | Height: | Size: 565 KiB |
BIN
assets/images/_common/texture/3.0x/roller-2-white.gif
Normal file
After Width: | Height: | Size: 954 KiB |
Before Width: | Height: | Size: 795 KiB |
BIN
assets/images/_common/texture/roller-1-white.gif
Normal file
After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 795 KiB |
Before Width: | Height: | Size: 1.3 MiB |
BIN
assets/images/_common/texture/roller-2-white.gif
Normal file
After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 262 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 33 KiB |
BIN
assets/images/widget/background-empty.jpg
Normal file
After Width: | Height: | Size: 217 KiB |
BIN
assets/images/widget/wonderous-icon.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
@ -1,95 +1,83 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_inappwebview (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_inappwebview/Core (= 0.0.1)
|
|
||||||
- OrderedSet (~> 5.0)
|
|
||||||
- flutter_inappwebview/Core (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- OrderedSet (~> 5.0)
|
|
||||||
- flutter_native_splash (0.0.1):
|
- flutter_native_splash (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- google_maps_flutter_ios (0.0.1):
|
- google_maps_flutter_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- GoogleMaps
|
- GoogleMaps (< 9.0)
|
||||||
- GoogleMaps (6.2.1):
|
- GoogleMaps (6.2.1):
|
||||||
- GoogleMaps/Maps (= 6.2.1)
|
- GoogleMaps/Maps (= 6.2.1)
|
||||||
- GoogleMaps/Base (6.2.1)
|
- GoogleMaps/Base (6.2.1)
|
||||||
- GoogleMaps/Maps (6.2.1):
|
- GoogleMaps/Maps (6.2.1):
|
||||||
- GoogleMaps/Base
|
- GoogleMaps/Base
|
||||||
- image_gallery_saver (1.5.0):
|
- home_widget (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- integration_test (0.0.1):
|
- image_gallery_saver (2.0.2):
|
||||||
- Flutter
|
- Flutter
|
||||||
- OrderedSet (5.0.0)
|
|
||||||
- package_info_plus (0.4.5):
|
- package_info_plus (0.4.5):
|
||||||
- Flutter
|
- Flutter
|
||||||
- path_provider_ios (0.0.1):
|
- path_provider_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- share_plus (0.0.1):
|
- FlutterMacOS
|
||||||
- Flutter
|
- shared_preferences_foundation (0.0.1):
|
||||||
- shared_preferences_ios (0.0.1):
|
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- url_launcher_ios (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- webview_flutter_wkwebview (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
|
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`)
|
- google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`)
|
||||||
|
- home_widget (from `.symlinks/plugins/home_widget/ios`)
|
||||||
- image_gallery_saver (from `.symlinks/plugins/image_gallery_saver/ios`)
|
- image_gallery_saver (from `.symlinks/plugins/image_gallery_saver/ios`)
|
||||||
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
|
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
- GoogleMaps
|
- GoogleMaps
|
||||||
- OrderedSet
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_inappwebview:
|
|
||||||
:path: ".symlinks/plugins/flutter_inappwebview/ios"
|
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
google_maps_flutter_ios:
|
google_maps_flutter_ios:
|
||||||
:path: ".symlinks/plugins/google_maps_flutter_ios/ios"
|
:path: ".symlinks/plugins/google_maps_flutter_ios/ios"
|
||||||
|
home_widget:
|
||||||
|
:path: ".symlinks/plugins/home_widget/ios"
|
||||||
image_gallery_saver:
|
image_gallery_saver:
|
||||||
:path: ".symlinks/plugins/image_gallery_saver/ios"
|
:path: ".symlinks/plugins/image_gallery_saver/ios"
|
||||||
integration_test:
|
|
||||||
:path: ".symlinks/plugins/integration_test/ios"
|
|
||||||
package_info_plus:
|
package_info_plus:
|
||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
path_provider_ios:
|
path_provider_foundation:
|
||||||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
share_plus:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/share_plus/ios"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
shared_preferences_ios:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences_ios/ios"
|
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
webview_flutter_wkwebview:
|
||||||
|
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||||
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
|
||||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
||||||
google_maps_flutter_ios: 66201f392bf62d500f07670a30488a247b9bb5b9
|
google_maps_flutter_ios: d1318b4ff711612cab16862d7a87e31a7403d458
|
||||||
GoogleMaps: 20d7b12be49a14287f797e88e0e31bc4156aaeb4
|
GoogleMaps: 20d7b12be49a14287f797e88e0e31bc4156aaeb4
|
||||||
image_gallery_saver: 259eab68fb271cfd57d599904f7acdc7832e7ef2
|
home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57
|
||||||
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
|
image_gallery_saver: cb43cc43141711190510e92c460eb1655cd343cb
|
||||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
|
||||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
||||||
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
|
||||||
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
webview_flutter_wkwebview: 4f3e50f7273d31e5500066ed267e3ae4309c5ae4
|
||||||
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
||||||
|
|
||||||
COCOAPODS: 1.11.3
|
COCOAPODS: 1.15.0
|
||||||
|
@ -8,6 +8,18 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
296251252AE7410D00D574FF /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296251242AE7410D00D574FF /* Colors.swift */; };
|
||||||
|
2978ECDD2B62D00C00E36CE8 /* FlutterAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2978ECDC2B62D00C00E36CE8 /* FlutterAssets.swift */; };
|
||||||
|
297F6FC72AD06E0D00FF159E /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 297F6FC62AD06E0D00FF159E /* WidgetKit.framework */; };
|
||||||
|
297F6FC92AD06E0D00FF159E /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 297F6FC82AD06E0D00FF159E /* SwiftUI.framework */; };
|
||||||
|
297F6FCC2AD06E0D00FF159E /* WonderousWidgetBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 297F6FCB2AD06E0D00FF159E /* WonderousWidgetBundle.swift */; };
|
||||||
|
297F6FCE2AD06E0D00FF159E /* WonderousWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 297F6FCD2AD06E0D00FF159E /* WonderousWidget.swift */; };
|
||||||
|
297F6FD12AD06E0F00FF159E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 297F6FD02AD06E0F00FF159E /* Assets.xcassets */; };
|
||||||
|
297F6FD32AD06E0F00FF159E /* WonderousWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 297F6FCF2AD06E0D00FF159E /* WonderousWidget.intentdefinition */; };
|
||||||
|
297F6FD42AD06E0F00FF159E /* WonderousWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 297F6FCF2AD06E0D00FF159E /* WonderousWidget.intentdefinition */; };
|
||||||
|
297F6FD72AD06E0F00FF159E /* Wonderous WidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 297F6FC52AD06E0D00FF159E /* Wonderous WidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
297FD5742AE18011008D8BFE /* WonderousWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 297FD5732AE18011008D8BFE /* WonderousWidgetView.swift */; };
|
||||||
|
297FD5762AE19BD9008D8BFE /* WonderWidgetViewComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 297FD5752AE19BD9008D8BFE /* WonderWidgetViewComponents.swift */; };
|
||||||
323DE3CFA8490EAB3C4E249C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A44ACC5DE81A9C3E5BDA151 /* Pods_Runner.framework */; };
|
323DE3CFA8490EAB3C4E249C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A44ACC5DE81A9C3E5BDA151 /* Pods_Runner.framework */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
@ -17,6 +29,13 @@
|
|||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
297F6FD52AD06E0F00FF159E /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 297F6FC42AD06E0D00FF159E;
|
||||||
|
remoteInfo = WonderousWidgetExtension;
|
||||||
|
};
|
||||||
E214FC8827C5A18E005F78FB /* PBXContainerItemProxy */ = {
|
E214FC8827C5A18E005F78FB /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
@ -27,6 +46,17 @@
|
|||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
297F6FD82AD06E0F00FF159E /* Embed Foundation Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
297F6FD72AD06E0F00FF159E /* Wonderous WidgetExtension.appex in Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed Foundation Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@ -43,6 +73,19 @@
|
|||||||
1475293CB8660AC785DF56AB /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
1475293CB8660AC785DF56AB /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
296251242AE7410D00D574FF /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
|
||||||
|
2978ECDC2B62D00C00E36CE8 /* FlutterAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlutterAssets.swift; sourceTree = "<group>"; };
|
||||||
|
297F6FC52AD06E0D00FF159E /* Wonderous WidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; name = "Wonderous WidgetExtension.appex"; path = WonderousWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
297F6FC62AD06E0D00FF159E /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
|
||||||
|
297F6FC82AD06E0D00FF159E /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
||||||
|
297F6FCB2AD06E0D00FF159E /* WonderousWidgetBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WonderousWidgetBundle.swift; sourceTree = "<group>"; };
|
||||||
|
297F6FCD2AD06E0D00FF159E /* WonderousWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WonderousWidget.swift; sourceTree = "<group>"; };
|
||||||
|
297F6FCF2AD06E0D00FF159E /* WonderousWidget.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = WonderousWidget.intentdefinition; sourceTree = "<group>"; };
|
||||||
|
297F6FD02AD06E0F00FF159E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
297F6FD22AD06E0F00FF159E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
297FD56C2ADF0DAB008D8BFE /* WonderousWidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WonderousWidgetExtension.entitlements; sourceTree = "<group>"; };
|
||||||
|
297FD5732AE18011008D8BFE /* WonderousWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WonderousWidgetView.swift; sourceTree = "<group>"; };
|
||||||
|
297FD5752AE19BD9008D8BFE /* WonderWidgetViewComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WonderWidgetViewComponents.swift; sourceTree = "<group>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
4A44ACC5DE81A9C3E5BDA151 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
4A44ACC5DE81A9C3E5BDA151 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
@ -62,6 +105,15 @@
|
|||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
297F6FC22AD06E0D00FF159E /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
297F6FC92AD06E0D00FF159E /* SwiftUI.framework in Frameworks */,
|
||||||
|
297F6FC72AD06E0D00FF159E /* WidgetKit.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@ -80,10 +132,28 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
297F6FCA2AD06E0D00FF159E /* WonderousWidget */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
297F6FCB2AD06E0D00FF159E /* WonderousWidgetBundle.swift */,
|
||||||
|
297F6FCD2AD06E0D00FF159E /* WonderousWidget.swift */,
|
||||||
|
297F6FCF2AD06E0D00FF159E /* WonderousWidget.intentdefinition */,
|
||||||
|
297F6FD02AD06E0F00FF159E /* Assets.xcassets */,
|
||||||
|
297F6FD22AD06E0F00FF159E /* Info.plist */,
|
||||||
|
297FD5732AE18011008D8BFE /* WonderousWidgetView.swift */,
|
||||||
|
297FD5752AE19BD9008D8BFE /* WonderWidgetViewComponents.swift */,
|
||||||
|
296251242AE7410D00D574FF /* Colors.swift */,
|
||||||
|
2978ECDC2B62D00C00E36CE8 /* FlutterAssets.swift */,
|
||||||
|
);
|
||||||
|
path = WonderousWidget;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
5073AC1D92C10773F20D12A2 /* Frameworks */ = {
|
5073AC1D92C10773F20D12A2 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4A44ACC5DE81A9C3E5BDA151 /* Pods_Runner.framework */,
|
4A44ACC5DE81A9C3E5BDA151 /* Pods_Runner.framework */,
|
||||||
|
297F6FC62AD06E0D00FF159E /* WidgetKit.framework */,
|
||||||
|
297F6FC82AD06E0D00FF159E /* SwiftUI.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -102,8 +172,10 @@
|
|||||||
97C146E51CF9000F007C117D = {
|
97C146E51CF9000F007C117D = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
297FD56C2ADF0DAB008D8BFE /* WonderousWidgetExtension.entitlements */,
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
|
297F6FCA2AD06E0D00FF159E /* WonderousWidget */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
5073AC1D92C10773F20D12A2 /* Frameworks */,
|
5073AC1D92C10773F20D12A2 /* Frameworks */,
|
||||||
E090BB04291350D10AF9DE4E /* Pods */,
|
E090BB04291350D10AF9DE4E /* Pods */,
|
||||||
@ -115,6 +187,7 @@
|
|||||||
children = (
|
children = (
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
E214FC8227C5A18D005F78FB /* wondersUITests.xctest */,
|
E214FC8227C5A18D005F78FB /* wondersUITests.xctest */,
|
||||||
|
297F6FC52AD06E0D00FF159E /* Wonderous WidgetExtension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -148,6 +221,23 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
297F6FC42AD06E0D00FF159E /* WonderousWidgetExtension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 297F6FDC2AD06E0F00FF159E /* Build configuration list for PBXNativeTarget "WonderousWidgetExtension" */;
|
||||||
|
buildPhases = (
|
||||||
|
297F6FC12AD06E0D00FF159E /* Sources */,
|
||||||
|
297F6FC22AD06E0D00FF159E /* Frameworks */,
|
||||||
|
297F6FC32AD06E0D00FF159E /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = WonderousWidgetExtension;
|
||||||
|
productName = WonderousWidgetExtension;
|
||||||
|
productReference = 297F6FC52AD06E0D00FF159E /* Wonderous WidgetExtension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
@ -157,6 +247,7 @@
|
|||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
|
297F6FD82AD06E0F00FF159E /* Embed Foundation Extensions */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
9DAF500633B345EE15CA82E0 /* [CP] Embed Pods Frameworks */,
|
9DAF500633B345EE15CA82E0 /* [CP] Embed Pods Frameworks */,
|
||||||
@ -165,6 +256,7 @@
|
|||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
297F6FD62AD06E0F00FF159E /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Runner;
|
name = Runner;
|
||||||
productName = Runner;
|
productName = Runner;
|
||||||
@ -198,10 +290,13 @@
|
|||||||
KnownAssetTags = (
|
KnownAssetTags = (
|
||||||
New,
|
New,
|
||||||
);
|
);
|
||||||
LastSwiftUpdateCheck = 1320;
|
LastSwiftUpdateCheck = 1430;
|
||||||
LastUpgradeCheck = 1300;
|
LastUpgradeCheck = 1430;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
297F6FC42AD06E0D00FF159E = {
|
||||||
|
CreatedOnToolsVersion = 14.3.1;
|
||||||
|
};
|
||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
CreatedOnToolsVersion = 7.3.1;
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
LastSwiftMigration = 1100;
|
LastSwiftMigration = 1100;
|
||||||
@ -227,11 +322,20 @@
|
|||||||
targets = (
|
targets = (
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
E214FC8127C5A18D005F78FB /* wondersUITests */,
|
E214FC8127C5A18D005F78FB /* wondersUITests */,
|
||||||
|
297F6FC42AD06E0D00FF159E /* WonderousWidgetExtension */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
297F6FC32AD06E0D00FF159E /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
297F6FD12AD06E0F00FF159E /* Assets.xcassets in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@ -282,6 +386,7 @@
|
|||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||||
);
|
);
|
||||||
name = "Thin Binary";
|
name = "Thin Binary";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
@ -342,10 +447,25 @@
|
|||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
297F6FC12AD06E0D00FF159E /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
297FD5762AE19BD9008D8BFE /* WonderWidgetViewComponents.swift in Sources */,
|
||||||
|
296251252AE7410D00D574FF /* Colors.swift in Sources */,
|
||||||
|
297F6FD32AD06E0F00FF159E /* WonderousWidget.intentdefinition in Sources */,
|
||||||
|
2978ECDD2B62D00C00E36CE8 /* FlutterAssets.swift in Sources */,
|
||||||
|
297FD5742AE18011008D8BFE /* WonderousWidgetView.swift in Sources */,
|
||||||
|
297F6FCE2AD06E0D00FF159E /* WonderousWidget.swift in Sources */,
|
||||||
|
297F6FCC2AD06E0D00FF159E /* WonderousWidgetBundle.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
297F6FD42AD06E0F00FF159E /* WonderousWidget.intentdefinition in Sources */,
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||||
);
|
);
|
||||||
@ -361,6 +481,11 @@
|
|||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
297F6FD62AD06E0F00FF159E /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 297F6FC42AD06E0D00FF159E /* WonderousWidgetExtension */;
|
||||||
|
targetProxy = 297F6FD52AD06E0F00FF159E /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
E214FC8927C5A18E005F78FB /* PBXTargetDependency */ = {
|
E214FC8927C5A18E005F78FB /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||||
@ -444,9 +569,12 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 4;
|
CURRENT_PROJECT_VERSION = 4;
|
||||||
DEVELOPMENT_TEAM = S3TL5AY6Y3;
|
DEVELOPMENT_TEAM = S3TL5AY6Y3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@ -458,6 +586,7 @@
|
|||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.gskinner.flutter.wonders;
|
PRODUCT_BUNDLE_IDENTIFIER = com.gskinner.flutter.wonders;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
@ -465,6 +594,120 @@
|
|||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
};
|
};
|
||||||
|
297F6FD92AD06E0F00FF159E /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = WonderousWidgetExtension.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = S3TL5AY6Y3;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = WonderousWidget/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Wonderous Widget";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "com.gskinner.flutter.wonders.Wonderous-Widget";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
297F6FDA2AD06E0F00FF159E /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = WonderousWidgetExtension.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = S3TL5AY6Y3;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = WonderousWidget/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Wonderous Widget";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "com.gskinner.flutter.wonders.Wonderous-Widget";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
297F6FDB2AD06E0F00FF159E /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "Wonderous WidgetExtension.entitlements";
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = S3TL5AY6Y3;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "Wonderous Widget/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Wonderous Widget";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "com.gskinner.flutter.wonders.Wonderous-Widget";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
97C147031CF9000F007C117D /* Debug */ = {
|
97C147031CF9000F007C117D /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
@ -580,9 +823,12 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 4;
|
CURRENT_PROJECT_VERSION = 4;
|
||||||
DEVELOPMENT_TEAM = S3TL5AY6Y3;
|
DEVELOPMENT_TEAM = S3TL5AY6Y3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@ -594,6 +840,7 @@
|
|||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.gskinner.flutter.wonders;
|
PRODUCT_BUNDLE_IDENTIFIER = com.gskinner.flutter.wonders;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@ -606,6 +853,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
@ -714,6 +962,16 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
297F6FDC2AD06E0F00FF159E /* Build configuration list for PBXNativeTarget "WonderousWidgetExtension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
297F6FD92AD06E0F00FF159E /* Debug */,
|
||||||
|
297F6FDA2AD06E0F00FF159E /* Release */,
|
||||||
|
297F6FDB2AD06E0F00FF159E /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1300"
|
LastUpgradeVersion = "1430"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
@ -1,122 +1,122 @@
|
|||||||
{
|
{
|
||||||
"images": [
|
"images": [
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename": "Icon-App-20x20@2x.png",
|
"filename": "Icon-App-20x20@2x.png",
|
||||||
"scale" : "2x"
|
"idiom": "iphone",
|
||||||
|
"scale": "2x",
|
||||||
|
"size": "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename": "Icon-App-20x20@3x.png",
|
"filename": "Icon-App-20x20@3x.png",
|
||||||
"scale" : "3x"
|
"idiom": "iphone",
|
||||||
|
"scale": "3x",
|
||||||
|
"size": "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename": "Icon-App-29x29@1x.png",
|
"filename": "Icon-App-29x29@1x.png",
|
||||||
"scale" : "1x"
|
"idiom": "iphone",
|
||||||
|
"scale": "1x",
|
||||||
|
"size": "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename": "Icon-App-29x29@2x.png",
|
"filename": "Icon-App-29x29@2x.png",
|
||||||
"scale" : "2x"
|
"idiom": "iphone",
|
||||||
|
"scale": "2x",
|
||||||
|
"size": "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename": "Icon-App-29x29@3x.png",
|
"filename": "Icon-App-29x29@3x.png",
|
||||||
"scale" : "3x"
|
"idiom": "iphone",
|
||||||
|
"scale": "3x",
|
||||||
|
"size": "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename": "Icon-App-40x40@2x.png",
|
"filename": "Icon-App-40x40@2x.png",
|
||||||
"scale" : "2x"
|
"idiom": "iphone",
|
||||||
|
"scale": "2x",
|
||||||
|
"size": "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename": "Icon-App-40x40@3x.png",
|
"filename": "Icon-App-40x40@3x.png",
|
||||||
"scale" : "3x"
|
"idiom": "iphone",
|
||||||
|
"scale": "3x",
|
||||||
|
"size": "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "60x60",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename": "Icon-App-60x60@2x.png",
|
"filename": "Icon-App-60x60@2x.png",
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "60x60",
|
|
||||||
"idiom": "iphone",
|
"idiom": "iphone",
|
||||||
|
"scale": "2x",
|
||||||
|
"size": "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
"filename": "Icon-App-60x60@3x.png",
|
"filename": "Icon-App-60x60@3x.png",
|
||||||
"scale" : "3x"
|
"idiom": "iphone",
|
||||||
|
"scale": "3x",
|
||||||
|
"size": "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename": "Icon-App-20x20@1x.png",
|
"filename": "Icon-App-20x20@1x.png",
|
||||||
"scale" : "1x"
|
"idiom": "ipad",
|
||||||
|
"scale": "1x",
|
||||||
|
"size": "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename": "Icon-App-20x20@2x.png",
|
"filename": "Icon-App-20x20@2x.png",
|
||||||
"scale" : "2x"
|
"idiom": "ipad",
|
||||||
|
"scale": "2x",
|
||||||
|
"size": "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename": "Icon-App-29x29@1x.png",
|
"filename": "Icon-App-29x29@1x.png",
|
||||||
"scale" : "1x"
|
"idiom": "ipad",
|
||||||
|
"scale": "1x",
|
||||||
|
"size": "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename": "Icon-App-29x29@2x.png",
|
"filename": "Icon-App-29x29@2x.png",
|
||||||
"scale" : "2x"
|
"idiom": "ipad",
|
||||||
|
"scale": "2x",
|
||||||
|
"size": "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename": "Icon-App-40x40@1x.png",
|
"filename": "Icon-App-40x40@1x.png",
|
||||||
"scale" : "1x"
|
"idiom": "ipad",
|
||||||
|
"scale": "1x",
|
||||||
|
"size": "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename": "Icon-App-40x40@2x.png",
|
"filename": "Icon-App-40x40@2x.png",
|
||||||
"scale" : "2x"
|
"idiom": "ipad",
|
||||||
|
"scale": "2x",
|
||||||
|
"size": "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename": "Icon-App-76x76@1x.png",
|
"filename": "Icon-App-76x76@1x.png",
|
||||||
"scale" : "1x"
|
"idiom": "ipad",
|
||||||
|
"scale": "1x",
|
||||||
|
"size": "76x76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename": "Icon-App-76x76@2x.png",
|
"filename": "Icon-App-76x76@2x.png",
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "83.5x83.5",
|
|
||||||
"idiom": "ipad",
|
"idiom": "ipad",
|
||||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
"scale": "2x",
|
||||||
"scale" : "2x"
|
"size": "76x76"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "Icon-App-83.5x83.5@2x.png",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "2x",
|
||||||
|
"size": "83.5x83.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "1024x1024",
|
|
||||||
"idiom" : "ios-marketing",
|
|
||||||
"filename": "Icon-App-1024x1024@1x.png",
|
"filename": "Icon-App-1024x1024@1x.png",
|
||||||
"scale" : "1x"
|
"idiom": "ios-marketing",
|
||||||
|
"scale": "1x",
|
||||||
|
"size": "1024x1024"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info": {
|
"info": {
|
||||||
"version" : 1,
|
"author": "icons_launcher",
|
||||||
"author" : "xcode"
|
"version": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
Before Width: | Height: | Size: 500 KiB After Width: | Height: | Size: 452 KiB |
Before Width: | Height: | Size: 700 B After Width: | Height: | Size: 632 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 973 B |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 70 B After Width: | Height: | Size: 69 B |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 50 KiB |
@ -2,6 +2,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>FlutterDeepLinkingEnabled</key>
|
||||||
|
<true/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
@ -29,8 +31,6 @@
|
|||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>FLTEnableImpeller</key>
|
|
||||||
<false/>
|
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
@ -4,5 +4,9 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>aps-environment</key>
|
<key>aps-environment</key>
|
||||||
<string>development</string>
|
<string>development</string>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.com.gskinner.flutter.wonders.widget</string>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
6
ios/WonderousWidget/Assets.xcassets/Contents.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
11
ios/WonderousWidget/Colors.swift
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
/// Define some custom extensions on the Color class, so we can use the shorthand syntax `..myColor`
|
||||||
|
extension Color {
|
||||||
|
public static let accent = Color(red: 0.89, green: 0.58, blue: 0.36)
|
||||||
|
public static let offWhite = Color(red: 0.97, green: 0.92, blue: 0.9)
|
||||||
|
public static let mediumGrey = Color(red: 0.62, green: 0.6, blue: 0.58)
|
||||||
|
public static let darkGrey = Color(red: 0.15, green: 0.15, blue: 0.15)
|
||||||
|
public static let body = Color(red: 0.32, green: 0.31, blue: 0.3);
|
||||||
|
}
|
22
ios/WonderousWidget/FlutterAssets.swift
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct FlutterImages {
|
||||||
|
static let bgEmpty = getAssetPath("/assets/images/widget/background-empty.jpg")
|
||||||
|
static let icon = getAssetPath("/assets/images/widget/wonderous-icon.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAssetPath(_ path : String) -> String {
|
||||||
|
return assetBundleUrl.appending(path: path).path()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a file path to the location of the flutter assetBundle
|
||||||
|
var assetBundleUrl: URL {
|
||||||
|
let bundle = Bundle.main
|
||||||
|
if bundle.bundleURL.pathExtension == "appex" {
|
||||||
|
// Peel off two directory levels - MY_APP.app/PlugIns/MY_APP_EXTENSION.appex
|
||||||
|
var url = bundle.bundleURL.deletingLastPathComponent().deletingLastPathComponent()
|
||||||
|
url.append(component: "Frameworks/App.framework/flutter_assets")
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
return bundle.bundleURL
|
||||||
|
}
|
11
ios/WonderousWidget/FlutterUtils.swift
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// FlutterUtils.swift
|
||||||
|
// Wonderous WidgetExtension
|
||||||
|
//
|
||||||
|
// Created by Shawn on 2023-10-19.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
|
11
ios/WonderousWidget/Info.plist
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.widgetkit-extension</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
63
ios/WonderousWidget/WonderWidgetViewComponents.swift
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
|
||||||
|
// Loads a default image from the flutter assets bundle,
|
||||||
|
// or displays a base64 encoded image that has been saved from the flutter application
|
||||||
|
struct BgImage : View {
|
||||||
|
var entry: WonderousTimelineEntry
|
||||||
|
var body: some View {
|
||||||
|
var uiImage:UIImage?;
|
||||||
|
// If there is no saved imageData, use the default bg image
|
||||||
|
if(entry.imageData.isEmpty){
|
||||||
|
uiImage = UIImage(contentsOfFile: FlutterImages.bgEmpty);
|
||||||
|
}
|
||||||
|
// Load a base64 encoded image that has been written by the flutter app
|
||||||
|
else {
|
||||||
|
uiImage = UIImage(data: Data(base64Encoded: entry.imageData)!)
|
||||||
|
}
|
||||||
|
if(uiImage != nil){
|
||||||
|
// Use geometry reader to prevent an oversized bg image from pushing the other content out of the widgets bounds (https://stackoverflow.com/questions/57593552/swiftui-prevent-image-from-expanding-view-rect-outside-of-screen-bounds)
|
||||||
|
let image = GeometryReader { geometry in
|
||||||
|
Image(uiImage: uiImage!)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
.edgesIgnoringSafeArea(.all) // Ignore the safe area
|
||||||
|
.frame(maxWidth: geometry.size.width, maxHeight: geometry.size.height)
|
||||||
|
}
|
||||||
|
return AnyView(image)
|
||||||
|
}
|
||||||
|
debugPrint("The image file could not be loaded")
|
||||||
|
return AnyView(EmptyView())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declares a restyled version of the native ProgressView
|
||||||
|
struct GaugeProgressStyle: ProgressViewStyle {
|
||||||
|
func makeBody(configuration: Configuration) -> some View {
|
||||||
|
let fractionCompleted = configuration.fractionCompleted ?? 0
|
||||||
|
return ZStack {
|
||||||
|
Circle()
|
||||||
|
.stroke(Color.body, style: StrokeStyle(lineWidth: 2))
|
||||||
|
Circle()
|
||||||
|
.trim(from: 0, to: fractionCompleted)
|
||||||
|
.stroke(Color.accent, style: StrokeStyle(lineWidth: 4, lineCap: .round))
|
||||||
|
.rotationEffect(.degrees(90))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an extension to support new containerBackground API on
|
||||||
|
// iOS 17 while still supporting iOS 16 and less (https://nemecek.be/blog/192/hotfixing-widgets-for-ios-17-containerbackground-padding)
|
||||||
|
extension View {
|
||||||
|
func widgetBackground(_ backgroundView: some View) -> some View {
|
||||||
|
if #available(iOSApplicationExtension 17.0, iOS 17.0, macOSApplicationExtension 14.0, *) {
|
||||||
|
return containerBackground(for: .widget) {
|
||||||
|
backgroundView
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return background(backgroundView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
ios/WonderousWidget/WonderousWidget.intentdefinition
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>INEnums</key>
|
||||||
|
<array/>
|
||||||
|
<key>INIntentDefinitionModelVersion</key>
|
||||||
|
<string>1.2</string>
|
||||||
|
<key>INIntentDefinitionNamespace</key>
|
||||||
|
<string>88xZPY</string>
|
||||||
|
<key>INIntentDefinitionSystemVersion</key>
|
||||||
|
<string>20A294</string>
|
||||||
|
<key>INIntentDefinitionToolsBuildVersion</key>
|
||||||
|
<string>12A6144</string>
|
||||||
|
<key>INIntentDefinitionToolsVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
|
<key>INIntents</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>INIntentCategory</key>
|
||||||
|
<string>information</string>
|
||||||
|
<key>INIntentDescriptionID</key>
|
||||||
|
<string>tVvJ9c</string>
|
||||||
|
<key>INIntentEligibleForWidgets</key>
|
||||||
|
<true/>
|
||||||
|
<key>INIntentIneligibleForSuggestions</key>
|
||||||
|
<true/>
|
||||||
|
<key>INIntentName</key>
|
||||||
|
<string>Configuration</string>
|
||||||
|
<key>INIntentResponse</key>
|
||||||
|
<dict>
|
||||||
|
<key>INIntentResponseCodes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>INIntentResponseCodeName</key>
|
||||||
|
<string>success</string>
|
||||||
|
<key>INIntentResponseCodeSuccess</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>INIntentResponseCodeName</key>
|
||||||
|
<string>failure</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<key>INIntentTitle</key>
|
||||||
|
<string>Configuration</string>
|
||||||
|
<key>INIntentTitleID</key>
|
||||||
|
<string>gpCwrM</string>
|
||||||
|
<key>INIntentType</key>
|
||||||
|
<string>Custom</string>
|
||||||
|
<key>INIntentVerb</key>
|
||||||
|
<string>View</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>INTypes</key>
|
||||||
|
<array/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
72
ios/WonderousWidget/WonderousWidget.swift
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import WidgetKit
|
||||||
|
import SwiftUI
|
||||||
|
import Intents
|
||||||
|
|
||||||
|
/// Every home-widget requires a TimelineEntry. This is passed into the view and propvides any data it needs
|
||||||
|
struct WonderousTimelineEntry : TimelineEntry {
|
||||||
|
// Date is a mandatory field for all TimelineEntries
|
||||||
|
let date: Date
|
||||||
|
// Custom field for the wonderous view
|
||||||
|
let discoveredCount:Int;
|
||||||
|
var title:String = "";
|
||||||
|
var subTitle:String = "";
|
||||||
|
var imageData:String = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Widget, defines some high level configuration options as well as the primary view that will display the widget.
|
||||||
|
struct WonderousWidget: Widget {
|
||||||
|
let kind: String = "WonderousWidget"
|
||||||
|
var body: some WidgetConfiguration {
|
||||||
|
StaticConfiguration(kind: kind, provider: WonderousTimelineProvider()) { entry in
|
||||||
|
WonderousWidgetView(entry: entry)
|
||||||
|
}
|
||||||
|
.contentMarginsDisabled()
|
||||||
|
.configurationDisplayName("Wonderous Widget")
|
||||||
|
.description("Track your collected artifacts!")
|
||||||
|
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WonderousConfig {
|
||||||
|
let iosKey = "group.com.gskinner.flutter.wonders.widget"
|
||||||
|
let discoveredCountKey = "dicoveredCount"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TimelineProvider, returns various WonderousTimelineEntry configurations for different contexts
|
||||||
|
struct WonderousTimelineProvider: TimelineProvider {
|
||||||
|
// Provide an entry for a placeholder version of the widget
|
||||||
|
func placeholder(in context: Context) -> WonderousTimelineEntry {
|
||||||
|
WonderousTimelineEntry(date: Date(), discoveredCount: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide an entry for the current time and state of the widget
|
||||||
|
func getSnapshot(in context: Context, completion: @escaping (WonderousTimelineEntry) -> ()) {
|
||||||
|
let entry:WonderousTimelineEntry
|
||||||
|
let userDefaults = UserDefaults(suiteName: "group.com.gskinner.flutter.wonders.widget")
|
||||||
|
let discoveredCount = userDefaults?.integer(forKey: "discoveredCount") ?? 0
|
||||||
|
let title = userDefaults?.string(forKey: "lastDiscoveredTitle") ?? ""
|
||||||
|
let subTitle = userDefaults?.string(forKey: "lastDiscoveredSubTitle") ?? ""
|
||||||
|
let imageData = userDefaults?.string(forKey: "lastDiscoveredImageData") ?? ""
|
||||||
|
entry = WonderousTimelineEntry(
|
||||||
|
date: Date(),
|
||||||
|
discoveredCount:discoveredCount,
|
||||||
|
title: title,
|
||||||
|
subTitle: subTitle.prefix(1).capitalized + subTitle.dropFirst(),
|
||||||
|
imageData: imageData
|
||||||
|
)
|
||||||
|
completion(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide an array of entries for the current time and, optionally, any future times
|
||||||
|
func getTimeline(in context: Context, completion: @escaping (Timeline<WonderousTimelineEntry>) -> ()) {
|
||||||
|
getSnapshot(in: context) { (entry) in
|
||||||
|
let timeline = Timeline(entries: [entry], policy: .atEnd)
|
||||||
|
completion(timeline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
12
ios/WonderousWidget/WonderousWidgetBundle.swift
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import WidgetKit
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// WonderousWidgetBundle
|
||||||
|
// -> WonderousWidgetView
|
||||||
|
// -> WonderousWidgetViewComponents
|
||||||
|
@main
|
||||||
|
struct WonderousWidgetBundle: WidgetBundle {
|
||||||
|
var body: some Widget {
|
||||||
|
WonderousWidget()
|
||||||
|
}
|
||||||
|
}
|
76
ios/WonderousWidget/WonderousWidgetView.swift
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import WidgetKit
|
||||||
|
import SwiftUI
|
||||||
|
import Intents
|
||||||
|
|
||||||
|
/// Defines the view / layout of the widget
|
||||||
|
struct WonderousWidgetView : View {
|
||||||
|
@Environment(\.widgetFamily) var family: WidgetFamily
|
||||||
|
var entry: WonderousTimelineProvider.Entry
|
||||||
|
var body: some View {
|
||||||
|
let showTitle = family == .systemLarge
|
||||||
|
let showIcon = family != .systemSmall
|
||||||
|
let showTitleAndDesc = family != .systemSmall
|
||||||
|
let progressPct = Double(entry.discoveredCount) / 24.0
|
||||||
|
let iconImage = FlutterImages.icon;
|
||||||
|
let title = entry.title.isEmpty ? "Wonderous" : entry.title;
|
||||||
|
let subTitle = entry.subTitle.isEmpty ? "Search for hidden artifacts" : entry.subTitle;
|
||||||
|
|
||||||
|
let content = VStack{
|
||||||
|
// Top row with optional Title and Icon
|
||||||
|
HStack {
|
||||||
|
if(showTitle) {
|
||||||
|
Text("Collection")
|
||||||
|
.font(.system(size: 15))
|
||||||
|
.foregroundColor(.offWhite)
|
||||||
|
}
|
||||||
|
Spacer();
|
||||||
|
if(showIcon) {
|
||||||
|
Image(uiImage: UIImage(contentsOfFile: iconImage)!)
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(height: 24)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer();
|
||||||
|
|
||||||
|
// Bottom hz row with title, desc and progress gauge
|
||||||
|
HStack {
|
||||||
|
if(showTitleAndDesc) {
|
||||||
|
VStack(alignment: .leading){
|
||||||
|
Text(title)
|
||||||
|
.font(.system(size: 22))
|
||||||
|
.foregroundColor(.white);
|
||||||
|
Text(subTitle)
|
||||||
|
.font(.system(size: 15))
|
||||||
|
.foregroundColor(.mediumGrey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer();
|
||||||
|
ZStack{
|
||||||
|
ProgressView(value: progressPct)
|
||||||
|
.progressViewStyle(GaugeProgressStyle())
|
||||||
|
.frame(width: 48, height: 48)
|
||||||
|
|
||||||
|
Text("\(Int((progressPct * 100).rounded()))%").font(.system(size: 13)).foregroundColor(.white)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stack content on top of the background image and a gradient
|
||||||
|
return ZStack{
|
||||||
|
BgImage(entry: entry).opacity(0.8)
|
||||||
|
LinearGradient(
|
||||||
|
gradient: Gradient(colors: [.black.opacity(0), .black]),
|
||||||
|
startPoint: .center,
|
||||||
|
endPoint: .bottom)
|
||||||
|
content.padding(16)
|
||||||
|
}
|
||||||
|
// Ios requires that widgets have a background color
|
||||||
|
.widgetBackground(Color.darkGrey)
|
||||||
|
// Deeplink into collections view when tapped
|
||||||
|
.widgetURL(URL(string: "wonderous:///home/collection"))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
10
ios/WonderousWidgetExtension.entitlements
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.com.gskinner.flutter.wonders.widget</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
174
lib/_tools/artifact_download_helper.dart
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:image/image.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:wonders/logic/data/collectible_data.dart';
|
||||||
|
import 'package:wonders/logic/data/highlight_data.dart';
|
||||||
|
import 'package:wonders/logic/data/wonders_data/chichen_itza_data.dart';
|
||||||
|
import 'package:wonders/logic/data/wonders_data/christ_redeemer_data.dart';
|
||||||
|
import 'package:wonders/logic/data/wonders_data/great_wall_data.dart';
|
||||||
|
import 'package:wonders/logic/data/wonders_data/machu_picchu_data.dart';
|
||||||
|
import 'package:wonders/logic/data/wonders_data/petra_data.dart';
|
||||||
|
import 'package:wonders/logic/data/wonders_data/pyramids_giza_data.dart';
|
||||||
|
import 'package:wonders/logic/data/wonders_data/taj_mahal_data.dart';
|
||||||
|
import 'package:wonders/logic/data/wonders_data/colosseum_data.dart';
|
||||||
|
|
||||||
|
import 'package:wonders/common_libs.dart';
|
||||||
|
|
||||||
|
class ArtifactDownloadHelper extends StatefulWidget {
|
||||||
|
const ArtifactDownloadHelper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ArtifactDownloadHelper> createState() => _ArtifactDownloadHelperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Using collectiblesData fetch the data for each artifact and download the image.
|
||||||
|
/// Resize all images to have multiple sizes (small, medium, large)
|
||||||
|
/// Save images using format [ID].jpg and [ID].json
|
||||||
|
/// OR modify CollectibleData_helper.html to include all data in the collectiblesData list so no JSON is required.
|
||||||
|
class _ArtifactDownloadHelperState extends State<ArtifactDownloadHelper> {
|
||||||
|
late String imagesDir;
|
||||||
|
final http = Client();
|
||||||
|
final List<String> missingIds = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
createDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> createDirectory() async {
|
||||||
|
final rootDir = await getApplicationDocumentsDirectory();
|
||||||
|
imagesDir = '${rootDir.path}/met_collectibles';
|
||||||
|
await Directory(imagesDir).create(recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: downloadArtifacts,
|
||||||
|
child: Text('Download Artifacts'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void downloadArtifacts() async {
|
||||||
|
missingIds.clear();
|
||||||
|
|
||||||
|
/// Download collectibles
|
||||||
|
for (var c in collectiblesData) {
|
||||||
|
if (await downloadImageAndJson(c.artifactId) == false) {
|
||||||
|
missingIds.add(c.artifactId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Download Highights
|
||||||
|
for (var h in HighlightData.all) {
|
||||||
|
if (await downloadImageAndJson(h.artifactId) == false) {
|
||||||
|
missingIds.add(h.artifactId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Download search artifacts
|
||||||
|
final searchData = ChichenItzaData().searchData +
|
||||||
|
ChristRedeemerData().searchData +
|
||||||
|
ColosseumData().searchData +
|
||||||
|
GreatWallData().searchData +
|
||||||
|
MachuPicchuData().searchData +
|
||||||
|
PetraData().searchData +
|
||||||
|
PyramidsGizaData().searchData +
|
||||||
|
TajMahalData().searchData;
|
||||||
|
|
||||||
|
for (var a in searchData) {
|
||||||
|
final id = a.id.toString();
|
||||||
|
if (await downloadImageAndJson(id) == false) {
|
||||||
|
missingIds.add(id);
|
||||||
|
}
|
||||||
|
final index = searchData.indexOf(a) + 1;
|
||||||
|
if (index % 100 == 0) {
|
||||||
|
debugPrint('$index/${searchData.length}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debugPrint('Download complete :) Missing IDs: $missingIds');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> downloadImageAndJson(String id) async {
|
||||||
|
File jsonFile = File('$imagesDir/$id.json');
|
||||||
|
late Map json;
|
||||||
|
if (jsonFile.existsSync()) {
|
||||||
|
json = jsonDecode(jsonFile.readAsStringSync()) as Map;
|
||||||
|
} else {
|
||||||
|
debugPrint('Downloading $id');
|
||||||
|
// Fetch JSON for id
|
||||||
|
Uri uri = Uri.parse('https://collectionapi.metmuseum.org/public/collection/v1/objects/$id');
|
||||||
|
final response = await http.get(uri);
|
||||||
|
json = jsonDecode(response.body) as Map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if primaryImage field is valid
|
||||||
|
if (!json.containsKey('primaryImage') || json['primaryImage'].isEmpty) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Download image
|
||||||
|
final url = json['primaryImage'] as String;
|
||||||
|
//bool isPublicDomain = json['isPublicDomain'] as bool;
|
||||||
|
File imgFile = File('$imagesDir/$id.jpg');
|
||||||
|
// If image does not already exist, download it
|
||||||
|
if (!imgFile.existsSync()) {
|
||||||
|
await downloadImage(id, url);
|
||||||
|
if (!imgFile.existsSync()) return false;
|
||||||
|
}
|
||||||
|
// Try to resize image
|
||||||
|
if (await resizeImage(id, [600, 2000]) == false) {
|
||||||
|
debugPrint('Failed to resize $id');
|
||||||
|
imgFile.deleteSync();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Write JSON to file
|
||||||
|
if (!jsonFile.existsSync()) {
|
||||||
|
jsonFile.writeAsStringSync(jsonEncode(json));
|
||||||
|
debugPrint('json saved @ ${jsonFile.path}');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> downloadImage(String id, String url) async {
|
||||||
|
//final sizes = [400, 800, 1600, 3000];
|
||||||
|
debugPrint('Downloading $url to $imagesDir');
|
||||||
|
final imgResponse = await get(Uri.parse(url));
|
||||||
|
// If the image is less than a KB, it's probably a 404 image.
|
||||||
|
if (imgResponse.bodyBytes.lengthInBytes < 2000) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
File file = File('$imagesDir/$id.jpg');
|
||||||
|
file.writeAsBytesSync(imgResponse.bodyBytes);
|
||||||
|
debugPrint('img saved @ ${file.path}');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> resizeImage(String id, List<int> sizes) async {
|
||||||
|
final srcFile = File('$imagesDir/$id.jpg');
|
||||||
|
//debugPrint('Resizing $id...');
|
||||||
|
try {
|
||||||
|
final img = decodeJpg(srcFile.readAsBytesSync());
|
||||||
|
if (img != null) {
|
||||||
|
// Write various sizes to disk
|
||||||
|
for (var size in sizes) {
|
||||||
|
final resizedFile = File('$imagesDir/${id}_$size.jpg');
|
||||||
|
if (await resizedFile.exists()) continue;
|
||||||
|
final resizedImg = copyResize(img, width: size);
|
||||||
|
await resizedFile.writeAsBytes(encodeJpg(resizedImg, quality: 90));
|
||||||
|
debugPrint('Resized ${id}_$size');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Failed to resize $id');
|
||||||
|
debugPrint(e.toString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@ final int maxYear = wondersLogic.timelineEndYear;
|
|||||||
const int maxRequests = 32;
|
const int maxRequests = 32;
|
||||||
|
|
||||||
class ArtifactSearchHelper extends StatefulWidget {
|
class ArtifactSearchHelper extends StatefulWidget {
|
||||||
const ArtifactSearchHelper({Key? key}) : super(key: key);
|
const ArtifactSearchHelper({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ArtifactSearchHelper> createState() => _ArtifactSearchHelperState();
|
State<ArtifactSearchHelper> createState() => _ArtifactSearchHelperState();
|
||||||
@ -161,15 +161,19 @@ class _ArtifactSearchHelperState extends State<ArtifactSearchHelper> {
|
|||||||
//if (!json.containsKey('isPublicDomain') || !json['isPublicDomain']) return _logError(id, 'not public domain')
|
//if (!json.containsKey('isPublicDomain') || !json['isPublicDomain']) return _logError(id, 'not public domain')
|
||||||
|
|
||||||
final int year = ((json['objectBeginDate'] as int) + (json['objectEndDate'] as int)) ~/ 2;
|
final int year = ((json['objectBeginDate'] as int) + (json['objectEndDate'] as int)) ~/ 2;
|
||||||
if (year < minYear || year > maxYear) return _logError(id, 'year is out of range');
|
if (year < minYear || year > maxYear) {
|
||||||
|
return _logError(id, 'year is out of range');
|
||||||
|
}
|
||||||
|
|
||||||
String? imageUrlSmall = json['primaryImageSmall'];
|
String? imageUrlSmall = json['primaryImageSmall'];
|
||||||
if (imageUrlSmall == null) return _logError(id, 'no small image url');
|
if (imageUrlSmall == null || imageUrlSmall.isEmpty) {
|
||||||
if (!imageUrlSmall.startsWith(SearchData.baseImagePath)) {
|
return _logError(id, 'no small image url');
|
||||||
return _logError(id, 'unexpected image uri: "$imageUrlSmall"');
|
|
||||||
}
|
}
|
||||||
String imagePath = imageUrlSmall.substring(SearchData.baseImagePath.length);
|
// if (!imageUrlSmall.startsWith(SearchData.baseImagePath)) {
|
||||||
imagePath = imagePath.replaceFirst('/web-large/', '/mobile-large/');
|
// return _logError(id, 'unexpected image uri: "$imageUrlSmall"');
|
||||||
|
// }
|
||||||
|
// String imageUrl = imageUrlSmall.substring(SearchData.baseImagePath.length);
|
||||||
|
// imageUrl = imageUrl.replaceFirst('/web-large/', '/mobile-large/');
|
||||||
|
|
||||||
double? aspectRatio = 0;
|
double? aspectRatio = 0;
|
||||||
if (checkImages) aspectRatio = await _getAspectRatio(imageUrlSmall);
|
if (checkImages) aspectRatio = await _getAspectRatio(imageUrlSmall);
|
||||||
@ -180,7 +184,6 @@ class _ArtifactSearchHelperState extends State<ArtifactSearchHelper> {
|
|||||||
id,
|
id,
|
||||||
_escape(json['title']),
|
_escape(json['title']),
|
||||||
_getKeywords(json),
|
_getKeywords(json),
|
||||||
imagePath,
|
|
||||||
aspectRatio,
|
aspectRatio,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -229,12 +232,22 @@ class _ArtifactSearchHelperState extends State<ArtifactSearchHelper> {
|
|||||||
|
|
||||||
String suggestions = _getSuggestions(entries);
|
String suggestions = _getSuggestions(entries);
|
||||||
|
|
||||||
|
const fileNames = {
|
||||||
|
WonderType.chichenItza: 'chichen_itza',
|
||||||
|
WonderType.christRedeemer: 'christ_redeemer',
|
||||||
|
WonderType.colosseum: 'colosseum',
|
||||||
|
WonderType.greatWall: 'great_wall',
|
||||||
|
WonderType.machuPicchu: 'machu_picchu',
|
||||||
|
WonderType.petra: 'petra',
|
||||||
|
WonderType.pyramidsGiza: 'pyramids_giza',
|
||||||
|
WonderType.tajMahal: 'taj_mahal',
|
||||||
|
};
|
||||||
Directory dir = await getApplicationDocumentsDirectory();
|
Directory dir = await getApplicationDocumentsDirectory();
|
||||||
String type = wonder!.type.toString().split('.').last;
|
String name = '${fileNames[wonder!.type]}_search_data.dart';
|
||||||
String path = '${dir.path}/$type.dart';
|
String path = '${dir.path}/$name';
|
||||||
File file = File(path);
|
File file = File(path);
|
||||||
await file.writeAsString('$suggestions\n\n$output');
|
await file.writeAsString('$suggestions\n\n$output');
|
||||||
_log('- Wrote file: $type.dart');
|
_log('- Wrote file: $name');
|
||||||
debugPrint(path);
|
debugPrint(path);
|
||||||
_nextWonder();
|
_nextWonder();
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,9 @@ class ImagePaths {
|
|||||||
|
|
||||||
static String textures = '$common/texture';
|
static String textures = '$common/texture';
|
||||||
static String icons = '$common/icons';
|
static String icons = '$common/icons';
|
||||||
static String speckles = '$textures/speckles-white.png';
|
|
||||||
static String roller1 = '$textures/roller-1-white.png';
|
static String roller1 = '$textures/roller-1-white.gif';
|
||||||
static String roller2 = '$textures/roller-2-white.png';
|
static String roller2 = '$textures/roller-2-white.gif';
|
||||||
|
|
||||||
static String appLogo = '$common/app-logo.png';
|
static String appLogo = '$common/app-logo.png';
|
||||||
static String appLogoPlain = '$common/app-logo-plain.png';
|
static String appLogoPlain = '$common/app-logo-plain.png';
|
||||||
@ -43,24 +43,16 @@ class SvgPaths {
|
|||||||
/// For wonder specific assets, add an extension to [WonderType] for easy lookup
|
/// For wonder specific assets, add an extension to [WonderType] for easy lookup
|
||||||
extension WonderAssetExtensions on WonderType {
|
extension WonderAssetExtensions on WonderType {
|
||||||
String get assetPath {
|
String get assetPath {
|
||||||
switch (this) {
|
return switch (this) {
|
||||||
case WonderType.pyramidsGiza:
|
WonderType.pyramidsGiza => '${ImagePaths.root}/pyramids',
|
||||||
return '${ImagePaths.root}/pyramids';
|
WonderType.greatWall => '${ImagePaths.root}/great_wall_of_china',
|
||||||
case WonderType.greatWall:
|
WonderType.petra => '${ImagePaths.root}/petra',
|
||||||
return '${ImagePaths.root}/great_wall_of_china';
|
WonderType.colosseum => '${ImagePaths.root}/colosseum',
|
||||||
case WonderType.petra:
|
WonderType.chichenItza => '${ImagePaths.root}/chichen_itza',
|
||||||
return '${ImagePaths.root}/petra';
|
WonderType.machuPicchu => '${ImagePaths.root}/machu_picchu',
|
||||||
case WonderType.colosseum:
|
WonderType.tajMahal => '${ImagePaths.root}/taj_mahal',
|
||||||
return '${ImagePaths.root}/colosseum';
|
WonderType.christRedeemer => '${ImagePaths.root}/christ_the_redeemer'
|
||||||
case WonderType.chichenItza:
|
};
|
||||||
return '${ImagePaths.root}/chichen_itza';
|
|
||||||
case WonderType.machuPicchu:
|
|
||||||
return '${ImagePaths.root}/machu_picchu';
|
|
||||||
case WonderType.tajMahal:
|
|
||||||
return '${ImagePaths.root}/taj_mahal';
|
|
||||||
case WonderType.christRedeemer:
|
|
||||||
return '${ImagePaths.root}/christ_the_redeemer';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String get homeBtn => '$assetPath/wonder-button.png';
|
String get homeBtn => '$assetPath/wonder-button.png';
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/// Consolidate imports that are common across the app.
|
/// Consolidate imports that are common across the app.
|
||||||
|
library;
|
||||||
|
|
||||||
export 'dart:math';
|
export 'dart:math';
|
||||||
|
|
||||||
@ -14,7 +15,6 @@ export 'package:get_it_mixin/get_it_mixin.dart';
|
|||||||
export 'package:go_router/go_router.dart';
|
export 'package:go_router/go_router.dart';
|
||||||
export 'package:provider/provider.dart';
|
export 'package:provider/provider.dart';
|
||||||
export 'package:rnd/rnd.dart';
|
export 'package:rnd/rnd.dart';
|
||||||
export 'package:simple_rich_text/simple_rich_text.dart';
|
|
||||||
export 'package:sized_context/sized_context.dart';
|
export 'package:sized_context/sized_context.dart';
|
||||||
export 'package:wonders/assets.dart';
|
export 'package:wonders/assets.dart';
|
||||||
export 'package:wonders/logic/app_logic.dart';
|
export 'package:wonders/logic/app_logic.dart';
|
||||||
|
@ -145,7 +145,7 @@
|
|||||||
"chichenItzaCallout2": "The city comprised an area of at least 1.9 sq miles (5 sq km) of densely clustered architecture.",
|
"chichenItzaCallout2": "The city comprised an area of at least 1.9 sq miles (5 sq km) of densely clustered architecture.",
|
||||||
"chichenItzaVideoCaption": "“Ancient Maya 101 | National Geographic.” Youtube, uploaded by National Geographic.",
|
"chichenItzaVideoCaption": "“Ancient Maya 101 | National Geographic.” Youtube, uploaded by National Geographic.",
|
||||||
"chichenItzaMapCaption": "Map showing location of Chichen Itza in Yucatán State, Mexico.",
|
"chichenItzaMapCaption": "Map showing location of Chichen Itza in Yucatán State, Mexico.",
|
||||||
"chichenItzaHistoryInfo1": "Chichen Itza was a powerful regional capital controlling north and central Yucatán. The earliest hieroglyphic date discovered at Chichen Itza is equivalent to 832 CE, while the last known date was recorded in the Osario temple in 998 CE.\nDominating the North Platform of Chichen Itza is the famous Temple of Kukulcán. The temple was identified by the first Spaniards to see it, as El Castillo (\"the castle\"), and it regularly is referred to as such. The temple was identified by the first Spaniards to see it, as El Castillo (\"the castle\"), and it regularly is referred to as such.",
|
"chichenItzaHistoryInfo1": "Chichen Itza was a powerful regional capital controlling north and central Yucatán. The earliest hieroglyphic date discovered at Chichen Itza is equivalent to 832 CE, while the last known date was recorded in the Osario temple in 998 CE.\nDominating the North Platform of Chichen Itza is the famous Temple of Kukulcán. The temple was identified by the first Spaniards to see it, as El Castillo (\"the castle\"), and it regularly is referred to as such.",
|
||||||
"chichenItzaHistoryInfo2": "The city was thought to have the most diverse population in the Maya world, a factor that could have contributed to this architectural variety.",
|
"chichenItzaHistoryInfo2": "The city was thought to have the most diverse population in the Maya world, a factor that could have contributed to this architectural variety.",
|
||||||
"chichenItzaConstructionInfo1": "The structures of Chichen Itza were built from precisely chiseled limestone blocks that fit together perfectly without the mortar. Many of these stone buildings were originally painted in red, green, blue and purple colors depending on the availability of the pigments.\nThe stepped pyramid El Castillo stands about 98 feet (30 m) high and consists of a series of nine square terraces, each approximately 8.4 feet (2.57 m) high, with a 20 foot (6 m) high temple upon the summit.",
|
"chichenItzaConstructionInfo1": "The structures of Chichen Itza were built from precisely chiseled limestone blocks that fit together perfectly without the mortar. Many of these stone buildings were originally painted in red, green, blue and purple colors depending on the availability of the pigments.\nThe stepped pyramid El Castillo stands about 98 feet (30 m) high and consists of a series of nine square terraces, each approximately 8.4 feet (2.57 m) high, with a 20 foot (6 m) high temple upon the summit.",
|
||||||
"chichenItzaConstructionInfo2": "It was built upon broken terrain, which was artificially leveled to support structures such as the Castillo pyramid. Important buildings within the center were connected by a dense network of paved roads called sacbeob.",
|
"chichenItzaConstructionInfo2": "It was built upon broken terrain, which was artificially leveled to support structures such as the Castillo pyramid. Important buildings within the center were connected by a dense network of paved roads called sacbeob.",
|
||||||
@ -427,5 +427,7 @@
|
|||||||
"timelineEvent1969ce": "Apollo 11 mission lands on the moon",
|
"timelineEvent1969ce": "Apollo 11 mission lands on the moon",
|
||||||
"privacyPolicy": "Privacy Policy",
|
"privacyPolicy": "Privacy Policy",
|
||||||
"privacyStatement": "As explained in our {privacyUrl} we do not collect any personal information.",
|
"privacyStatement": "As explained in our {privacyUrl} we do not collect any personal information.",
|
||||||
"@privacyStatement": {"placeholders": {"privacyUrl": {}}}
|
"@privacyStatement": {"placeholders": {"privacyUrl": {}}},
|
||||||
|
"pageNotFoundBackButton": "Back to civilization",
|
||||||
|
"pageNotFoundMessage": "The page you are looking for does not exist."
|
||||||
}
|
}
|
@ -405,5 +405,7 @@
|
|||||||
"timelineEvent1957ce": "苏联发射斯普特尼克1号",
|
"timelineEvent1957ce": "苏联发射斯普特尼克1号",
|
||||||
"timelineEvent1969ce": "阿波罗11号在月球着陆",
|
"timelineEvent1969ce": "阿波罗11号在月球着陆",
|
||||||
"privacyPolicy": "隐私政策",
|
"privacyPolicy": "隐私政策",
|
||||||
"privacyStatement": "gskinner 非常重视对用户隐私的保护,正如{privacyUrl}里所诉,gskinner 不会收集您的个人信息。"
|
"privacyStatement": "gskinner 非常重视对用户隐私的保护,正如{privacyUrl}里所诉,gskinner 不会收集您的个人信息。",
|
||||||
|
"pageNotFoundBackButton": "回到文明",
|
||||||
|
"pageNotFoundMessage": "您正在寻找的页面不存在"
|
||||||
}
|
}
|
@ -1,45 +1,54 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:desktop_window/desktop_window.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/logic/common/platform_info.dart';
|
import 'package:wonders/logic/common/platform_info.dart';
|
||||||
|
import 'package:wonders/ui/common/modals/fullscreen_video_viewer.dart';
|
||||||
import 'package:wonders/ui/common/utils/page_routes.dart';
|
import 'package:wonders/ui/common/utils/page_routes.dart';
|
||||||
|
|
||||||
class AppLogic {
|
class AppLogic {
|
||||||
|
Size _appSize = Size.zero;
|
||||||
|
|
||||||
/// Indicates to the rest of the app that bootstrap has not completed.
|
/// Indicates to the rest of the app that bootstrap has not completed.
|
||||||
/// The router will use this to prevent redirects while bootstrapping.
|
/// The router will use this to prevent redirects while bootstrapping.
|
||||||
bool isBootstrapComplete = false;
|
bool isBootstrapComplete = false;
|
||||||
|
|
||||||
bool get isLandscapeEnabled => PlatformInfo.isDesktopOrWeb || deviceSize.shortestSide > 500;
|
/// Indicates which orientations the app will allow be default. Affects Android/iOS devices only.
|
||||||
|
/// Defaults to both landscape (hz) and portrait (vt)
|
||||||
|
List<Axis> supportedOrientations = [Axis.vertical, Axis.horizontal];
|
||||||
|
|
||||||
/// Support portrait and landscape on desktop, web and tablets. Stick to portrait for phones.
|
/// Allow a view to override the currently supported orientations. For example, [FullscreenVideoViewer] always wants to enable both landscape and portrait.
|
||||||
/// A return value of null indicated both orientations are supported.
|
/// If a view sets this override, they are responsible for setting it back to null when finished.
|
||||||
Axis? get supportedOrientations => isLandscapeEnabled ? null : Axis.vertical;
|
List<Axis>? _supportedOrientationsOverride;
|
||||||
|
set supportedOrientationsOverride(List<Axis>? value) {
|
||||||
Size get deviceSize {
|
if (_supportedOrientationsOverride != value) {
|
||||||
final w = WidgetsBinding.instance.platformDispatcher.views.first;
|
_supportedOrientationsOverride = value;
|
||||||
return w.physicalSize / w.devicePixelRatio;
|
_updateSystemOrientation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the app and all main actors.
|
/// Initialize the app and all main actors.
|
||||||
/// Loads settings, sets up services etc.
|
/// Loads settings, sets up services etc.
|
||||||
Future<void> bootstrap() async {
|
Future<void> bootstrap() async {
|
||||||
debugPrint('bootstrap app, deviceSize: $deviceSize, isTablet: $isLandscapeEnabled');
|
debugPrint('bootstrap start...');
|
||||||
|
|
||||||
// Set min-sizes for desktop apps
|
if (kIsWeb) {
|
||||||
if (PlatformInfo.isDesktop) {
|
// SB: This is intentionally not a debugPrint, as it's a message for users who open the console on web.
|
||||||
await DesktopWindow.setMinWindowSize($styles.sizes.minAppSize);
|
print(
|
||||||
|
'''Thanks for checking out Wonderous on the web!
|
||||||
|
If you encounter any issues please report them at https://github.com/gskinnerTeam/flutter-wonderous-app/issues.''',
|
||||||
|
);
|
||||||
|
// Required on web to automatically enable accessibility features
|
||||||
|
WidgetsFlutterBinding.ensureInitialized().ensureSemantics();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load any bitmaps the views might need
|
// Load any bitmaps the views might need
|
||||||
await AppBitmaps.init();
|
await AppBitmaps.init();
|
||||||
|
|
||||||
// Set the initial supported orientations
|
|
||||||
setDeviceOrientation(supportedOrientations);
|
|
||||||
|
|
||||||
// Set preferred refresh rate to the max possible (the OS may ignore this)
|
// Set preferred refresh rate to the max possible (the OS may ignore this)
|
||||||
if (PlatformInfo.isAndroid) {
|
if (!kIsWeb && PlatformInfo.isAndroid) {
|
||||||
await FlutterDisplayMode.setHighRefreshRate();
|
await FlutterDisplayMode.setHighRefreshRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +65,7 @@ class AppLogic {
|
|||||||
timelineLogic.init();
|
timelineLogic.init();
|
||||||
|
|
||||||
// Collectibles
|
// Collectibles
|
||||||
|
collectiblesLogic.init();
|
||||||
await collectiblesLogic.load();
|
await collectiblesLogic.load();
|
||||||
|
|
||||||
// Flag bootStrap as complete
|
// Flag bootStrap as complete
|
||||||
@ -66,30 +76,53 @@ class AppLogic {
|
|||||||
if (showIntro) {
|
if (showIntro) {
|
||||||
appRouter.go(ScreenPaths.intro);
|
appRouter.go(ScreenPaths.intro);
|
||||||
} else {
|
} else {
|
||||||
appRouter.go(ScreenPaths.home);
|
appRouter.go(initialDeeplink ?? ScreenPaths.home);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDeviceOrientation(Axis? axis) {
|
|
||||||
final orientations = <DeviceOrientation>[];
|
|
||||||
if (axis == null || axis == Axis.vertical) {
|
|
||||||
orientations.addAll([
|
|
||||||
DeviceOrientation.portraitUp,
|
|
||||||
DeviceOrientation.portraitDown,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
if (axis == null || axis == Axis.horizontal) {
|
|
||||||
orientations.addAll([
|
|
||||||
DeviceOrientation.landscapeLeft,
|
|
||||||
DeviceOrientation.landscapeRight,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
SystemChrome.setPreferredOrientations(orientations);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<T?> showFullscreenDialogRoute<T>(BuildContext context, Widget child, {bool transparent = false}) async {
|
Future<T?> showFullscreenDialogRoute<T>(BuildContext context, Widget child, {bool transparent = false}) async {
|
||||||
return await Navigator.of(context).push<T>(
|
return await Navigator.of(context).push<T>(
|
||||||
PageRoutes.dialog<T>(child, duration: $styles.times.pageTransition),
|
PageRoutes.dialog<T>(child, duration: $styles.times.pageTransition),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Called from the UI layer once a MediaQuery has been obtained
|
||||||
|
void handleAppSizeChanged(Size appSize) {
|
||||||
|
/// Disable landscape layout on smaller form factors
|
||||||
|
bool isSmall = display.size.shortestSide / display.devicePixelRatio < 600;
|
||||||
|
supportedOrientations = isSmall ? [Axis.vertical] : [Axis.vertical, Axis.horizontal];
|
||||||
|
_updateSystemOrientation();
|
||||||
|
_appSize = appSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Display get display => PlatformDispatcher.instance.displays.first;
|
||||||
|
|
||||||
|
bool shouldUseNavRail() => _appSize.width > _appSize.height && _appSize.height > 250;
|
||||||
|
|
||||||
|
void _updateSystemOrientation() {
|
||||||
|
final axisList = _supportedOrientationsOverride ?? supportedOrientations;
|
||||||
|
//debugPrint('updateDeviceOrientation, supportedAxis: $axisList');
|
||||||
|
final orientations = <DeviceOrientation>[];
|
||||||
|
if (axisList.contains(Axis.vertical)) {
|
||||||
|
orientations.addAll([
|
||||||
|
DeviceOrientation.portraitUp,
|
||||||
|
DeviceOrientation.portraitDown,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (axisList.contains(Axis.horizontal)) {
|
||||||
|
orientations.addAll([
|
||||||
|
DeviceOrientation.landscapeLeft,
|
||||||
|
DeviceOrientation.landscapeRight,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
SystemChrome.setPreferredOrientations(orientations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppImageCache extends WidgetsFlutterBinding {
|
||||||
|
@override
|
||||||
|
ImageCache createImageCache() {
|
||||||
|
this.imageCache.maximumSizeBytes = 250 << 20; // 250mb
|
||||||
|
return super.createImageCache();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,18 @@ import 'dart:collection';
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/logic/common/http_client.dart';
|
import 'package:wonders/logic/common/http_client.dart';
|
||||||
import 'package:wonders/logic/data/artifact_data.dart';
|
import 'package:wonders/logic/data/artifact_data.dart';
|
||||||
import 'package:wonders/logic/met_api_service.dart';
|
import 'package:wonders/logic/artifact_api_service.dart';
|
||||||
|
|
||||||
class MetAPILogic {
|
class ArtifactAPILogic {
|
||||||
final HashMap<String, ArtifactData?> _artifactCache = HashMap();
|
final HashMap<String, ArtifactData?> _artifactCache = HashMap();
|
||||||
|
|
||||||
MetAPIService get service => GetIt.I.get<MetAPIService>();
|
ArtifactAPIService get service => GetIt.I.get<ArtifactAPIService>();
|
||||||
|
|
||||||
/// Returns artifact data by ID. Returns null if artifact cannot be found. */
|
/// Returns artifact data by ID. Returns null if artifact cannot be found. */
|
||||||
Future<ArtifactData?> getArtifactByID(String id) async {
|
Future<ArtifactData?> getArtifactByID(String id, {bool selfHosted = false}) async {
|
||||||
if (_artifactCache.containsKey(id)) return _artifactCache[id];
|
if (_artifactCache.containsKey(id)) return _artifactCache[id];
|
||||||
ServiceResult<ArtifactData?> result = (await service.getObjectByID(id));
|
ServiceResult<ArtifactData?> result =
|
||||||
|
(await (selfHosted ? service.getSelfHostedObjectByID(id) : service.getMetObjectByID(id)));
|
||||||
if (!result.success) throw $strings.artifactDetailsErrorNotFound(id);
|
if (!result.success) throw $strings.artifactDetailsErrorNotFound(id);
|
||||||
ArtifactData? artifact = result.content;
|
ArtifactData? artifact = result.content;
|
||||||
return _artifactCache[id] = artifact;
|
return _artifactCache[id] = artifact;
|
@ -1,14 +1,20 @@
|
|||||||
import 'package:wonders/logic/common/http_client.dart';
|
import 'package:wonders/logic/common/http_client.dart';
|
||||||
import 'package:wonders/logic/data/artifact_data.dart';
|
import 'package:wonders/logic/data/artifact_data.dart';
|
||||||
|
|
||||||
class MetAPIService {
|
class ArtifactAPIService {
|
||||||
final String _baseMETUrl = 'https://collectionapi.metmuseum.org/public/collection/v1';
|
final String _baseMETUrl = 'https://collectionapi.metmuseum.org/public/collection/v1';
|
||||||
|
final String _baseSelfHostedUrl = 'https://www.wonderous.info/met';
|
||||||
|
|
||||||
Future<ServiceResult<ArtifactData?>> getObjectByID(String id) async {
|
Future<ServiceResult<ArtifactData?>> getMetObjectByID(String id) async {
|
||||||
HttpResponse? response = await HttpClient.send('$_baseMETUrl/objects/$id');
|
HttpResponse? response = await HttpClient.send('$_baseMETUrl/objects/$id');
|
||||||
return ServiceResult<ArtifactData?>(response, _parseArtifactData);
|
return ServiceResult<ArtifactData?>(response, _parseArtifactData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<ServiceResult<ArtifactData?>> getSelfHostedObjectByID(String id) async {
|
||||||
|
HttpResponse? response = await HttpClient.send('$_baseSelfHostedUrl/$id.json');
|
||||||
|
return ServiceResult<ArtifactData?>(response, _parseArtifactData);
|
||||||
|
}
|
||||||
|
|
||||||
ArtifactData? _parseArtifactData(Map<String, dynamic> content) {
|
ArtifactData? _parseArtifactData(Map<String, dynamic> content) {
|
||||||
// Source: https://metmuseum.github.io/
|
// Source: https://metmuseum.github.io/
|
||||||
return ArtifactData(
|
return ArtifactData(
|
@ -1,6 +1,10 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
import 'package:wonders/logic/common/save_load_mixin.dart';
|
import 'package:wonders/logic/common/save_load_mixin.dart';
|
||||||
import 'package:wonders/logic/data/collectible_data.dart';
|
import 'package:wonders/logic/data/collectible_data.dart';
|
||||||
|
import 'package:wonders/logic/native_widget_service.dart';
|
||||||
|
|
||||||
class CollectiblesLogic with ThrottledSaveLoadMixin {
|
class CollectiblesLogic with ThrottledSaveLoadMixin {
|
||||||
@override
|
@override
|
||||||
@ -13,11 +17,17 @@ class CollectiblesLogic with ThrottledSaveLoadMixin {
|
|||||||
late final statesById = ValueNotifier<Map<String, int>>({})..addListener(_updateCounts);
|
late final statesById = ValueNotifier<Map<String, int>>({})..addListener(_updateCounts);
|
||||||
|
|
||||||
int _discoveredCount = 0;
|
int _discoveredCount = 0;
|
||||||
|
|
||||||
int get discoveredCount => _discoveredCount;
|
int get discoveredCount => _discoveredCount;
|
||||||
|
|
||||||
int _exploredCount = 0;
|
int _exploredCount = 0;
|
||||||
|
|
||||||
int get exploredCount => _exploredCount;
|
int get exploredCount => _exploredCount;
|
||||||
|
|
||||||
|
late final _nativeWidget = GetIt.I<NativeWidgetService>();
|
||||||
|
|
||||||
|
void init() => _nativeWidget.init();
|
||||||
|
|
||||||
CollectibleData? fromId(String? id) => id == null ? null : all.firstWhereOrNull((o) => o.id == id);
|
CollectibleData? fromId(String? id) => id == null ? null : all.firstWhereOrNull((o) => o.id == id);
|
||||||
|
|
||||||
List<CollectibleData> forWonder(WonderType wonder) {
|
List<CollectibleData> forWonder(WonderType wonder) {
|
||||||
@ -28,6 +38,14 @@ class CollectiblesLogic with ThrottledSaveLoadMixin {
|
|||||||
Map<String, int> states = Map.of(statesById.value);
|
Map<String, int> states = Map.of(statesById.value);
|
||||||
states[id] = state;
|
states[id] = state;
|
||||||
statesById.value = states;
|
statesById.value = states;
|
||||||
|
if (state == CollectibleState.discovered) {
|
||||||
|
final data = fromId(id)!;
|
||||||
|
_updateNativeHomeWidgetData(
|
||||||
|
title: data.title,
|
||||||
|
id: data.id,
|
||||||
|
imageUrl: data.imageUrlSmall,
|
||||||
|
);
|
||||||
|
}
|
||||||
scheduleSave();
|
scheduleSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +55,12 @@ class CollectiblesLogic with ThrottledSaveLoadMixin {
|
|||||||
if (state == CollectibleState.discovered) _discoveredCount++;
|
if (state == CollectibleState.discovered) _discoveredCount++;
|
||||||
if (state == CollectibleState.explored) _exploredCount++;
|
if (state == CollectibleState.explored) _exploredCount++;
|
||||||
});
|
});
|
||||||
|
final foundCount = discoveredCount + exploredCount;
|
||||||
|
_nativeWidget.save<int>('discoveredCount', foundCount).then((value) {
|
||||||
|
_nativeWidget.markDirty();
|
||||||
|
});
|
||||||
|
|
||||||
|
debugPrint('setting discoveredCount for home widget $foundCount');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a discovered item, sorted by the order of wondersLogic.all
|
/// Get a discovered item, sorted by the order of wondersLogic.all
|
||||||
@ -67,11 +91,35 @@ class CollectiblesLogic with ThrottledSaveLoadMixin {
|
|||||||
for (int i = 0; i < all.length; i++) {
|
for (int i = 0; i < all.length; i++) {
|
||||||
states[all[i].id] = CollectibleState.lost;
|
states[all[i].id] = CollectibleState.lost;
|
||||||
}
|
}
|
||||||
|
_updateNativeHomeWidgetData(); // clear home widget data
|
||||||
statesById.value = states;
|
statesById.value = states;
|
||||||
debugPrint('collection reset');
|
debugPrint('collection reset');
|
||||||
scheduleSave();
|
scheduleSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _updateNativeHomeWidgetData({String title = '', String id = '', String imageUrl = ''}) async {
|
||||||
|
if (!_nativeWidget.isSupported) return;
|
||||||
|
// Save title
|
||||||
|
await _nativeWidget.save<String>('lastDiscoveredTitle', title);
|
||||||
|
// Subtitle
|
||||||
|
String subTitle = '';
|
||||||
|
if (id.isNotEmpty) {
|
||||||
|
final artifactData = await artifactLogic.getArtifactByID(id);
|
||||||
|
subTitle = artifactData?.date ?? '';
|
||||||
|
}
|
||||||
|
await _nativeWidget.save<String>('lastDiscoveredSubTitle', subTitle);
|
||||||
|
// Image,
|
||||||
|
// Download, convert to base64 string and write to shared widget data
|
||||||
|
String imageBase64 = '';
|
||||||
|
if (imageUrl.isNotEmpty) {
|
||||||
|
var bytes = await http.readBytes(Uri.parse(imageUrl));
|
||||||
|
imageBase64 = base64Encode(bytes);
|
||||||
|
debugPrint('Saving base64 bytes for homeWidget');
|
||||||
|
}
|
||||||
|
await _nativeWidget.save<String>('lastDiscoveredImageData', imageBase64);
|
||||||
|
await _nativeWidget.markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void copyFromJson(Map<String, dynamic> value) {
|
void copyFromJson(Map<String, dynamic> value) {
|
||||||
Map<String, int> states = {};
|
Map<String, int> states = {};
|
||||||
|
@ -94,7 +94,7 @@ class ServiceResult<R> {
|
|||||||
ServiceResult(this.response, R Function(Map<String, dynamic>) parser) {
|
ServiceResult(this.response, R Function(Map<String, dynamic>) parser) {
|
||||||
if (StringUtils.isNotEmpty(response.body) && response.success) {
|
if (StringUtils.isNotEmpty(response.body) && response.success) {
|
||||||
try {
|
try {
|
||||||
content = parser.call(jsonDecode(response.body!));
|
content = parser.call(jsonDecode(utf8.decode(response.raw!.bodyBytes)));
|
||||||
} on FormatException catch (e) {
|
} on FormatException catch (e) {
|
||||||
dev.log('ParseError: ${e.message}');
|
dev.log('ParseError: ${e.message}');
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ class PlatformInfo {
|
|||||||
static bool get isDesktopOrWeb => isDesktop || kIsWeb;
|
static bool get isDesktopOrWeb => isDesktop || kIsWeb;
|
||||||
static bool get isMobile => _mobilePlatforms.contains(defaultTargetPlatform) && !kIsWeb;
|
static bool get isMobile => _mobilePlatforms.contains(defaultTargetPlatform) && !kIsWeb;
|
||||||
|
|
||||||
static double get pixelRatio => WidgetsBinding.instance.window.devicePixelRatio;
|
static double get pixelRatio => WidgetsBinding.instance.platformDispatcher.views.first.devicePixelRatio;
|
||||||
|
|
||||||
static bool get isWindows => defaultTargetPlatform == TargetPlatform.windows;
|
static bool get isWindows => defaultTargetPlatform == TargetPlatform.windows;
|
||||||
static bool get isLinux => defaultTargetPlatform == TargetPlatform.linux;
|
static bool get isLinux => defaultTargetPlatform == TargetPlatform.linux;
|
||||||
|
@ -49,9 +49,10 @@ class RetryImage extends ImageProvider<Object> {
|
|||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageStreamCompleter _commonLoad(ImageStreamCompleter Function() loader) {
|
@override
|
||||||
|
ImageStreamCompleter loadImage(Object key, ImageDecoderCallback decode) {
|
||||||
final _DelegatingImageStreamCompleter completer = _DelegatingImageStreamCompleter();
|
final _DelegatingImageStreamCompleter completer = _DelegatingImageStreamCompleter();
|
||||||
ImageStreamCompleter completerToWrap = loader();
|
ImageStreamCompleter completerToWrap = imageProvider.loadImage(key, decode);
|
||||||
late ImageStreamListener listener;
|
late ImageStreamListener listener;
|
||||||
|
|
||||||
Duration duration = const Duration(milliseconds: 250);
|
Duration duration = const Duration(milliseconds: 250);
|
||||||
@ -69,7 +70,7 @@ class RetryImage extends ImageProvider<Object> {
|
|||||||
}
|
}
|
||||||
Future<void>.delayed(duration).then((void v) {
|
Future<void>.delayed(duration).then((void v) {
|
||||||
duration *= 2;
|
duration *= 2;
|
||||||
completerToWrap = loader();
|
completerToWrap = imageProvider.loadImage(key, decode);
|
||||||
count += 1;
|
count += 1;
|
||||||
completerToWrap.addListener(listener);
|
completerToWrap.addListener(listener);
|
||||||
});
|
});
|
||||||
@ -84,24 +85,12 @@ class RetryImage extends ImageProvider<Object> {
|
|||||||
return completer;
|
return completer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
// ignore: deprecated_member_use
|
|
||||||
ImageStreamCompleter load(Object key, DecoderCallback decode) {
|
|
||||||
// ignore: deprecated_member_use
|
|
||||||
return _commonLoad(() => imageProvider.load(key, decode));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
ImageStreamCompleter loadBuffer(Object key, DecoderBufferCallback decode) {
|
|
||||||
return _commonLoad(() => imageProvider.loadBuffer(key, decode));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
if (other.runtimeType != runtimeType) {
|
if (other.runtimeType != runtimeType) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return other is RetryImage && other.imageProvider == other.imageProvider && other.scale == scale;
|
return other is RetryImage && other.imageProvider == imageProvider && other.scale == scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -16,7 +16,7 @@ mixin ThrottledSaveLoadMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> save() async {
|
Future<void> save() async {
|
||||||
debugPrint('Saving...');
|
if (!kIsWeb) debugPrint('Saving...');
|
||||||
try {
|
try {
|
||||||
await _file.save(toJson());
|
await _file.save(toJson());
|
||||||
} on Exception catch (e) {
|
} on Exception catch (e) {
|
||||||
|