Compare commits

..

13 Commits

Author SHA1 Message Date
Jose Olarte III
bb2a4ab76e URL scheme config for iOS
- Registers the timesafari:// URL scheme
- Sets the bundle URL name to app.timesafari
2025-06-16 16:09:08 +08:00
Matthew Raymer
048dded278 fix: resolve deep link route mismatch for project links
- Fix schema validation mismatch between "project-details" and "project"
- Update VALID_DEEP_LINK_ROUTES to include "project" instead of "project-details"
- Update deepLinkSchemas to use "project" route name
- Update documentation to reflect correct route name
- Resolves "Invalid route path: project" errors in deep link handling

The deep link timesafari://project/01JWH0YAB3MAGBD751VAJAXQ17 now works correctly
and routes to the ProjectViewView component as expected.

Fixes: Deep link validation errors for project routes
2025-06-16 05:48:13 +00:00
e240c2940a remove unused deep links and add another 2025-06-15 13:54:12 -06:00
54dca9e745 fix project deep-link (and reorder alphabetically) 2025-06-15 11:02:16 -06:00
9f0fed0a60 update ios check to work, and add links to app stores 2025-06-14 22:10:49 -06:00
0d152adbf2 remove the deep-link autoVerify because it caused a build failure 2025-06-14 22:06:12 -06:00
cead308800 incorporate one of the BUILDING steps directly into the file 2025-06-13 22:37:03 -06:00
676a301331 bump to build 30 version 0.5.4 2025-06-13 22:36:28 -06:00
d6db81cc36 fix some result types and refactor types themselves 2025-06-13 21:58:57 -06:00
Matthew Raymer
f2ddcd2541 feat: add conditional rendering for claim certificate link and update gitignore
- Add v-if directive to show claim certificate link only when veriClaim.id exists
- Update .gitignore to exclude android app resource directory
- Prevents broken links when claim data is not fully loaded
- Improves build process by ignoring generated Android resources

This change ensures the certificate link is only displayed when there's
valid claim data available, preventing navigation errors and improving
user experience. The gitignore update helps keep the repository clean
by excluding Android-specific generated files.
2025-06-14 03:31:12 +00:00
fb81f7b96e fix problems with :href links causing the app to reload for DB errors on mobile 2025-06-13 20:39:12 -06:00
a23416ead1 fix optional message at top to not overflow 2025-06-12 20:10:31 -06:00
530c7c1a13 fix problem with user-profile page, and bump to build 29 & version 0.5.3 2025-06-12 19:16:02 -06:00
30 changed files with 757 additions and 1402 deletions

1
.gitignore vendored
View File

@@ -55,3 +55,4 @@ build_logs/
icons
android/app/src/main/res/

View File

@@ -321,11 +321,11 @@ Prerequisites: macOS with Xcode installed
#### Each Release
0. First time (or if XCode dependencies change):
0. First time (or if dependencies change):
- `pkgx +rubygems.org sh`
- ... and you may have to fix these, especially with pkgx
- ... and you may have to fix these, especially with pkgx:
```bash
gem_path=$(which gem)
@@ -334,12 +334,9 @@ Prerequisites: macOS with Xcode installed
export GEM_PATH=$shortened_path
```
```bash
cd ios/App
pod install
```
1. Check the iOS flag isIOS in CapacitorPlatformService (currently hard-coded for iOS build).
1. Build the web assets:
2. Build the web assets:
```bash
rm -rf dist
@@ -347,8 +344,7 @@ Prerequisites: macOS with Xcode installed
npm run build:capacitor
```
2. Update iOS project with latest build:
3. Update iOS project with latest build:
```bash
npx cap sync ios
@@ -356,7 +352,7 @@ Prerequisites: macOS with Xcode installed
- If that fails with "Could not find..." then look at the "gem_path" instructions above.
3. Copy the assets:
4. Copy the assets:
```bash
# It makes no sense why capacitor-assets will not run without these but it actually changes the contents.
@@ -367,15 +363,14 @@ Prerequisites: macOS with Xcode installed
npx capacitor-assets generate --ios
```
4. Bump the version to match Android:
4. Bump the version to match Android & package.json:
```
cd ios/App
xcrun agvtool new-version 25
xcrun agvtool new-version 30
# Unfortunately this edits Info.plist directly.
#xcrun agvtool new-marketing-version 0.4.5
cat App.xcodeproj/project.pbxproj | sed "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 0.5.1;/g" > temp
mv temp App.xcodeproj/project.pbxproj
cat App.xcodeproj/project.pbxproj | sed "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 0.5.4;/g" > temp && mv temp App.xcodeproj/project.pbxproj
cd -
```
@@ -403,6 +398,8 @@ Prerequisites: macOS with Xcode installed
* You'll probably have to "Manage" something about encryption, disallowed in France.
* Then "Save" and "Add to Review" and "Resubmit to App Review".
8. Revert the iOS flag isIOS in CapacitorPlatformService.
### Android Build
Prerequisites: Android Studio with Java SDK installed
@@ -427,7 +424,7 @@ Prerequisites: Android Studio with Java SDK installed
npx capacitor-assets generate --android
```
4. Bump version to match iOS: android/app/build.gradle
4. Bump version to match iOS & package.json: android/app/build.gradle
5. Open the project in Android Studio:
@@ -478,7 +475,7 @@ At play.google.com/console:
- Note that if you add testers, you have to go to "Publishing Overview" and send those changes or your (closed) testers won't see it.
## First-time Android Configuration for deep links
## Android Configuration for deep links
You must add the following intent filter to the `android/app/src/main/AndroidManifest.xml` file:
@@ -490,3 +487,5 @@ You must add the following intent filter to the `android/app/src/main/AndroidMan
<data android:scheme="timesafari" />
</intent-filter>
```
... though when we tried that most recently it failed to 'build' the APK with: http(s) scheme and host attribute are missing, but are required for Android App Links [AppLinkUrlError]

View File

@@ -31,8 +31,8 @@ android {
applicationId "app.timesafari.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 26
versionName "0.5.1"
versionCode 30
versionName "0.5.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

View File

@@ -403,7 +403,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 26;
CURRENT_PROJECT_VERSION = 30;
DEVELOPMENT_TEAM = GM3FS5JQPH;
ENABLE_APP_SANDBOX = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
@@ -413,7 +413,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.5.1;
MARKETING_VERSION = 0.5.4;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = app.timesafari;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -430,7 +430,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 26;
CURRENT_PROJECT_VERSION = 30;
DEVELOPMENT_TEAM = GM3FS5JQPH;
ENABLE_APP_SANDBOX = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
@@ -440,7 +440,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.5.1;
MARKETING_VERSION = 0.5.4;
PRODUCT_BUNDLE_IDENTIFIER = app.timesafari;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";

View File

@@ -49,5 +49,16 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>app.timesafari</string>
<key>CFBundleURLSchemes</key>
<array>
<string>timesafari</string>
</array>
</dict>
</array>
</dict>
</plist>

579
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "timesafari",
"version": "0.4.8",
"version": "0.5.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "timesafari",
"version": "0.4.8",
"version": "0.5.4",
"dependencies": {
"@capacitor-community/sqlite": "6.0.2",
"@capacitor-mlkit/barcode-scanning": "^6.0.0",
@@ -3835,9 +3835,9 @@
}
},
"node_modules/@electron/asar/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4524,9 +4524,9 @@
}
},
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6686,9 +6686,9 @@
}
},
"node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6983,6 +6983,29 @@
"integrity": "sha512-meL9DERHj+fFVWoOX9fXqfcYcSpUfSYJPcFvDPKrxitICbwAoWR+Ut4j5NO9zAT917HUHLQmqzQbAsGNHlDcxQ==",
"license": "Apache-2.0 OR MIT"
},
"node_modules/@isaacs/balanced-match": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@isaacs/brace-expansion": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@isaacs/balanced-match": "^4.0.1"
},
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -7839,9 +7862,9 @@
}
},
"node_modules/@react-native/assets-registry": {
"version": "0.79.3",
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.79.3.tgz",
"integrity": "sha512-Vy8DQXCJ21YSAiHxrNBz35VqVlZPpRYm50xRTWRf660JwHuJkFQG8cUkrLzm7AUriqUXxwpkQHcY+b0ibw9ejQ==",
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.80.0.tgz",
"integrity": "sha512-MlScsKAz99zoYghe5Rf5mUqsqz2rMB02640NxtPtBMSHNdGxxRlWu/pp1bFexDa1DYJwyIjnLgt3Z/Y90ikHfw==",
"license": "MIT",
"optional": true,
"peer": true,
@@ -7947,20 +7970,20 @@
}
},
"node_modules/@react-native/community-cli-plugin": {
"version": "0.79.3",
"resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.79.3.tgz",
"integrity": "sha512-N/+p4HQqN4yK6IRzn7OgMvUIcrmEWkecglk1q5nj+AzNpfIOzB+mqR20SYmnPfeXF+mZzYCzRANb3KiM+WsSDA==",
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.80.0.tgz",
"integrity": "sha512-uadfVvzZfz5tGpqwslL12i+rELK9m6cLhtqICX0JQvS7Bu12PJwrozhKzEzIYwN9i3wl2dWrKDUr08izt7S9Iw==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"@react-native/dev-middleware": "0.79.3",
"@react-native/dev-middleware": "0.80.0",
"chalk": "^4.0.0",
"debug": "^2.2.0",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"metro": "^0.82.0",
"metro-config": "^0.82.0",
"metro-core": "^0.82.0",
"metro": "^0.82.2",
"metro-config": "^0.82.2",
"metro-core": "^0.82.2",
"semver": "^7.1.3"
},
"engines": {
@@ -7975,25 +7998,97 @@
}
}
},
"node_modules/@react-native/community-cli-plugin/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"node_modules/@react-native/community-cli-plugin/node_modules/@react-native/debugger-frontend": {
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.80.0.tgz",
"integrity": "sha512-lpu9Z3xtKUaKFvEcm5HSgo1KGfkDa/W3oZHn22Zy0WQ9MiOu2/ar1txgd1wjkoNiK/NethKcRdCN7mqnc6y2mA==",
"license": "BSD-3-Clause",
"optional": true,
"peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/@react-native/community-cli-plugin/node_modules/@react-native/dev-middleware": {
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.80.0.tgz",
"integrity": "sha512-lLyTnJ687A5jF3fn8yR/undlCis3FG+N/apQ+Q0Lcl+GV6FsZs0U5H28YmL6lZtjOj4TLek6uGPMPmZasHx7cQ==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"ms": "2.0.0"
"@isaacs/ttlcache": "^1.4.1",
"@react-native/debugger-frontend": "0.80.0",
"chrome-launcher": "^0.15.2",
"chromium-edge-launcher": "^0.2.0",
"connect": "^3.6.5",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"nullthrows": "^1.1.1",
"open": "^7.0.3",
"serve-static": "^1.16.2",
"ws": "^6.2.3"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@react-native/community-cli-plugin/node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@react-native/community-cli-plugin/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/@react-native/community-cli-plugin/node_modules/open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@react-native/community-cli-plugin/node_modules/ws": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
"integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"async-limiter": "~1.0.0"
}
},
"node_modules/@react-native/debugger-frontend": {
"version": "0.79.3",
"resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.79.3.tgz",
@@ -8078,9 +8173,9 @@
}
},
"node_modules/@react-native/gradle-plugin": {
"version": "0.79.3",
"resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.79.3.tgz",
"integrity": "sha512-imfpZLhNBc9UFSzb/MOy2tNcIBHqVmexh/qdzw83F75BmUtLb/Gs1L2V5gw+WI1r7RqDILbWk7gXB8zUllwd+g==",
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.80.0.tgz",
"integrity": "sha512-drmS68rabSMOuDD+YsAY2luNT8br82ycodSDORDqAg7yWQcieHMp4ZUOcdOi5iW+JCqobablT/b6qxcrBg+RaA==",
"license": "MIT",
"optional": true,
"peer": true,
@@ -8089,9 +8184,9 @@
}
},
"node_modules/@react-native/js-polyfills": {
"version": "0.79.3",
"resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.79.3.tgz",
"integrity": "sha512-PEBtg6Kox6KahjCAch0UrqCAmHiNLEbp2SblUEoFAQnov4DSxBN9safh+QSVaCiMAwLjvNfXrJyygZz60Dqz3Q==",
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.80.0.tgz",
"integrity": "sha512-dMX7IcBuwghySTgIeK8q03tYz/epg5ScGmJEfBQAciuhzMDMV1LBR/9wwdgD73EXM/133yC5A+TlHb3KQil4Ew==",
"license": "MIT",
"optional": true,
"peer": true,
@@ -8108,9 +8203,9 @@
"peer": true
},
"node_modules/@react-native/virtualized-lists": {
"version": "0.79.3",
"resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.79.3.tgz",
"integrity": "sha512-/0rRozkn+iIHya2vnnvprDgT7QkfI54FLrACAN3BLP7MRlfOIGOrZsXpRLndnLBVnjNzkcre84i1RecjoXnwIA==",
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.80.0.tgz",
"integrity": "sha512-d9zZdPS/ZRexVAkxo1eRp85U7XnnEpXA1ZpSomRKxBuStYKky1YohfEX5YD5MhphemKK24tT7JR4UhaLlmeX8Q==",
"license": "MIT",
"optional": true,
"peer": true,
@@ -8217,9 +8312,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.42.0.tgz",
"integrity": "sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz",
"integrity": "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==",
"cpu": [
"arm"
],
@@ -8231,9 +8326,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.42.0.tgz",
"integrity": "sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.43.0.tgz",
"integrity": "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==",
"cpu": [
"arm64"
],
@@ -8271,9 +8366,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.42.0.tgz",
"integrity": "sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.43.0.tgz",
"integrity": "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==",
"cpu": [
"arm64"
],
@@ -8285,9 +8380,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.42.0.tgz",
"integrity": "sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.43.0.tgz",
"integrity": "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==",
"cpu": [
"x64"
],
@@ -8299,9 +8394,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.42.0.tgz",
"integrity": "sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.43.0.tgz",
"integrity": "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==",
"cpu": [
"arm"
],
@@ -8313,9 +8408,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.42.0.tgz",
"integrity": "sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.43.0.tgz",
"integrity": "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==",
"cpu": [
"arm"
],
@@ -8353,9 +8448,9 @@
]
},
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.42.0.tgz",
"integrity": "sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz",
"integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==",
"cpu": [
"loong64"
],
@@ -8367,9 +8462,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.42.0.tgz",
"integrity": "sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz",
"integrity": "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==",
"cpu": [
"ppc64"
],
@@ -8381,9 +8476,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.42.0.tgz",
"integrity": "sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz",
"integrity": "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==",
"cpu": [
"riscv64"
],
@@ -8395,9 +8490,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.42.0.tgz",
"integrity": "sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.43.0.tgz",
"integrity": "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==",
"cpu": [
"riscv64"
],
@@ -8409,9 +8504,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.42.0.tgz",
"integrity": "sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.43.0.tgz",
"integrity": "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==",
"cpu": [
"s390x"
],
@@ -8462,9 +8557,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.42.0.tgz",
"integrity": "sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.43.0.tgz",
"integrity": "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==",
"cpu": [
"ia32"
],
@@ -8874,9 +8969,9 @@
}
},
"node_modules/@stencil/core": {
"version": "4.33.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.33.1.tgz",
"integrity": "sha512-12k9xhAJBkpg598it+NRmaYIdEe6TSnsL/v6/KRXDcUyTK11VYwZQej2eHnMWtqot+znJ+GNTqb5YbiXi+5Low==",
"version": "4.35.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.35.0.tgz",
"integrity": "sha512-x0IFtj7IJStK+ZqIkhReWbiC0UMjMJnNXV8OXG+DCLDExZaVaxL3MLuq6BJBBcQ1MHZduTHDv3Iz0Zshoj3zjQ==",
"license": "MIT",
"bin": {
"stencil": "bin/stencil"
@@ -11184,13 +11279,13 @@
}
},
"node_modules/app-builder-lib/node_modules/minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
"integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
"@isaacs/brace-expansion": "^5.0.0"
},
"engines": {
"node": "20 || >=22"
@@ -11612,9 +11707,9 @@
}
},
"node_modules/axios": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
"integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz",
"integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
@@ -12199,9 +12294,9 @@
}
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -12648,9 +12743,9 @@
}
},
"node_modules/cacache/node_modules/rimraf/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12868,9 +12963,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001721",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz",
"integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==",
"version": "1.0.30001723",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz",
"integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==",
"devOptional": true,
"funding": [
{
@@ -14507,9 +14602,9 @@
}
},
"node_modules/decode-named-character-reference": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz",
"integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz",
"integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -14931,9 +15026,9 @@
}
},
"node_modules/dir-compare/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -15347,9 +15442,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.166",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz",
"integrity": "sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==",
"version": "1.5.167",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.167.tgz",
"integrity": "sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==",
"devOptional": true,
"license": "ISC"
},
@@ -15865,9 +15960,9 @@
}
},
"node_modules/eslint/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -16079,9 +16174,9 @@
}
},
"node_modules/ethers": {
"version": "6.14.3",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.14.3.tgz",
"integrity": "sha512-qq7ft/oCJohoTcsNPFaXSQUm457MA5iWqkf1Mb11ujONdg7jBI6sAOrHaTi3j0CBqIGFSCeR/RMc+qwRRub7IA==",
"version": "6.14.4",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.14.4.tgz",
"integrity": "sha512-Jm/dzRs2Z9iBrT6e9TvGxyb5YVKAPLlpna7hjxH7KH/++DSh2T/JVmQUv7iHI5E55hDbp/gEVvstWYXVxXFzsA==",
"funding": [
{
"type": "individual",
@@ -16178,21 +16273,21 @@
"license": "MIT"
},
"node_modules/ethr-did": {
"version": "3.0.37",
"resolved": "https://registry.npmjs.org/ethr-did/-/ethr-did-3.0.37.tgz",
"integrity": "sha512-L9UUhAS8B1T7jTRdKLwAt514lx2UrJebJK7uc6UU4AJ9RhY8Vcfwc93Ux82jREE7yvvqDPXsVNH+lS3aw18a9A==",
"version": "3.0.38",
"resolved": "https://registry.npmjs.org/ethr-did/-/ethr-did-3.0.38.tgz",
"integrity": "sha512-gUxtErXVOQUJf+bmnxRdSJdlU9aFbQSBNaJCYGt+PLqw6l4qqInTfMRiWpwe/brhRtdjE+64tnayOVk8ataeQA==",
"license": "Apache-2.0",
"dependencies": {
"did-jwt": "^8.0.0",
"did-resolver": "^4.1.0",
"ethers": "^6.8.1",
"ethr-did-resolver": "11.0.3"
"ethr-did-resolver": "11.0.4"
}
},
"node_modules/ethr-did-resolver": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/ethr-did-resolver/-/ethr-did-resolver-11.0.3.tgz",
"integrity": "sha512-lQ1T/SZfgR6Kp05/GSIXnMELxQ5H6M6OCTH4wBTVSAgHzbJiDNVIYWzg/c+NniIM88B0ViAi4CaiCHaiUlvPQg==",
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/ethr-did-resolver/-/ethr-did-resolver-11.0.4.tgz",
"integrity": "sha512-EJ/dL2QsFzvhBJd0nlPFjma3bxpQOWyp2TytQZyAeqi6SfZ4ALCB0VaA4dSeT4T8ZtI2pzs/sD7t/7A0584J6Q==",
"license": "Apache-2.0",
"dependencies": {
"did-resolver": "^4.1.0",
@@ -17617,9 +17712,9 @@
}
},
"node_modules/glob/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"devOptional": true,
"license": "MIT",
"dependencies": {
@@ -19127,9 +19222,9 @@
}
},
"node_modules/jake/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -24054,9 +24149,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz",
"integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
"version": "8.5.5",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz",
"integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==",
"funding": [
{
"type": "opencollective",
@@ -24954,44 +25049,43 @@
"peer": true
},
"node_modules/react-native": {
"version": "0.79.3",
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.79.3.tgz",
"integrity": "sha512-EzH1+9gzdyEo9zdP6u7Sh3Jtf5EOMwzy+TK65JysdlgAzfEVfq4mNeXcAZ6SmD+CW6M7ARJbvXLyTD0l2S5rpg==",
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.80.0.tgz",
"integrity": "sha512-b9K1ygb2MWCBtKAodKmE3UsbUuC29Pt4CrJMR0ocTA8k+8HJQTPleBPDNKL4/p0P01QO9aL/gZUddoxHempLow==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"@jest/create-cache-key-function": "^29.7.0",
"@react-native/assets-registry": "0.79.3",
"@react-native/codegen": "0.79.3",
"@react-native/community-cli-plugin": "0.79.3",
"@react-native/gradle-plugin": "0.79.3",
"@react-native/js-polyfills": "0.79.3",
"@react-native/normalize-colors": "0.79.3",
"@react-native/virtualized-lists": "0.79.3",
"@react-native/assets-registry": "0.80.0",
"@react-native/codegen": "0.80.0",
"@react-native/community-cli-plugin": "0.80.0",
"@react-native/gradle-plugin": "0.80.0",
"@react-native/js-polyfills": "0.80.0",
"@react-native/normalize-colors": "0.80.0",
"@react-native/virtualized-lists": "0.80.0",
"abort-controller": "^3.0.0",
"anser": "^1.4.9",
"ansi-regex": "^5.0.0",
"babel-jest": "^29.7.0",
"babel-plugin-syntax-hermes-parser": "0.25.1",
"babel-plugin-syntax-hermes-parser": "0.28.1",
"base64-js": "^1.5.1",
"chalk": "^4.0.0",
"commander": "^12.0.0",
"event-target-shim": "^5.0.1",
"flow-enums-runtime": "^0.0.6",
"glob": "^7.1.1",
"invariant": "^2.2.4",
"jest-environment-node": "^29.7.0",
"memoize-one": "^5.0.0",
"metro-runtime": "^0.82.0",
"metro-source-map": "^0.82.0",
"metro-runtime": "^0.82.2",
"metro-source-map": "^0.82.2",
"nullthrows": "^1.1.1",
"pretty-format": "^29.7.0",
"promise": "^8.3.0",
"react-devtools-core": "^6.1.1",
"react-refresh": "^0.14.0",
"regenerator-runtime": "^0.13.2",
"scheduler": "0.25.0",
"scheduler": "0.26.0",
"semver": "^7.1.3",
"stacktrace-parser": "^0.1.10",
"whatwg-fetch": "^3.0.0",
@@ -25005,8 +25099,8 @@
"node": ">=18"
},
"peerDependencies": {
"@types/react": "^19.0.0",
"react": "^19.0.0"
"@types/react": "^19.1.0",
"react": "^19.1.0"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -25039,14 +25133,46 @@
"react-native": "*"
}
},
"node_modules/react-native/node_modules/@react-native/codegen": {
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.80.0.tgz",
"integrity": "sha512-X9TsPgytoUkNrQjzAZh4dXa4AuouvYT0NzYyvnjw1ry4LESCZtKba+eY4x3+M30WPR52zjgu+UFL//14BSdCCA==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"glob": "^7.1.1",
"hermes-parser": "0.28.1",
"invariant": "^2.2.4",
"nullthrows": "^1.1.1",
"yargs": "^17.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@babel/core": "*"
}
},
"node_modules/react-native/node_modules/@react-native/normalize-colors": {
"version": "0.79.3",
"resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.3.tgz",
"integrity": "sha512-T75NIQPRFCj6DFMxtcVMJTZR+3vHXaUMSd15t+CkJpc5LnyX91GVaPxpRSAdjFh7m3Yppl5MpdjV/fntImheYQ==",
"version": "0.80.0",
"resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.80.0.tgz",
"integrity": "sha512-bJZDSopadjJxMDvysc634eTfLL4w7cAx5diPe14Ez5l+xcKjvpfofS/1Ja14DlgdMJhxGd03MTXlrxoWust3zg==",
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/react-native/node_modules/babel-plugin-syntax-hermes-parser": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.28.1.tgz",
"integrity": "sha512-meT17DOuUElMNsL5LZN56d+KBp22hb0EfxWfuPUeoSi54e40v1W4C2V36P75FpsH9fVEfDKpw5Nnkahc8haSsQ==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"hermes-parser": "0.28.1"
}
},
"node_modules/react-native/node_modules/commander": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
@@ -25058,6 +25184,25 @@
"node": ">=18"
}
},
"node_modules/react-native/node_modules/hermes-estree": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.28.1.tgz",
"integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==",
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/react-native/node_modules/hermes-parser": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.28.1.tgz",
"integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"hermes-estree": "0.28.1"
}
},
"node_modules/react-native/node_modules/ws": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
@@ -25514,9 +25659,9 @@
}
},
"node_modules/replace/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -25960,15 +26105,15 @@
}
},
"node_modules/rimraf/node_modules/glob": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz",
"integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==",
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
"integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==",
"dev": true,
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"foreground-child": "^3.3.1",
"jackspeak": "^4.1.1",
"minimatch": "^10.0.3",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
@@ -26010,13 +26155,13 @@
}
},
"node_modules/rimraf/node_modules/minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
"integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
"@isaacs/brace-expansion": "^5.0.0"
},
"engines": {
"node": "20 || >=22"
@@ -26094,9 +26239,9 @@
}
},
"node_modules/rollup": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.42.0.tgz",
"integrity": "sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.43.0.tgz",
"integrity": "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -26110,33 +26255,33 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.42.0",
"@rollup/rollup-android-arm64": "4.42.0",
"@rollup/rollup-darwin-arm64": "4.42.0",
"@rollup/rollup-darwin-x64": "4.42.0",
"@rollup/rollup-freebsd-arm64": "4.42.0",
"@rollup/rollup-freebsd-x64": "4.42.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.42.0",
"@rollup/rollup-linux-arm-musleabihf": "4.42.0",
"@rollup/rollup-linux-arm64-gnu": "4.42.0",
"@rollup/rollup-linux-arm64-musl": "4.42.0",
"@rollup/rollup-linux-loongarch64-gnu": "4.42.0",
"@rollup/rollup-linux-powerpc64le-gnu": "4.42.0",
"@rollup/rollup-linux-riscv64-gnu": "4.42.0",
"@rollup/rollup-linux-riscv64-musl": "4.42.0",
"@rollup/rollup-linux-s390x-gnu": "4.42.0",
"@rollup/rollup-linux-x64-gnu": "4.42.0",
"@rollup/rollup-linux-x64-musl": "4.42.0",
"@rollup/rollup-win32-arm64-msvc": "4.42.0",
"@rollup/rollup-win32-ia32-msvc": "4.42.0",
"@rollup/rollup-win32-x64-msvc": "4.42.0",
"@rollup/rollup-android-arm-eabi": "4.43.0",
"@rollup/rollup-android-arm64": "4.43.0",
"@rollup/rollup-darwin-arm64": "4.43.0",
"@rollup/rollup-darwin-x64": "4.43.0",
"@rollup/rollup-freebsd-arm64": "4.43.0",
"@rollup/rollup-freebsd-x64": "4.43.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.43.0",
"@rollup/rollup-linux-arm-musleabihf": "4.43.0",
"@rollup/rollup-linux-arm64-gnu": "4.43.0",
"@rollup/rollup-linux-arm64-musl": "4.43.0",
"@rollup/rollup-linux-loongarch64-gnu": "4.43.0",
"@rollup/rollup-linux-powerpc64le-gnu": "4.43.0",
"@rollup/rollup-linux-riscv64-gnu": "4.43.0",
"@rollup/rollup-linux-riscv64-musl": "4.43.0",
"@rollup/rollup-linux-s390x-gnu": "4.43.0",
"@rollup/rollup-linux-x64-gnu": "4.43.0",
"@rollup/rollup-linux-x64-musl": "4.43.0",
"@rollup/rollup-win32-arm64-msvc": "4.43.0",
"@rollup/rollup-win32-ia32-msvc": "4.43.0",
"@rollup/rollup-win32-x64-msvc": "4.43.0",
"fsevents": "~2.3.2"
}
},
"node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.42.0.tgz",
"integrity": "sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.43.0.tgz",
"integrity": "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==",
"cpu": [
"arm64"
],
@@ -26148,9 +26293,9 @@
]
},
"node_modules/rollup/node_modules/@rollup/rollup-darwin-x64": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.42.0.tgz",
"integrity": "sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.43.0.tgz",
"integrity": "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==",
"cpu": [
"x64"
],
@@ -26162,9 +26307,9 @@
]
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.42.0.tgz",
"integrity": "sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.43.0.tgz",
"integrity": "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==",
"cpu": [
"arm64"
],
@@ -26176,9 +26321,9 @@
]
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.42.0.tgz",
"integrity": "sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.43.0.tgz",
"integrity": "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==",
"cpu": [
"arm64"
],
@@ -26190,9 +26335,9 @@
]
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.42.0.tgz",
"integrity": "sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.43.0.tgz",
"integrity": "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==",
"cpu": [
"x64"
],
@@ -26204,9 +26349,9 @@
]
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.42.0.tgz",
"integrity": "sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.43.0.tgz",
"integrity": "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==",
"cpu": [
"x64"
],
@@ -26218,9 +26363,9 @@
]
},
"node_modules/rollup/node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.42.0.tgz",
"integrity": "sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.43.0.tgz",
"integrity": "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==",
"cpu": [
"arm64"
],
@@ -26232,9 +26377,9 @@
]
},
"node_modules/rollup/node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.42.0.tgz",
"integrity": "sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==",
"version": "4.43.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.43.0.tgz",
"integrity": "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==",
"cpu": [
"x64"
],
@@ -26410,9 +26555,9 @@
"license": "ISC"
},
"node_modules/scheduler": {
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
"integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
"license": "MIT",
"optional": true,
"peer": true
@@ -26424,9 +26569,9 @@
"license": "MIT"
},
"node_modules/sdp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.0.tgz",
"integrity": "sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==",
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.1.tgz",
"integrity": "sha512-lwsAIzOPlH8/7IIjjz3K0zYBk7aBVVcvjMwt3M4fLxpjMYyy7i3I97SLHebgn4YBjirkzfp3RvRDWSKsh/+WFw==",
"license": "MIT"
},
"node_modules/secp256k1": {
@@ -28495,9 +28640,9 @@
}
},
"node_modules/test-exclude/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"license": "MIT",
"optional": true,
"peer": true,
@@ -31045,9 +31190,9 @@
}
},
"node_modules/zod": {
"version": "3.25.58",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.58.tgz",
"integrity": "sha512-DVLmMQzSZwNYzQoMaM3MQWnxr2eq+AtM9Hx3w1/Yl0pH8sLTSjN4jGP7w6f7uand6Hw44tsnSu1hz1AOA6qI2Q==",
"version": "3.25.64",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.64.tgz",
"integrity": "sha512-hbP9FpSZf7pkS7hRVUrOjhwKJNyampPgtXKc3AN6DsWtoHsg2Sb4SQaS4Tcay380zSwd2VPo9G9180emBACp5g==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"

View File

@@ -1,6 +1,6 @@
{
"name": "timesafari",
"version": "0.5.1",
"version": "0.5.4",
"description": "Time Safari Application",
"author": {
"name": "Time Safari Team"

View File

@@ -1,458 +1,82 @@
<template>
<div v-if="visible" class="dialog-overlay">
<div class="dialog">
<!-- Step 1: Giver -->
<div v-show="currentStep === 1" id="sectionGiftedGiver">
<label class="block font-bold mb-4">
{{
stepType === "recipient"
? "Choose who received the gift:"
: showProjects
? "Choose a project benefitted from:"
: "Choose a person received from:"
}}
</label>
<!-- Unified Quick-pick grid for People and Projects -->
<ul
:class="
shouldShowProjects
? 'grid grid-cols-3 md:grid-cols-4 gap-x-2 gap-y-4 text-center mb-4'
: 'grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-x-2 gap-y-4 text-center mb-4'
"
>
<template v-if="shouldShowProjects">
<!-- show projects -->
<li
v-for="project in projects.slice(0, 7)"
:key="project.handleId"
class="cursor-pointer"
@click="
stepType === 'recipient'
? selectRecipientProject(project)
: selectProject(project)
"
>
<div class="relative w-fit mx-auto">
<ProjectIcon
:entity-id="project.handleId"
:icon-size="48"
:image-url="project.image"
class="!size-[3rem] mx-auto border border-slate-300 bg-white overflow-hidden rounded-full mb-1"
/>
</div>
<h3
class="text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden"
>
{{ project.name }}
</h3>
<div class="text-xs text-slate-500 truncate">
<font-awesome icon="user" class="fa-fw text-slate-400" />
{{
didInfo(project.issuerDid, activeDid, allMyDids, allContacts)
}}
</div>
</li>
<li
v-if="projects.length === 0"
class="text-xs text-slate-500 italic col-span-full"
>
(No projects found.)
</li>
<li v-if="projects.length > 0">
<router-link :to="{ name: 'discover' }" class="cursor-pointer">
<font-awesome
icon="circle-right"
class="text-blue-500 text-5xl mb-1"
/>
<h3
class="text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden"
>
Show All
</h3>
</router-link>
</li>
</template>
<template v-else>
<!-- show people (contacts) -->
<li
v-if="
stepType === 'recipient' ||
(stepType === 'giver' && isFromProjectView)
"
:class="{
'cursor-pointer': !wouldCreateConflict(activeDid),
'cursor-not-allowed opacity-50': wouldCreateConflict(activeDid)
}"
@click="
!wouldCreateConflict(activeDid) &&
(stepType === 'recipient'
? selectRecipient({ did: activeDid, name: 'You' })
: selectGiver({ did: activeDid, name: 'You' }))
"
>
<font-awesome
:class="{
'text-blue-500 text-5xl mb-1': !wouldCreateConflict(activeDid),
'text-slate-400 text-5xl mb-1': wouldCreateConflict(activeDid)
}"
icon="hand"
/>
<h3
:class="{
'text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden': !wouldCreateConflict(activeDid),
'text-xs text-slate-400 font-medium text-ellipsis whitespace-nowrap overflow-hidden': wouldCreateConflict(activeDid)
}"
>
You
</h3>
</li>
<li
class="cursor-pointer"
@click="
stepType === 'recipient' ? selectRecipient() : selectGiver()
"
>
<font-awesome
icon="circle-question"
class="text-slate-400 text-5xl mb-1"
/>
<h3
class="text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden"
>
Unnamed
</h3>
</li>
<li
v-if="allContacts.length === 0"
class="text-xs text-slate-500 italic col-span-full"
>
(Add friends to see more people worthy of recognition.)
</li>
<li
v-for="contact in allContacts.slice(0, 10)"
:key="contact.did"
:class="{
'cursor-pointer': !wouldCreateConflict(contact.did),
'cursor-not-allowed opacity-50': wouldCreateConflict(contact.did)
}"
@click="
!wouldCreateConflict(contact.did) &&
(stepType === 'recipient'
? selectRecipient(contact)
: selectGiver(contact))
"
>
<div class="relative w-fit mx-auto">
<EntityIcon
:contact="contact"
class="!size-[3rem] mx-auto border border-slate-300 bg-white overflow-hidden rounded-full mb-1"
/>
<div
class="rounded-full bg-slate-400 absolute bottom-0 right-0 p-1 translate-x-1/3"
>
<font-awesome
icon="clock"
class="block text-white text-xs w-[1em]"
/>
</div>
</div>
<h3
:class="{
'text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden': !wouldCreateConflict(contact.did),
'text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden text-slate-400': wouldCreateConflict(contact.did)
}"
>
{{ contact.name || contact.did }}
</h3>
</li>
<li v-if="allContacts.length > 0" class="cursor-pointer">
<router-link
:to="{
name: 'contact-gift',
query: {
stepType: stepType,
giverEntityType: giverEntityType,
recipientEntityType: recipientEntityType,
...(stepType === 'giver'
? {
recipientProjectId: toProjectId,
recipientProjectName: receiver?.name,
recipientProjectImage: receiver?.image,
recipientProjectHandleId: receiver?.handleId,
recipientDid: receiver?.did,
}
: {
giverProjectId: fromProjectId,
giverProjectName: giver?.name,
giverProjectImage: giver?.image,
giverProjectHandleId: giver?.handleId,
giverDid: giver?.did,
}),
fromProjectId: fromProjectId,
toProjectId: toProjectId,
showProjects: (showProjects || false).toString(),
isFromProjectView: (isFromProjectView || false).toString(),
},
}"
>
<font-awesome
icon="circle-right"
class="text-blue-500 text-5xl mb-1"
/>
<h3
class="text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden"
>
Show All
</h3>
</router-link>
</li>
</template>
</ul>
<button
class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg"
@click="cancel"
>
Cancel
</button>
</div>
<!-- Step 2: Gift -->
<div v-show="currentStep === 2" id="sectionGiftedGift">
<div class="grid grid-cols-2 gap-2 mb-4">
<!-- Giver Button -->
<button
v-if="
(giverEntityType === 'person' || giverEntityType === 'project') &&
!(isFromProjectView && giverEntityType === 'project')
"
class="flex-1 flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2"
@click="goBackToStep1('giver')"
>
<div>
<template v-if="giverEntityType === 'project'">
<ProjectIcon
v-if="giver?.handleId"
:entity-id="giver.handleId"
:icon-size="32"
:image-url="giver.image"
class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/>
</template>
<template v-else>
<EntityIcon
v-if="giver?.did"
:contact="giver"
class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/>
<font-awesome
v-else
icon="circle-question"
class="text-slate-400 text-3xl"
/>
</template>
</div>
<div class="text-start min-w-0">
<p class="text-xs text-slate-500 leading-1 -mb-1 uppercase">
{{
giverEntityType === "project"
? "Benefited from:"
: "Received from:"
}}
</p>
<h3 class="font-semibold truncate">
{{ giver?.name || "Unnamed" }}
</h3>
</div>
<p class="ms-auto text-sm text-blue-500 pe-1">
<font-awesome icon="pen" title="Change" />
</p>
</button>
<div
v-else
class="flex-1 flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2"
>
<div>
<template v-if="giverEntityType === 'project'">
<ProjectIcon
v-if="giver?.handleId"
:entity-id="giver.handleId"
:icon-size="32"
:image-url="giver.image"
class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/>
</template>
<template v-else>
<EntityIcon
v-if="giver?.did"
:contact="giver"
class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/>
<font-awesome
v-else
icon="circle-question"
class="text-slate-400 text-3xl"
/>
</template>
</div>
<div class="text-start min-w-0">
<p class="text-xs text-slate-500 leading-1 -mb-1 uppercase">
{{
giverEntityType === "project"
? "Benefited from:"
: "Received from:"
}}
</p>
<h3 class="font-semibold truncate">
{{ giver?.name || "Unnamed" }}
</h3>
</div>
<p class="ms-auto text-sm text-slate-400 pe-1">
<font-awesome icon="lock" title="Can't be changed" />
</p>
</div>
<!-- Recipient Button -->
<button
v-if="recipientEntityType === 'person'"
class="flex-1 flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2"
@click="goBackToStep1('recipient')"
>
<div>
<EntityIcon
v-if="receiver?.did"
:contact="receiver"
class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/>
<font-awesome
v-else
icon="circle-question"
class="text-slate-400 text-3xl"
/>
</div>
<div class="text-start min-w-0">
<p class="text-xs text-slate-500 leading-1 -mb-1 uppercase">
Given to:
</p>
<h3 class="font-semibold truncate">
{{ receiver?.name || "Unnamed" }}
</h3>
</div>
<p class="ms-auto text-sm text-blue-500 pe-1">
<font-awesome icon="pen" title="Change" />
</p>
</button>
<div
v-else-if="recipientEntityType === 'project'"
class="flex-1 flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2"
>
<div>
<ProjectIcon
v-if="receiver?.handleId"
:entity-id="receiver.handleId"
:icon-size="32"
:image-url="receiver.image"
class="rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/>
</div>
<div class="text-start min-w-0">
<p class="text-xs text-slate-500 leading-1 -mb-1 uppercase">
Given to project:
</p>
<h3 class="font-semibold truncate">
{{ receiver?.name || "Unnamed" }}
</h3>
</div>
<p class="ms-auto text-sm text-slate-400 pe-1">
<font-awesome icon="lock" title="Can't be changed" />
</p>
</div>
</div>
<h1 class="text-xl font-bold text-center mb-4">
{{ customTitle }}
</h1>
<input
v-model="description"
type="text"
class="block w-full rounded border border-slate-400 px-3 py-2 mb-4 placeholder:italic"
class="block w-full rounded border border-slate-400 mb-2 px-3 py-2"
:placeholder="prompt || 'What was given?'"
/>
<div class="flex mb-4">
<button
class="rounded-s border border-e-0 border-slate-400 bg-slate-200 px-4 py-2"
<div class="flex flex-row justify-center">
<span
class="rounded-l border border-r-0 border-slate-400 bg-slate-200 text-center text-blue-500 px-2 py-2 w-20"
@click="changeUnitCode()"
>
{{ libsUtil.UNIT_SHORT[unitCode] || unitCode }}
</span>
<div
class="border border-r-0 border-slate-400 bg-slate-200 px-4 py-2"
@click="amountInput === '0' ? null : decrement()"
>
<font-awesome icon="chevron-left" />
</button>
</div>
<input
id="inputGivenAmount"
v-model="amountInput"
type="number"
class="flex-1 border border-e-0 border-slate-400 px-2 py-2 text-center w-[1px]"
class="border border-r-0 border-slate-400 px-2 py-2 text-center w-20"
/>
<button
class="rounded-e border border-slate-400 bg-slate-200 px-4 py-2"
<div
class="rounded-r border border-slate-400 bg-slate-200 px-4 py-2"
@click="increment()"
>
<font-awesome icon="chevron-right" />
</button>
<select
v-model="unitCode"
class="flex-1 rounded border border-slate-400 ms-2 px-3 py-2"
>
<option value="HUR">Hours</option>
<option value="USD">US $</option>
<option value="BTC">BTC</option>
<option value="BX">BX</option>
<option value="ETH">ETH</option>
</select>
</div>
</div>
<div class="mt-4 flex justify-center">
<span>
<router-link
:to="{
name: 'gifted-details',
query: giftedDetailsQuery,
query: {
amountInput,
description,
giverDid: giver?.did,
giverName: giver?.name,
offerId,
fulfillsProjectId: toProjectId,
providerProjectId: fromProjectId,
recipientDid: receiver?.did,
recipientName: receiver?.name,
unitCode,
},
}"
class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg mb-4"
class="text-blue-500"
>
Photo &amp; more options&hellip;
Photo & more options ...
</router-link>
<p class="text-center text-sm mb-4">
<b class="font-medium">Sign &amp; Send</b> to publish to the world
</span>
</div>
<p class="text-center mb-2 mt-6 italic">
Sign & Send to publish to the world
<font-awesome
icon="circle-info"
class="fa-fw text-blue-500 text-base cursor-pointer"
class="pl-2 text-blue-500 cursor-pointer"
@click="explainData()"
/>
</p>
<!-- Conflict warning -->
<div v-if="hasPersonConflict" class="mb-4 p-3 bg-red-50 border border-red-200 rounded-md">
<p class="text-red-700 text-sm text-center">
<font-awesome icon="exclamation-triangle" class="fa-fw mr-1" />
Cannot record: Same person selected as both giver and recipient
</p>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
<button
:disabled="hasPersonConflict"
:class="{
'block w-full text-center text-md uppercase font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg': !hasPersonConflict,
'block w-full text-center text-md uppercase font-bold bg-gradient-to-b from-slate-300 to-slate-500 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-slate-400 px-1.5 py-2 rounded-lg cursor-not-allowed': hasPersonConflict
}"
class="block w-full text-center text-lg font-bold uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md"
@click="confirm"
>
Sign &amp; Send
</button>
<button
class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg"
class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md"
@click="cancel"
>
Cancel
@@ -460,18 +84,16 @@
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop, Watch } from "vue-facing-decorator";
import { Vue, Component, Prop } from "vue-facing-decorator";
import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
import {
createAndSubmitGive,
didInfo,
serverMessageForUser,
getHeaders,
} from "../libs/endorserServer";
import * as libsUtil from "../libs/util";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
@@ -480,38 +102,13 @@ import * as databaseUtil from "../db/databaseUtil";
import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import EntityIcon from "../components/EntityIcon.vue";
import ProjectIcon from "../components/ProjectIcon.vue";
import { PlanData } from "../interfaces/records";
@Component({
components: {
EntityIcon,
ProjectIcon,
},
})
@Component
export default class GiftedDialog extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
@Prop() fromProjectId = "";
@Prop() toProjectId = "";
@Prop({ default: false }) showProjects = false;
@Prop() isFromProjectView = false;
@Watch("showProjects")
onShowProjectsChange() {
this.updateEntityTypes();
}
@Watch("fromProjectId")
onFromProjectIdChange() {
this.updateEntityTypes();
}
@Watch("toProjectId")
onToProjectIdChange() {
this.updateEntityTypes();
}
activeDid = "";
allContacts: Array<Contact> = [];
@@ -528,84 +125,9 @@ export default class GiftedDialog extends Vue {
receiver?: libsUtil.GiverReceiverInputInfo;
unitCode = "HUR";
visible = false;
currentStep = 1;
libsUtil = libsUtil;
projects: PlanData[] = [];
didInfo = didInfo;
// Computed property to help debug template logic
get shouldShowProjects() {
const result =
(this.stepType === "giver" && this.giverEntityType === "project") ||
(this.stepType === "recipient" && this.recipientEntityType === "project");
return result;
}
// Computed property to check if current selection would create a conflict
get hasPersonConflict() {
// Only check for conflicts when both entities are persons
if (this.giverEntityType !== "person" || this.recipientEntityType !== "person") {
return false;
}
// Check if giver and recipient are the same person
if (this.giver?.did && this.receiver?.did && this.giver.did === this.receiver.did) {
return true;
}
return false;
}
// Computed property to check if a contact would create a conflict when selected
wouldCreateConflict(contactDid: string) {
// Only check for conflicts when both entities are persons
if (this.giverEntityType !== "person" || this.recipientEntityType !== "person") {
return false;
}
if (this.stepType === "giver") {
// If selecting as giver, check if it conflicts with current recipient
return this.receiver?.did === contactDid;
} else if (this.stepType === "recipient") {
// If selecting as recipient, check if it conflicts with current giver
return this.giver?.did === contactDid;
}
return false;
}
stepType = "giver";
giverEntityType = "person" as "person" | "project";
recipientEntityType = "person" as "person" | "project";
updateEntityTypes() {
// Reset and set entity types based on current context
this.giverEntityType = "person";
this.recipientEntityType = "person";
// Determine entity types based on current context
if (this.showProjects) {
// HomeView "Project" button or ProjectViewView "Given by This"
this.giverEntityType = "project";
this.recipientEntityType = "person";
} else if (this.fromProjectId) {
// ProjectViewView "Given by This" button (project is giver)
this.giverEntityType = "project";
this.recipientEntityType = "person";
} else if (this.toProjectId) {
// ProjectViewView "Given to This" button (project is recipient)
this.giverEntityType = "person";
this.recipientEntityType = "project";
} else {
// HomeView "Person" button
this.giverEntityType = "person";
this.recipientEntityType = "person";
}
}
async open(
giver?: libsUtil.GiverReceiverInputInfo,
receiver?: libsUtil.GiverReceiverInputInfo,
@@ -618,14 +140,10 @@ export default class GiftedDialog extends Vue {
this.giver = giver;
this.prompt = prompt || "";
this.receiver = receiver;
// if we show "given to user" selection, default checkbox to true
this.amountInput = "0";
this.callbackOnSuccess = callbackOnSuccess;
this.offerId = offerId || "";
this.currentStep = giver ? 2 : 1;
this.stepType = "giver";
// Update entity types based on current props
this.updateEntityTypes();
try {
let settings = await databaseUtil.retrieveSettingsForActiveAccount();
@@ -656,16 +174,7 @@ export default class GiftedDialog extends Vue {
this.allContacts,
);
}
if (
this.giverEntityType === "project" ||
this.recipientEntityType === "project"
) {
await this.loadProjects();
} else {
// Clear projects array when not needed
this.projects = [];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
logger.error("Error retrieving settings from database:", err);
this.$notify(
@@ -715,7 +224,6 @@ export default class GiftedDialog extends Vue {
this.amountInput = "0";
this.prompt = "";
this.unitCode = "HUR";
this.currentStep = 1;
}
async confirm() {
@@ -758,20 +266,6 @@ export default class GiftedDialog extends Vue {
return;
}
// Check for person conflict
if (this.hasPersonConflict) {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "You cannot select the same person as both giver and recipient.",
},
3000,
);
return;
}
this.close();
this.$notify(
{
@@ -810,50 +304,24 @@ export default class GiftedDialog extends Vue {
unitCode: string = "HUR",
) {
try {
// Determine the correct parameters based on entity types
let fromDid: string | undefined;
let toDid: string | undefined;
let fulfillsProjectHandleId: string | undefined;
let providerPlanHandleId: string | undefined;
if (this.giverEntityType === "project" && this.recipientEntityType === "person") {
// Project-to-person gift
fromDid = undefined; // No person giver
toDid = recipientDid as string; // Person recipient
fulfillsProjectHandleId = undefined; // No project recipient
providerPlanHandleId = this.giver?.handleId; // Project giver
} else if (this.giverEntityType === "person" && this.recipientEntityType === "project") {
// Person-to-project gift
fromDid = giverDid as string; // Person giver
toDid = undefined; // No person recipient
fulfillsProjectHandleId = this.toProjectId; // Project recipient
providerPlanHandleId = undefined; // No project giver
} else {
// Person-to-person gift
fromDid = giverDid as string;
toDid = recipientDid as string;
fulfillsProjectHandleId = undefined;
providerPlanHandleId = undefined;
}
const result = await createAndSubmitGive(
this.axios,
this.apiServer,
this.activeDid,
fromDid,
toDid,
giverDid as string,
recipientDid as string,
description,
amount,
unitCode,
fulfillsProjectHandleId,
this.toProjectId,
this.offerId,
false,
undefined,
providerPlanHandleId,
this.fromProjectId,
);
if (!result.success) {
const errorMessage = this.getGiveCreationErrorMessage(result);
const errorMessage = result.error;
logger.error("Error with give creation result:", result);
this.$notify(
{
@@ -899,19 +367,6 @@ export default class GiftedDialog extends Vue {
// Helper functions for readability
/**
* @param result direct response eg. ErrorResult or SuccessResult (potentially with embedded "data")
* @returns best guess at an error message
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getGiveCreationErrorMessage(result: any) {
return (
result.error?.userMessage ||
result.error?.error ||
result.response?.data?.error?.message
);
}
explainData() {
this.$notify(
{
@@ -923,114 +378,6 @@ export default class GiftedDialog extends Vue {
-1,
);
}
selectGiver(contact?: Contact) {
if (contact) {
this.giver = {
did: contact.did,
name: contact.name || contact.did,
};
} else {
this.giver = {
did: "",
name: "Unnamed",
};
}
this.currentStep = 2;
}
goBackToStep1(step: string) {
this.stepType = step;
this.currentStep = 1;
}
async loadProjects() {
try {
const response = await fetch(this.apiServer + "/api/v2/report/plans", {
method: "GET",
headers: await getHeaders(this.activeDid),
});
if (response.status !== 200) {
throw new Error("Failed to load projects");
}
const results = await response.json();
if (results.data) {
this.projects = results.data;
}
} catch (error) {
logger.error("Error loading projects:", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to load projects",
},
3000,
);
}
}
selectProject(project: PlanData) {
this.giver = {
did: project.handleId,
name: project.name,
image: project.image,
handleId: project.handleId,
};
this.receiver = {
did: this.activeDid,
name: "You",
};
this.currentStep = 2;
}
selectRecipient(contact?: Contact) {
if (contact) {
this.receiver = {
did: contact.did,
name: contact.name || contact.did,
};
} else {
this.receiver = {
did: "",
name: "Unnamed",
};
}
this.currentStep = 2;
}
selectRecipientProject(project: PlanData) {
this.receiver = {
did: project.handleId,
name: project.name,
image: project.image,
handleId: project.handleId,
};
this.currentStep = 2;
}
// Computed property for the query parameters
get giftedDetailsQuery() {
return {
amountInput: this.amountInput,
description: this.description,
giverDid: this.giverEntityType === "person" ? this.giver?.did : undefined,
giverName: this.giver?.name,
offerId: this.offerId,
fulfillsProjectId: this.giverEntityType === "person" && this.recipientEntityType === "project"
? this.toProjectId
: undefined,
providerProjectId: this.giverEntityType === "project" && this.recipientEntityType === "person"
? this.giver?.handleId
: this.fromProjectId,
recipientDid: this.receiver?.did,
recipientName: this.receiver?.name,
unitCode: this.unitCode,
};
}
}
</script>

View File

@@ -48,12 +48,15 @@
<span>
{{ didInfo(visDid) }}
<span v-if="!serverUtil.isEmptyOrHiddenDid(visDid)">
<a :href="`/did/${visDid}`" class="text-blue-500">
<router-link
:to="{ path: '/did/' + encodeURIComponent(visDid) }"
class="text-blue-500"
>
<font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a>
</router-link>
</span>
</span>
</div>

View File

@@ -250,7 +250,7 @@ export default class OfferDialog extends Vue {
);
if (!result.success) {
const errorMessage = this.getOfferCreationErrorMessage(result);
const errorMessage = result.error;
logger.error("Error with offer creation result:", result);
this.$notify(
{
@@ -290,21 +290,6 @@ export default class OfferDialog extends Vue {
);
}
}
// Helper functions for readability
/**
* @param result direct response eg. ErrorResult or SuccessResult (potentially with embedded "data")
* @returns best guess at an error message
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getOfferCreationErrorMessage(result: any) {
return (
serverMessageForUser(result) ||
result.error?.userMessage ||
result.error?.error
);
}
}
</script>

View File

@@ -38,14 +38,14 @@ export default class TopMessage extends Vue {
settings.apiServer !== AppString.PROD_ENDORSER_API_SERVER
) {
const didPrefix = settings.activeDid?.slice(11, 15);
this.message = "You're linked to a non-prod server, user " + didPrefix;
this.message = "You're not using prod, user " + didPrefix;
} else if (
settings.warnIfProdServer &&
settings.apiServer === AppString.PROD_ENDORSER_API_SERVER
) {
const didPrefix = settings.activeDid?.slice(11, 15);
this.message =
"You're linked to the production server, user " + didPrefix;
"You are using prod, user " + didPrefix;
}
} catch (err: unknown) {
this.$notify(

View File

@@ -1,6 +1,4 @@
import { AxiosResponse } from "axios";
import { GiverReceiverInputInfo } from "../libs/util";
import { ErrorResult, ResultWithType } from "./common";
export interface GiverOutputInfo {
action: string;
@@ -47,12 +45,3 @@ export interface ProviderInfo {
*/
linkConfirmed: boolean;
}
// Type for createAndSubmitClaim result
export type CreateAndSubmitClaimResult = SuccessResult | ErrorResult;
// Update SuccessResult to use ClaimResult
export interface SuccessResult extends ResultWithType {
type: "success";
response: AxiosResponse<ClaimResult>;
}

View File

@@ -15,10 +15,6 @@ export interface GenericCredWrapper<T extends GenericVerifiableCredential> {
publicUrls?: Record<string, string>;
}
export interface ResultWithType {
type: string;
}
export interface ErrorResponse {
error?: {
message?: string;
@@ -30,11 +26,6 @@ export interface InternalError {
userMessage?: string;
}
export interface ErrorResult extends ResultWithType {
type: "error";
error: InternalError;
}
export interface KeyMeta {
did: string;
publicKeyHex: string;

View File

@@ -30,7 +30,7 @@ import { z } from "zod";
// Add a union type of all valid route paths
export const VALID_DEEP_LINK_ROUTES = [
"user-profile",
"project-details",
"project",
"onboard-meeting-setup",
"invite-one-accept",
"contact-import",
@@ -61,7 +61,7 @@ export const deepLinkSchemas = {
"user-profile": z.object({
id: z.string(),
}),
"project-details": z.object({
"project": z.object({
id: z.string(),
}),
"onboard-meeting-setup": z.object({

View File

@@ -1,5 +1,6 @@
export type {
// From common.ts
CreateAndSubmitClaimResult,
GenericCredWrapper,
GenericVerifiableCredential,
KeyMeta,
@@ -18,11 +19,6 @@ export type {
RegisterActionClaim,
} from "./claims";
export type {
// From claims-result.ts
CreateAndSubmitClaimResult,
} from "./claims-result";
export type {
// From records.ts
PlanSummaryRecord,

View File

@@ -979,7 +979,7 @@ export const createAndSubmitConfirmation = async (
handleId: string | undefined,
apiServer: string,
axios: Axios,
) => {
): Promise<CreateAndSubmitClaimResult> => {
const goodClaim = removeSchemaContext(
removeVisibleToDids(
addLastClaimOrHandleAsIdIfMissing(claim, lastClaimId, handleId),

View File

@@ -29,7 +29,6 @@ import {
faCircleCheck,
faCircleInfo,
faCircleQuestion,
faCircleRight,
faCircleUser,
faClock,
faCoins,
@@ -61,7 +60,6 @@ import {
faLightbulb,
faLink,
faLocationDot,
faLock,
faLongArrowAltLeft,
faLongArrowAltRight,
faMagnifyingGlass,
@@ -81,7 +79,6 @@ import {
faSquareCaretDown,
faSquareCaretUp,
faSquarePlus,
faThumbtack,
faTrashCan,
faTriangleExclamation,
faUser,
@@ -114,7 +111,6 @@ library.add(
faCircleCheck,
faCircleInfo,
faCircleQuestion,
faCircleRight,
faCircleUser,
faClock,
faCoins,
@@ -146,7 +142,6 @@ library.add(
faLightbulb,
faLink,
faLocationDot,
faLock,
faLongArrowAltLeft,
faLongArrowAltRight,
faMagnifyingGlass,
@@ -166,7 +161,6 @@ library.add(
faSquareCaretDown,
faSquareCaretUp,
faSquarePlus,
faThumbtack,
faTrashCan,
faTriangleExclamation,
faUser,

View File

@@ -49,8 +49,6 @@ import { insertDidSpecificSettings, parseJsonField } from "../db/databaseUtil";
export interface GiverReceiverInputInfo {
did?: string;
name?: string;
image?: string;
handleId?: string;
}
export enum OnboardPage {

View File

@@ -28,7 +28,7 @@
*
* Supported Routes:
* - user-profile: View user profile
* - project-details: View project details
* - project: View project details
* - onboard-meeting-setup: Setup onboarding meeting
* - invite-one-accept: Accept invitation
* - contact-import: Import contacts
@@ -81,18 +81,16 @@ export class DeepLinkHandler {
string,
{ name: string; paramKey?: string }
> = {
"user-profile": { name: "user-profile" },
"project-details": { name: "project-details" },
"onboard-meeting-setup": { name: "onboard-meeting-setup" },
"invite-one-accept": { name: "invite-one-accept" },
"contact-import": { name: "contact-import" },
"confirm-gift": { name: "confirm-gift" },
claim: { name: "claim" },
"claim-cert": { name: "claim-cert" },
"claim": { name: "claim" },
"claim-add-raw": { name: "claim-add-raw" },
"contact-edit": { name: "contact-edit", paramKey: "did" },
contacts: { name: "contacts" },
did: { name: "did", paramKey: "did" },
"claim-cert": { name: "claim-cert" },
"confirm-gift": { name: "confirm-gift" },
"did": { name: "did", paramKey: "did" },
"invite-one-accept": { name: "invite-one-accept" },
"onboard-meeting-members": { name: "onboard-meeting-members" },
"onboard-meeting-setup": { name: "onboard-meeting-setup" },
"project": { name: "project" },
"user-profile": { name: "user-profile" },
};
/**

View File

@@ -5,6 +5,7 @@ import {
CameraSource,
CameraDirection,
} from "@capacitor/camera";
import { Capacitor } from "@capacitor/core";
import { Share } from "@capacitor/share";
import {
SQLiteConnection,
@@ -247,7 +248,7 @@ export class CapacitorPlatformService implements PlatformService {
hasFileSystem: true,
hasCamera: true,
isMobile: true,
isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent),
isIOS: Capacitor.getPlatform() === "ios",
hasFileDownload: false,
needsFileHandlingInstructions: true,
isNativeApp: true,

View File

@@ -198,7 +198,7 @@ export default class ClaimAddRawView extends Vue {
this.apiServer,
this.axios,
);
if (result.type === "success") {
if (result.success) {
this.$notify(
{
group: "alert",

View File

@@ -46,6 +46,7 @@
</h2>
<div class="flex justify-center w-full">
<router-link
v-if="veriClaim.id"
:to="'/claim-cert/' + encodeURIComponent(veriClaim.id)"
class="text-blue-500 mt-2"
title="Printable Certificate"
@@ -292,12 +293,17 @@
<div class="text-sm">
{{ didInfo(confirmerId) }}
<span v-if="!serverUtil.isEmptyOrHiddenDid(confirmerId)">
<a :href="`/did/${confirmerId}`" class="text-blue-500">
<router-link
:to="{
path: '/did/' + encodeURIComponent(confirmerId),
}"
class="text-blue-500"
>
<font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a>
</router-link>
</span>
</div>
</div>
@@ -329,12 +335,17 @@
<div class="text-sm">
{{ didInfo(confsVisibleTo) }}
<span v-if="!serverUtil.isEmptyOrHiddenDid(confsVisibleTo)">
<a :href="`/did/${confsVisibleTo}`" class="text-blue-500">
<router-link
:to="{
path: '/did/' + encodeURIComponent(confsVisibleTo),
}"
class="text-blue-500"
>
<font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a>
</router-link>
</span>
</div>
</div>
@@ -443,12 +454,17 @@
<span>
{{ didInfo(visDid) }}
<span v-if="!serverUtil.isEmptyOrHiddenDid(visDid)">
<a :href="`/did/${visDid}`" class="text-blue-500">
<router-link
:to="{
path: '/did/' + encodeURIComponent(visDid),
}"
class="text-blue-500"
>
<font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a>
</router-link>
</span>
<span v-if="veriClaim.publicUrls?.[visDid]"
>, found at&nbsp;<a
@@ -925,7 +941,7 @@ export default class ClaimView extends Vue {
this.apiServer,
this.axios,
);
if (result.type === "success") {
if (result.success) {
this.$notify(
{
group: "alert",

View File

@@ -407,14 +407,14 @@
</a>
</div>
<div class="mt-2 ml-2">
<a
<router-link
v-if="isRegistered"
class="text-blue-500 cursor-pointer"
:href="urlForNewGive"
:to="urlForNewGive"
>
<font-awesome icon="file-lines" />
Record a Give Similar to the Original
</a>
</router-link>
</div>
</div>
</div>
@@ -831,7 +831,7 @@ export default class ConfirmGiftView extends Vue {
this.apiServer,
this.axios,
);
if (result.type === "success") {
if (result.success) {
this.$notify(
{
group: "alert",

View File

@@ -11,7 +11,7 @@
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
><font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</router-link>
{{ stepType === "giver" ? "Given by..." : "Given to..." }}
Given by...
</h1>
</div>
@@ -31,7 +31,7 @@
<button
type="button"
class="block w-full text-center text-sm uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-1.5 rounded-md"
@click="openDialog('Unnamed')"
@click="openDialog()"
>
<font-awesome icon="gift" class="fa-fw"></font-awesome>
</button>
@@ -65,13 +65,7 @@
</li>
</ul>
<GiftedDialog
ref="customDialog"
:from-project-id="fromProjectId"
:to-project-id="toProjectId"
:show-projects="showProjects"
:is-from-project-view="isFromProjectView"
/>
<GiftedDialog ref="customDialog" :to-project-id="projectId" />
</section>
</template>
@@ -103,24 +97,6 @@ export default class ContactGiftingView extends Vue {
description = "";
projectId = "";
prompt = "";
recipientProjectName = "";
recipientProjectImage = "";
recipientProjectHandleId = "";
// New context parameters
stepType = "giver";
giverEntityType = "person" as "person" | "project";
recipientEntityType = "person" as "person" | "project";
giverProjectId = "";
giverProjectName = "";
giverProjectImage = "";
giverProjectHandleId = "";
giverDid = "";
recipientDid = "";
fromProjectId = "";
toProjectId = "";
showProjects = false;
isFromProjectView = false;
async created() {
try {
@@ -148,41 +124,9 @@ export default class ContactGiftingView extends Vue {
);
}
this.projectId =
(this.$route.query["recipientProjectId"] as string) || "";
this.recipientProjectName =
(this.$route.query["recipientProjectName"] as string) || "";
this.recipientProjectImage =
(this.$route.query["recipientProjectImage"] as string) || "";
this.recipientProjectHandleId =
(this.$route.query["recipientProjectHandleId"] as string) || "";
this.projectId = (this.$route.query["projectId"] as string) || "";
this.prompt = (this.$route.query["prompt"] as string) ?? this.prompt;
// Read new context parameters
this.stepType = (this.$route.query["stepType"] as string) || "giver";
this.giverEntityType =
(this.$route.query["giverEntityType"] as "person" | "project") ||
"person";
this.recipientEntityType =
(this.$route.query["recipientEntityType"] as "person" | "project") ||
"person";
this.giverProjectId =
(this.$route.query["giverProjectId"] as string) || "";
this.giverProjectName =
(this.$route.query["giverProjectName"] as string) || "";
this.giverProjectImage =
(this.$route.query["giverProjectImage"] as string) || "";
this.giverProjectHandleId =
(this.$route.query["giverProjectHandleId"] as string) || "";
this.giverDid = (this.$route.query["giverDid"] as string) || "";
this.recipientDid = (this.$route.query["recipientDid"] as string) || "";
this.fromProjectId = (this.$route.query["fromProjectId"] as string) || "";
this.toProjectId = (this.$route.query["toProjectId"] as string) || "";
this.showProjects =
(this.$route.query["showProjects"] as string) === "true";
this.isFromProjectView =
(this.$route.query["isFromProjectView"] as string) === "true";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
logger.error("Error retrieving settings & contacts:", err);
@@ -200,108 +144,17 @@ export default class ContactGiftingView extends Vue {
}
}
openDialog(contact?: GiverReceiverInputInfo | "Unnamed") {
if (contact === "Unnamed") {
// Special case: Pass undefined to trigger Step 1, but with "Unnamed" pre-selected
let recipient: GiverReceiverInputInfo;
let giver: GiverReceiverInputInfo | undefined;
if (this.stepType === "giver") {
// We're selecting a giver, so recipient is either a project or the current user
if (this.recipientEntityType === "project") {
recipient = {
did: this.recipientProjectHandleId,
name: this.recipientProjectName,
image: this.recipientProjectImage,
handleId: this.recipientProjectHandleId,
};
} else {
recipient = { did: this.activeDid, name: "You" };
}
giver = undefined; // Will be set to "Unnamed" in GiftedDialog
} else {
// We're selecting a recipient, so recipient is "Unnamed" and giver is preserved from context
recipient = { did: "", name: "Unnamed" };
// Preserve the existing giver from the context
if (this.giverEntityType === "project") {
giver = {
did: this.giverProjectHandleId,
name: this.giverProjectName,
image: this.giverProjectImage,
handleId: this.giverProjectHandleId,
};
} else if (this.giverDid) {
giver = {
did: this.giverDid,
name: this.giverProjectName || "Someone",
};
} else {
giver = { did: this.activeDid, name: "You" };
}
}
openDialog(giver?: GiverReceiverInputInfo) {
const recipient = this.projectId
? undefined
: { did: this.activeDid, name: "you" };
(this.$refs.customDialog as GiftedDialog).open(
giver,
recipient,
undefined,
this.stepType === "giver" ? "Given by Unnamed" : "Given to Unnamed",
"Given by " + (giver?.name || "someone not named"),
this.prompt,
);
// Immediately select "Unnamed" and move to Step 2
(this.$refs.customDialog as GiftedDialog).selectGiver();
} else {
// Regular case: contact is a GiverReceiverInputInfo
let giver: GiverReceiverInputInfo;
let recipient: GiverReceiverInputInfo;
if (this.stepType === "giver") {
// We're selecting a giver, so the contact becomes the giver
giver = contact as GiverReceiverInputInfo; // Safe because we know contact is not "Unnamed" or undefined
// Recipient is either a project or the current user
if (this.recipientEntityType === "project") {
recipient = {
did: this.recipientProjectHandleId,
name: this.recipientProjectName,
image: this.recipientProjectImage,
handleId: this.recipientProjectHandleId,
};
} else {
recipient = { did: this.activeDid, name: "You" };
}
} else {
// We're selecting a recipient, so the contact becomes the recipient
recipient = contact as GiverReceiverInputInfo; // Safe because we know contact is not "Unnamed" or undefined
// Preserve the existing giver from the context
if (this.giverEntityType === "project") {
giver = {
did: this.giverProjectHandleId,
name: this.giverProjectName,
image: this.giverProjectImage,
handleId: this.giverProjectHandleId,
};
} else if (this.giverDid) {
giver = {
did: this.giverDid,
name: this.giverProjectName || "Someone",
};
} else {
giver = { did: this.activeDid, name: "You" };
}
}
(this.$refs.customDialog as GiftedDialog).open(
giver,
recipient,
undefined,
this.stepType === "giver"
? "Given by " + (contact?.name || "someone not named")
: "Given to " + (contact?.name || "someone not named"),
this.prompt,
);
}
}
}
</script>

View File

@@ -788,7 +788,7 @@ export default class DiscoverView extends Vue {
const route = {
path: this.isProjectsActive
? "/project/" + encodeURIComponent(id)
: "/userProfile/" + encodeURIComponent(id),
: "/user-profile/" + encodeURIComponent(id),
};
this.$router.push(route);
}

View File

@@ -826,7 +826,7 @@ export default class GiftedDetails extends Vue {
}
if (!result.success) {
const errorMessage = this.getGiveCreationErrorMessage(result);
const errorMessage = result.error;
logger.error("Error with give creation result:", result);
this.$notify(
{
@@ -899,19 +899,6 @@ export default class GiftedDetails extends Vue {
// Helper functions for readability
/**
* @param result direct response eg. ErrorResult or SuccessResult (potentially with embedded "data")
* @returns best guess at an error message
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getGiveCreationErrorMessage(result: any) {
return (
result.error?.userMessage ||
result.error?.error ||
result.response?.data?.error?.message
);
}
explainData() {
this.$notify(
{

View File

@@ -24,11 +24,11 @@
<!-- eslint-disable prettier/prettier max-len -->
<div>
<p>
This app focuses on gifts & gratitude, using them to build cool things together with your network.
This app focuses on raw gratitude, using it to build cool things together with your network.
</p>
<p class="ml-4">
If you'd like to see the page-by-page help,
If you'd like to see the page-by-page help again,
<span
class="text-blue-500 cursor-pointer"
@click="unsetFinishedOnboarding()"
@@ -555,9 +555,6 @@
initiative.
</p>
<h2 class="text-xl font-semibold">What app version is this?</h2>
<p>{{ package.version }} ({{ commitHash }})</p>
<h2 class="text-xl font-semibold">
I have other questions or feedback, like getting a new profile or removing my data or requesting an improvement.
</h2>
@@ -567,6 +564,28 @@
>info@TimeSafari.app</a
>
</p>
<h2 class="text-xl font-semibold">What app version is this?</h2>
<p>{{ package.version }} ({{ commitHash }})</p>
<div v-if="Capacitor.isNativePlatform()">
<h2 class="text-xl font-semibold">
Do I have the latest version?
</h2>
<p v-if="Capacitor.getPlatform() === 'ios'">
<a href="https://apps.apple.com/us/app/time-safari/id6742664907" target="_blank" class="text-blue-500">
Check the App Store.
</a>
</p>
<p v-else-if="Capacitor.getPlatform() === 'android'">
<a href="https://timesafari.app/app.apk" target="_blank" class="text-blue-500">
Download the latest APK to see.
</a>
</p>
<p v-else>
Sorry, your platform of '{{ Capacitor.getPlatform() }}' is not recognized.
</p>
</div>
</div>
<!-- eslint enable -->
</section>
@@ -603,6 +622,7 @@ export default class HelpView extends Vue {
showVerifiable = false;
APP_SERVER = APP_SERVER;
Capacitor = Capacitor;
// Ideally, we put no functionality in here, especially in the setup,
// because we never want this page to have a chance of throwing an error.

View File

@@ -117,73 +117,101 @@ Raymer * @version 1.0.0 */
</div>
<div v-else id="sectionRecordSomethingGiven">
<!-- Record Quick-Action -->
<div class="mb-6">
<div class="flex gap-2 items-center mb-2">
<h2 class="text-xl font-bold">Record something given by:</h2>
<!-- !isCreatingIdentifier && isRegistered -->
<!-- show the actions for recognizing a give -->
<div class="flex">
<h2 class="text-xl font-bold">What have you seen someone do?</h2>
<button
class="block ms-auto text-center text-white bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-2 rounded-full"
class="ml-2 block text-xs text-center bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1 rounded-md"
@click="openGiftedPrompts()"
>
<font-awesome
icon="lightbulb"
class="block text-center w-[1em]"
<font-awesome icon="lightbulb" class="fa-fw" />
</button>
</div>
<ul
class="grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-x-3 gap-y-5 text-center mt-4"
>
<li @click="openDialog()">
<img
src="../assets/blank-square.svg"
class="mx-auto border border-blue-500 rounded-md mb-1 cursor-pointer"
/>
</button>
</div>
<div class="grid grid-cols-2 gap-2">
<button
type="button"
class="text-center text-base uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-2 rounded-lg"
@click="openDialogPerson()"
<h3
class="text-xs text-blue-500 italic font-medium text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer"
>
<font-awesome icon="user" />
Person
</button>
<button
type="button"
class="text-center text-base uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-2 rounded-lg"
@click="openProjectDialog()"
Unnamed/Unknown
</h3>
</li>
<li v-if="allContacts.length === 0" class="text-sm">
(Add friends to see more people worthy of recognition.)
</li>
<li
v-for="contact in allContacts.slice(0, 6)"
:key="contact.did"
@click="openDialog(contact)"
>
<font-awesome icon="folder-open" />
Project
</button>
</div>
</div>
<EntityIcon
:contact="contact"
:icon-size="64"
class="mx-auto border border-blue-500 rounded-md mb-1 cursor-pointer"
/>
<h3
class="text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer"
>
{{ contact.name || contact.did }}
</h3>
</li>
<li>
<router-link
v-if="allContacts.length >= 6"
:to="{ name: 'contact-gift' }"
class="flex align-bottom text-xs text-blue-500 mt-12 cursor-pointer"
>
... or someone else...
</router-link>
</li>
</ul>
</div>
</div>
</div>
</div>
<GiftedDialog ref="customDialog" :show-projects="showProjectsDialog" />
<GiftedDialog ref="customDialog" />
<GiftedPrompts ref="giftedPrompts" />
<FeedFilters ref="feedFilters" />
<div class="relative">
<button
v-if="isRegistered"
class="absolute right-6 bottom-0 transform translate-y-1/2 text-center text-4xl leading-none bg-green-600 text-white w-14 py-2.5 rounded-full"
@click="openDialog()"
>
<font-awesome icon="plus" class="fa-fw" />
</button>
</div>
<!-- Results List -->
<div class="mt-4 mb-4">
<div class="flex gap-2 items-center mb-3">
<h2 class="text-xl font-bold">Latest Activity</h2>
<div class="flex items-center mb-4">
<h2 class="text-xl font-bold flex items-center gap-4">
Latest Activity
<button
v-if="resultsAreFiltered()"
class="block ms-auto text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-2 rounded-full"
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] px-3 py-1.5 rounded-md text-xs text-white"
@click="openFeedFilters()"
>
<font-awesome
icon="filter"
class="block text-center w-[1em] translate-y-[0.05em]"
/>
<font-awesome icon="filter" class="fa-fw" />
</button>
<button
v-else
class="block ms-auto text-center text-white bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-2 rounded-full"
class="bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] px-3 py-1.5 rounded-md text-xs text-white"
@click="openFeedFilters()"
>
<font-awesome
icon="filter"
class="block text-center w-[1em] translate-y-[0.05em]"
/>
<font-awesome icon="filter" class="fa-fw" />
</button>
</h2>
</div>
<div
@@ -446,7 +474,6 @@ export default class HomeView extends Vue {
selectedImageData: Blob | null = null;
isImageViewerOpen = false;
imageCache: Map<string, Blob | null> = new Map();
showProjectsDialog = false;
/**
* Initializes the component on mount
@@ -1610,34 +1637,18 @@ export default class HomeView extends Vue {
* @param giver Optional contact info for giver
* @param description Optional gift description
*/
openDialog(giver?: GiverReceiverInputInfo | "Unnamed", description?: string) {
if (giver === "Unnamed") {
// Special case: Pass undefined to trigger Step 1, but with "Unnamed" pre-selected
(this.$refs.customDialog as GiftedDialog).open(
undefined,
{
did: this.activeDid,
name: "You",
} as GiverReceiverInputInfo,
undefined,
"Given by Unnamed",
description,
);
// Immediately select "Unnamed" and move to Step 2
(this.$refs.customDialog as GiftedDialog).selectGiver();
} else {
openDialog(giver?: GiverReceiverInputInfo, description?: string) {
(this.$refs.customDialog as GiftedDialog).open(
giver,
{
did: this.activeDid,
name: "You",
name: "you",
} as GiverReceiverInputInfo,
undefined,
"Given by " + (giver?.name || "someone not named"),
description,
);
}
}
/**
* Opens prompts for gift ideas
@@ -1832,7 +1843,7 @@ export default class HomeView extends Vue {
this.axios,
);
if (result.type === "success") {
if (result.success) {
this.$notify(
{
group: "alert",
@@ -1870,18 +1881,5 @@ export default class HomeView extends Vue {
this.$router.push({ name: "contact-qr" });
}
}
openDialogPerson(
giver?: GiverReceiverInputInfo | "Unnamed",
description?: string,
) {
this.showProjectsDialog = false;
this.openDialog(giver, description);
}
openProjectDialog() {
this.showProjectsDialog = true;
(this.$refs.customDialog as any).open();
}
}
</script>

View File

@@ -52,16 +52,24 @@
icon="user"
class="fa-fw text-slate-400"
></font-awesome>
<span class="truncate inline-block max-w-[calc(100%-2rem)]">
{{ issuerInfoObject?.displayName }}
<span v-if="!serverUtil.isEmptyOrHiddenDid(issuer)">
<a :href="`/did/${issuer}`" class="text-blue-500">
</span>
<span class="inline-flex items-center">
<router-link
:to="{
path: '/did/' + encodeURIComponent(issuer),
}"
class="text-blue-500 ml-1"
title="See more about this person"
>
<font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a>
</router-link>
</span>
<span v-else-if="serverUtil.isHiddenDid(issuer)">
<span v-if="serverUtil.isHiddenDid(issuer)" class="ml-1">
<font-awesome
icon="info-circle"
class="fa-fw text-blue-500 cursor-pointer"
@@ -196,11 +204,63 @@
</div>
</div>
<GiftedDialog
ref="giveDialogToThis"
:to-project-id="projectId"
:is-from-project-view="true"
<div v-if="activeDid && isRegistered">
<div class="text-center">
<p class="mt-2 mt-4 text-center">Record a contribution from:</p>
</div>
<ul
class="grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-x-3 gap-y-5 text-center mb-5 mt-2"
>
<li @click="openGiftDialogToProject({ name: 'you', did: activeDid })">
<font-awesome
icon="hand"
class="fa-fw text-blue-500 text-5xl cursor-pointer"
/>
<h3
class="mt-5 text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer"
>
You
</h3>
</li>
<li @click="openGiftDialogToProject()">
<img
src="../assets/blank-square.svg"
class="mx-auto border border-blue-300 rounded-md mb-1 cursor-pointer"
/>
<h3
class="text-xs text-blue-500 italic font-medium text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer"
>
Unnamed/Unknown
</h3>
</li>
<li
v-for="contact in allContacts.slice(0, 5)"
:key="contact.did"
@click="openGiftDialogToProject(contact)"
>
<EntityIcon
:contact="contact"
:icon-size="64"
class="mx-auto border border-blue-300 rounded-md mb-1 cursor-pointer"
/>
<h3
class="text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer"
>
{{ contact.name || "(no name)" }}
</h3>
</li>
<li>
<span
v-if="allContacts.length >= 5"
class="flex align-bottom text-xs text-blue-500 mt-12 cursor-pointer"
@click="onClickAllContactsGifting()"
>
... or someone else...
</span>
</li>
</ul>
</div>
<GiftedDialog ref="giveDialogToThis" :to-project-id="projectId" />
<!-- Offers & Gifts to & from this -->
<div class="grid items-start grid-cols-1 sm:grid-cols-3 gap-4 mt-4">
@@ -466,12 +526,7 @@
</button>
</div>
</div>
<GiftedDialog
ref="giveDialogFromThis"
:from-project-id="projectId"
:show-projects="true"
:is-from-project-view="true"
/>
<GiftedDialog ref="giveDialogFromThis" :from-project-id="projectId" />
<h3 class="text-lg font-bold mb-3 mt-4">
Benefitted From This Project
@@ -1182,53 +1237,21 @@ export default class ProjectViewView extends Vue {
);
}
openGiftDialogToProject(
contact?: libsUtil.GiverReceiverInputInfo | "Unnamed",
) {
if (contact === "Unnamed") {
// Special case: Pass undefined to trigger Step 1, but with "Unnamed" pre-selected
openGiftDialogToProject(contact?: libsUtil.GiverReceiverInputInfo) {
(this.$refs.giveDialogToThis as GiftedDialog).open(
contact,
undefined,
undefined,
undefined,
"Given by Unnamed to this project",
(contact?.name || "Someone not named") + ` gave to this project`,
);
// Immediately select "Unnamed" and move to Step 2
(this.$refs.giveDialogToThis as GiftedDialog).selectGiver();
} else {
// Open straight to Step 2 with current user as giver and current project as recipient
(this.$refs.giveDialogToThis as GiftedDialog).open(
{
did: this.activeDid,
name: "You",
},
{
did: this.issuer,
name: this.name,
handleId: this.projectId,
image: this.imageUrl,
},
undefined,
`Given to ${this.name}`,
);
}
}
openGiftDialogFromProject() {
// Set the project as giver and the current user as recipient
(this.$refs.giveDialogFromThis as GiftedDialog).open(
{
did: undefined,
name: this.name,
handleId: this.projectId,
image: this.imageUrl,
},
undefined,
{ did: this.activeDid, name: "You" },
undefined,
`${this.name} gave to you`,
undefined,
undefined,
true,
`This project gave to you`,
);
}
@@ -1410,7 +1433,7 @@ export default class ProjectViewView extends Vue {
this.apiServer,
this.axios,
);
if (result.type === "success") {
if (result.success) {
this.$notify(
{
group: "alert",

View File

@@ -155,7 +155,7 @@ import { Contact } from "../db/tables/contacts";
import {
GenericCredWrapper,
GenericVerifiableCredential,
ErrorResult,
CreateAndSubmitClaimResult,
} from "../interfaces";
import {
BVC_MEETUPS_PROJECT_CLAIM_ID,
@@ -298,13 +298,13 @@ export default class QuickActionBvcBeginView extends Vue {
}
// in parallel, make a confirmation for each selected claim and send them all to the server
const confirmResults = await Promise.allSettled(
const confirmResults: PromiseSettledResult<CreateAndSubmitClaimResult>[] = await Promise.allSettled(
this.claimsToConfirmSelected.map(async (jwtId) => {
const record = this.claimsToConfirm.find(
(claim) => claim.id === jwtId,
);
if (!record) {
return { type: "error", error: "Record not found." };
return { success: false, error: "Record not found." };
}
return createAndSubmitConfirmation(
this.activeDid,
@@ -318,8 +318,8 @@ export default class QuickActionBvcBeginView extends Vue {
);
// check for any rejected confirmations
const confirmsSucceeded = confirmResults.filter(
(result) =>
result.status === "fulfilled" && result.value.type === "success",
// 'fulfilled' is the status in a successful PromiseFulfilledResult
(result) => result.status === "fulfilled" && result.value.success,
);
if (confirmsSucceeded.length < this.claimsToConfirmSelected.length) {
logger.error("Error sending confirmations:", confirmResults);
@@ -353,7 +353,7 @@ export default class QuickActionBvcBeginView extends Vue {
undefined,
BVC_MEETUPS_PROJECT_CLAIM_ID,
);
giveSucceeded = giveResult.type === "success";
giveSucceeded = giveResult.success;
if (!giveSucceeded) {
logger.error("Error sending give:", giveResult);
this.$notify(
@@ -362,7 +362,7 @@ export default class QuickActionBvcBeginView extends Vue {
type: "danger",
title: "Error",
text:
(giveResult as ErrorResult)?.error?.userMessage ||
(giveResult as CreateAndSubmitClaimResult)?.error ||
"There was an error sending that give.",
},
5000,