Compare commits

..

23 Commits

Author SHA1 Message Date
Jose Olarte III
ab523639a5 Normalized button visual styles 2023-12-13 18:48:45 +08:00
Jose Olarte III
0484dfb253 Spacing and typography fixes 2023-12-13 18:37:03 +08:00
Jose Olarte III
c2839e8a99 Mobile-style flushed-right toggle switches 2023-12-13 18:22:15 +08:00
Jose Olarte III
e533cd3d34 Visual improvements to "set name" button 2023-12-13 18:16:15 +08:00
Jose Olarte III
18e00b95c7 Fixed size and alignment of QR code button 2023-12-13 17:41:27 +08:00
Jose Olarte III
e97cd1b1fa Minor visual improvements in "giving recognition" section 2023-12-13 17:29:53 +08:00
ccca93b9f1 change some messages, rework tasks 2023-12-11 19:19:29 -07:00
1be6c04699 prompt them to fill in their name when sharing their info 2023-12-11 16:36:50 -07:00
2c33febb0e fix location of web-push unsubscribe action 2023-12-10 20:22:41 -07:00
e6f73dc81c add an unsubscribe to the web push 2023-12-10 20:17:14 -07:00
0d55a722c5 there's no need to capitalize EVERYTHING 2023-12-10 18:55:13 -07:00
97ef78f5dd add better debug logging for web-push info 2023-12-10 18:53:58 -07:00
672abac9a9 show web-push subscription info on demand, and refine docs 2023-12-10 18:43:24 -07:00
0607fad3e5 remove the 'never' option for notifications & close on 'maybe later' 2023-12-10 17:41:03 -07:00
6aa89a1d1d update icon and favicon 2023-12-10 16:53:35 -07:00
2556d5feb9 Merge pull request 'add hash to help page for tracking exact versions' (#95) from git-hash into master
Reviewed-on: trent_larson/crowd-funder-for-time-pwa#95
2023-12-10 11:21:23 -05:00
3c1654764c add commit hash to help page 2023-12-10 09:20:03 -07:00
4c1e229d62 compute commit hash with git-describe 2023-12-10 09:18:07 -07:00
17444d75de remove references to test file 2023-12-10 08:59:25 -07:00
f2fb432d2e update documentation for going to production 2023-12-09 22:15:24 -07:00
e45689daed bump version to next beta 2023-12-09 21:21:35 -07:00
041308ebc9 fix app name so that it'll build 2023-12-09 20:39:17 -07:00
9c36bb509a bump to v 0.1.5 and other misc tweaks 2023-12-09 20:36:51 -07:00
22 changed files with 2437 additions and 2478 deletions

View File

@@ -8,8 +8,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [0.1.6]
## [0.1.5] - 2023.12.09 - 9c36bb509a9bae9bb3306d3bd9eeb144b67aa8ad
### Added
- Web push notifications
- Web push notifications (though not finalized)
- Credentials details page
- See more data without an ID
- Change units of a give
## [0.1.4] - 2023.11.20 - 7311d36726f3667ec4c68f241f91d404273ad4db
### Added
- Offer on a project
### Changed
- Automatically set as visible when importing a contact
## [0.1.3] - 2023.11.08 - 910f57ec7d2e50803ae3d04f4b927e0f5219fbde
### Added

View File

@@ -22,16 +22,23 @@ npm run lint
If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js, eg: `publicPath: "/app/time-tracker/",`
```
npm run build
```
* `npx prettier --write ./sw_scripts/`
```
npx prettier --write ./sw_scripts/
```
to make sure the service worker scripts are in proper form
...to make sure the service worker scripts are in proper form
... then copy the contents of the `sw_scripts` folder to the `dist` folder - except additional_scripts.js.
* Update the CHANGELOG.md & the version in package.json, run `npm install`, and commit. Tag wth the new version: `git tag 0.1.0`
* If production, change src/constants/app.ts DEFAULT_*_SERVER to be PROD.
* `npm run build`
* Revert src/constants/app.ts & change version to "-beta"
* `cp sw_scripts/[ns]* dist/`
... to copy the contents of the `sw_scripts` folder to the `dist` folder - except additional_scripts.js.
* `rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntu@endorser.ch:time-safari`
@@ -103,9 +110,9 @@ To add an icon, add to main.ts and reference with `fa` element and `icon` attrib
### Clear/Reset data & restart
* Clear cache for site. (In Chrome, go to `chrome://settings/cookies` and "all site data and permissions"; in Firefox, go to `about:preferences` and search for cache.)
* Unregister service worker (in Chrome, go to `chrome://serviceworker-internals/`; in Firefox, go to `about:serviceworkers` or `about:debugging`).
* Clear notification permission (in Chrome, go to `chrome://settings/content/notifications`; in Firefox, go to `about:preferences` and search).
* Clear cache for site. (In Chrome, go to `chrome://settings/cookies` and "all site data and permissions"; in Firefox, go to `about:preferences` and search for "cache" then "Manage Data".)
* Unregister service worker (in Chrome, go to `chrome://serviceworker-internals/`; in Firefox, go to `about:serviceworkers`).
* Clear notification permission (in Chrome, go to `chrome://settings/content/notifications`; in Firefox, go to `about:preferences` and search for "notifications").
* Clear Cache Storage (in Chrome, in dev tools under Application; in Firefox, in dev tools under Storage).

51
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "crowd-funder-for-time-pwa",
"version": "0.1.4",
"name": "TimeSafari",
"version": "0.1.6-beta",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "crowd-funder-for-time-pwa",
"version": "0.1.4",
"name": "TimeSafari",
"version": "0.1.6-beta",
"dependencies": {
"@ethersproject/hdnode": "^5.7.0",
"@fortawesome/fontawesome-svg-core": "^6.4.2",
@@ -33,9 +33,9 @@
"ethereum-cryptography": "^2.1.2",
"ethereumjs-util": "^7.1.5",
"ethr-did-resolver": "^8.1.2",
"git-describe": "^4.1.1",
"jdenticon": "^3.2.0",
"js-generate-password": "^0.1.9",
"js-yaml": "^4.1.0",
"localstorage-slim": "^2.5.0",
"luxon": "^3.4.3",
"merkletreejs": "^0.3.10",
@@ -59,7 +59,6 @@
"web-did-resolver": "^2.0.27"
},
"devDependencies": {
"@types/js-yaml": "^4.0.9",
"@types/leaflet": "^1.9.4",
"@types/ramda": "^0.29.3",
"@types/three": "^0.155.1",
@@ -8794,12 +8793,6 @@
"@types/istanbul-lib-report": "*"
}
},
"node_modules/@types/js-yaml": {
"version": "4.0.9",
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
"integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
"dev": true
},
"node_modules/@types/json-schema": {
"version": "7.0.13",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz",
@@ -8902,8 +8895,7 @@
"node_modules/@types/semver": {
"version": "7.5.3",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz",
"integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==",
"dev": true
"integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw=="
},
"node_modules/@types/send": {
"version": "0.17.2",
@@ -11069,7 +11061,8 @@
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"devOptional": true
},
"node_modules/array-buffer-byte-length": {
"version": "1.0.0",
@@ -16279,6 +16272,30 @@
"node": ">=6"
}
},
"node_modules/git-describe": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/git-describe/-/git-describe-4.1.1.tgz",
"integrity": "sha512-JC8ganO5kO80G8+XE98TDDjnMXQN3Estk3qdJuG2EGRF/l6zuMTMcN+8OSfQZ5FWpqIRLB015anWX4aSRgnxAQ==",
"dependencies": {
"@types/semver": "^7.3.8",
"lodash": "^4.17.21"
},
"engines": {
"node": ">=4.0.0"
},
"optionalDependencies": {
"semver": "^5.6.0"
}
},
"node_modules/git-describe/node_modules/semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"optional": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -18593,6 +18610,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"devOptional": true,
"dependencies": {
"argparse": "^2.0.1"
},
@@ -19344,8 +19362,7 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"devOptional": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.clonedeep": {
"version": "4.5.0",

View File

@@ -1,6 +1,6 @@
{
"name": "crowd-funder-for-time-pwa",
"version": "0.1.4",
"name": "TimeSafari",
"version": "0.1.6-beta",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
@@ -33,9 +33,9 @@
"ethereum-cryptography": "^2.1.2",
"ethereumjs-util": "^7.1.5",
"ethr-did-resolver": "^8.1.2",
"git-describe": "^4.1.1",
"jdenticon": "^3.2.0",
"js-generate-password": "^0.1.9",
"js-yaml": "^4.1.0",
"localstorage-slim": "^2.5.0",
"luxon": "^3.4.3",
"merkletreejs": "^0.3.10",
@@ -59,7 +59,6 @@
"web-did-resolver": "^2.0.27"
},
"devDependencies": {
"@types/js-yaml": "^4.0.9",
"@types/leaflet": "^1.9.4",
"@types/ramda": "^0.29.3",
"@types/three": "^0.155.1",

View File

@@ -1,15 +1,20 @@
tasks:
- 40 notifications :
- push, where we trigger a ServiceWorker(?) in the app to reach out and check for new data assignee:matthew
- extract private_key_hex in py-push-server webpush.py
- 08 notifications :
- get it to work on Android
- get it to work on iOS
- lock down regenerate_vapid endpoint (so only we admins can do it on demand)
- remove sleep in py-push-server app.py
- revisit "maybe" and "never" buttons on accont screen
- make the app behave correctly when App Notifications are turned off
- remove "mute notifications"
- remove sleep in py-push-server app.py?
- see if we can detect OS-level notifications if turned off
- write troubleshooting docs for notifications
- make the "App Notifications" toggle on when they turn notifications on
- make the "App Notifications" toggle off when they turn notifications off
- in py-push-server, when sending a push to a subscriber and we get on a 410 "error #106", delete the subscription record
- https://gitea.anomalistdesign.com/trent_larson/py-push-server/pulls/3/files
- remove "notification push server" advanced setting since it only makes sense on the current domain
- .3 fix the Project-location-selection map display to not show on top of bottom icons (and any other UI tweaks on the map flow) assignee-group:ui
@@ -17,6 +22,7 @@ tasks:
- .5 If notifications are not enabled, add message to front page with link/button to enable
- fix notification error when first loading the app
- add note after contact addition that they can see your info
- enhance help page instructions for debugging
- add way to test quickly a push notification
@@ -30,7 +36,6 @@ tasks:
- add VC confirmation?
- Release Minimum Viable Product :
- generate new webpush.db entry, webpush.py private_key_hex & subscription_info & vapid_claims email
- .5 deploy endorser.ch server above Dec 1 (to get plan searches by names as well as descriptions)
- 08 thorough testing for errors & edge cases
- 01 ensure ability to recover server remotely, and add redundant access
@@ -58,6 +63,9 @@ tasks:
- switch some checks for activeDid to check for isRegistered
- .2 in SeedBackupView, don't load the mnemonic and keep it in memory; only load it when they click "show"
- .5 fix cert generation on server (since it didn't happen automatically for Nov 30)
- 04 fix lack of initial notification in Firefox (on MacOS, maybe others)
- contacts v+ :
- 01 Import all the non-sensitive data (ie. contacts & settings).
- .2 show error to user when adding a duplicate contact
@@ -99,6 +107,8 @@ tasks:
- automated tests, eg. cypress
- Notifications (wake on the phone, push notifications)
- pull instead of push, maybe via scheduled runs
- have a notification pop-up on Mac screen
- Connect with phone contacts
@@ -111,9 +121,6 @@ tasks:
- Do we want split first name & last name?
- 40 notifications v+ :
- pull, w/ scheduled runs
- 01 On nearby search, if user starts changing their box but cancels and goes back to the map it is zoomed far out. Fix to fit the box better.
- 16 From the home screen, make the quick action even easier.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -169,20 +169,12 @@
>
Turn on Notifications
</button>
<div class="grid grid-cols-2 gap-2">
<button
@click="maybeLater(notification.id)"
@click="close(notification.id)"
class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
>
Maybe Later
</button>
<button
@click="never(notification.id)"
class="block w-full text-center text-md font-bold uppercase bg-rose-600 text-white px-2 py-2 rounded-md"
>
Never
</button>
</div>
</div>
</div>
</div>
@@ -238,6 +230,10 @@
</p>
<button
@click="
close(notification.id);
turnOffNotifications();
"
class="block w-full text-center text-md font-bold uppercase bg-rose-600 text-white px-2 py-2 rounded-md mb-2"
>
Turn Off Notifications
@@ -410,7 +406,10 @@ export default class App extends Vue {
private requestNotificationPermission(): Promise<NotificationPermission> {
return Notification.requestPermission().then((permission) => {
if (permission !== "granted") {
alert("We need notification permission to provide certain features.");
alert(
"Allow this app permission to make notifications for personal reminders." +
" You can adjust them at any time in your settings.",
);
throw new Error("We weren't granted permission.");
}
return permission;
@@ -452,8 +451,13 @@ export default class App extends Vue {
});
})
.catch((error) => {
console.error("An error occurred:", error);
alert("Some error occurred." + error);
console.error(
"An error occurred setting notification permissions:",
error,
);
alert(
"Some error occurred setting notification permissions. See logs.",
);
});
}
@@ -520,7 +524,7 @@ export default class App extends Vue {
private sendSubscriptionToServer(
subscription: PushSubscription,
): Promise<void> {
console.log(subscription);
console.log("About to send subscription", subscription);
return fetch("/web-push/subscribe", {
method: "POST",
headers: {
@@ -535,12 +539,49 @@ export default class App extends Vue {
});
}
never(ID: string) {
alert(ID);
async turnOffNotifications() {
let subscription;
const pushProviderSuccess = await navigator.serviceWorker.ready
.then((registration) => {
return registration.pushManager.getSubscription();
})
.then((subscript) => {
subscription = subscript;
if (subscription) {
return subscription.unsubscribe();
} else {
console.log("Subscription object is not available.");
return false;
}
})
.catch((error) => {
console.log("Push provider server communication failed:", error);
return false;
});
maybeLater(ID: string) {
alert(ID);
const pushServerSuccess = await fetch("/web-push/unsubscribe", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(subscription),
})
.then((response) => {
return response.ok;
})
.catch((error) => {
console.log("Push server communication failed:", error);
return false;
});
alert(
"Notifications are off. Push provider unsubscribe " +
(pushProviderSuccess ? "succeeded" : "failed") +
(pushProviderSuccess === pushServerSuccess ? " and" : " but") +
" push server unsubscribe " +
(pushServerSuccess ? "succeeded" : "failed") +
".",
);
}
}
</script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -16,7 +16,7 @@ export type Settings = {
activeDid?: string; // Active Decentralized ID
apiServer?: string; // API server URL
firstName?: string; // User's first name
lastName?: string; // User's last name
lastName?: string; // deprecated - put all names in firstName
lastViewedClaimId?: string; // Last viewed claim ID
lastNotifiedClaimId?: string; // Last notified claim ID
isRegistered?: boolean;

View File

@@ -39,7 +39,6 @@ const routes: Array<RouteRecordRaw> = [
name: "account",
component: () =>
import(/* webpackChunkName: "account" */ "../views/AccountViewView.vue"),
beforeEnter: enterOrStart,
},
{
path: "/claim/:id?",

350
src/util.d.ts vendored
View File

@@ -105,10 +105,7 @@ declare module "util" {
| "date"
| "regexp"
| "module";
export type CustomInspectFunction = (
depth: number,
options: InspectOptionsStylized,
) => unknown; // TODO: , inspect: inspect
export type CustomInspectFunction = (depth: number, options: InspectOptionsStylized) => any; // TODO: , inspect: inspect
export interface InspectOptionsStylized extends InspectOptions {
stylize(text: string, styleType: Style): string;
}
@@ -157,10 +154,7 @@ declare module "util" {
* @since v0.5.3
* @param format A `printf`-like format string.
*/
export function format(
format?: string,
...param: (string | number | boolean)[]
): string;
export function format(format?: any, ...param: any[]): string;
/**
* This function is identical to {@link format}, except in that it takes
* an `inspectOptions` argument which specifies options that are passed along to {@link inspect}.
@@ -172,11 +166,7 @@ declare module "util" {
* ```
* @since v10.0.0
*/
export function formatWithOptions<T extends unknown[]>(
inspectOptions: InspectOptions,
format?: string,
...param: T
): string;
export function formatWithOptions(inspectOptions: InspectOptions, format?: any, ...param: any[]): string;
/**
* Returns the string name for a numeric error code that comes from a Node.js API.
* The mapping between error codes and error names is platform-dependent.
@@ -271,10 +261,7 @@ declare module "util" {
* @experimental
* @param resource Any non-null entity, reference to which is held weakly.
*/
export function aborted(
signal: AbortSignal,
resource: unknown,
): Promise<void>;
export function aborted(signal: AbortSignal, resource: any): Promise<void>;
/**
* The `util.inspect()` method returns a string representation of `object` that is
* intended for debugging. The output of `util.inspect` may change at any time
@@ -450,13 +437,8 @@ declare module "util" {
* @param object Any JavaScript primitive or `Object`.
* @return The representation of `object`.
*/
export function inspect(
object: unknown,
showHidden?: boolean,
depth?: number | null,
color?: boolean,
): string;
export function inspect(object: unknown, options?: InspectOptions): string;
export function inspect(object: any, showHidden?: boolean, depth?: number | null, color?: boolean): string;
export function inspect(object: any, options?: InspectOptions): string;
export namespace inspect {
let colors: NodeJS.Dict<[number, number]>;
let styles: {
@@ -613,10 +595,7 @@ declare module "util" {
* @since v0.3.0
* @legacy Use ES2015 class syntax and `extends` keyword instead.
*/
export function inherits(
constructor: unknown,
superConstructor: unknown,
): void;
export function inherits(constructor: unknown, superConstructor: unknown): void;
export type DebugLoggerFunction = (msg: string, ...param: unknown[]) => void;
export interface DebugLogger extends DebugLoggerFunction {
enabled: boolean;
@@ -678,10 +657,7 @@ declare module "util" {
* @param callback A callback invoked the first time the logging function is called with a function argument that is a more optimized logging function.
* @return The logging function
*/
export function debuglog(
section: string,
callback?: (fn: DebugLoggerFunction) => void,
): DebugLogger;
export function debuglog(section: string, callback?: (fn: DebugLoggerFunction) => void): DebugLogger;
export const debug: typeof debuglog;
/**
* Returns `true` if the given `object` is a `Boolean`. Otherwise, returns `false`.
@@ -771,9 +747,7 @@ declare module "util" {
* @since v0.11.5
* @deprecated Since v4.0.0 - Use `value === undefined || value === null` instead.
*/
export function isNullOrUndefined(
object: unknown,
): object is null | undefined;
export function isNullOrUndefined(object: unknown): object is null | undefined;
/**
* Returns `true` if the given `object` is a `Number`. Otherwise, returns `false`.
*
@@ -944,11 +918,7 @@ declare module "util" {
* @param code A deprecation code. See the `list of deprecated APIs` for a list of codes.
* @return The deprecated function wrapped to emit a warning.
*/
export function deprecate<T extends (...args: unknown[]) => unknown>(
fn: T,
msg: string,
code?: string,
): T;
export function deprecate<T extends Function>(fn: T, msg: string, code?: string): T;
/**
* Returns `true` if there is deep strict equality between `val1` and `val2`.
* Otherwise, returns `false`.
@@ -1017,9 +987,7 @@ declare module "util" {
* @param fn An `async` function
* @return a callback style function
*/
export function callbackify(
fn: () => Promise<void>,
): (callback: (err: NodeJS.ErrnoException) => void) => void;
export function callbackify(fn: () => Promise<void>): (callback: (err: NodeJS.ErrnoException) => void) => void;
export function callbackify<TResult>(
fn: () => Promise<TResult>,
): (callback: (err: NodeJS.ErrnoException, result: TResult) => void) => void;
@@ -1028,49 +996,22 @@ declare module "util" {
): (arg1: T1, callback: (err: NodeJS.ErrnoException) => void) => void;
export function callbackify<T1, TResult>(
fn: (arg1: T1) => Promise<TResult>,
): (
arg1: T1,
callback: (err: NodeJS.ErrnoException, result: TResult) => void,
) => void;
): (arg1: T1, callback: (err: NodeJS.ErrnoException, result: TResult) => void) => void;
export function callbackify<T1, T2>(
fn: (arg1: T1, arg2: T2) => Promise<void>,
): (
arg1: T1,
arg2: T2,
callback: (err: NodeJS.ErrnoException) => void,
) => void;
): (arg1: T1, arg2: T2, callback: (err: NodeJS.ErrnoException) => void) => void;
export function callbackify<T1, T2, TResult>(
fn: (arg1: T1, arg2: T2) => Promise<TResult>,
): (
arg1: T1,
arg2: T2,
callback: (err: NodeJS.ErrnoException | null, result: TResult) => void,
) => void;
): (arg1: T1, arg2: T2, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void;
export function callbackify<T1, T2, T3>(
fn: (arg1: T1, arg2: T2, arg3: T3) => Promise<void>,
): (
arg1: T1,
arg2: T2,
arg3: T3,
callback: (err: NodeJS.ErrnoException) => void,
) => void;
): (arg1: T1, arg2: T2, arg3: T3, callback: (err: NodeJS.ErrnoException) => void) => void;
export function callbackify<T1, T2, T3, TResult>(
fn: (arg1: T1, arg2: T2, arg3: T3) => Promise<TResult>,
): (
arg1: T1,
arg2: T2,
arg3: T3,
callback: (err: NodeJS.ErrnoException | null, result: TResult) => void,
) => void;
): (arg1: T1, arg2: T2, arg3: T3, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void;
export function callbackify<T1, T2, T3, T4>(
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<void>,
): (
arg1: T1,
arg2: T2,
arg3: T3,
arg4: T4,
callback: (err: NodeJS.ErrnoException) => void,
) => void;
): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err: NodeJS.ErrnoException) => void) => void;
export function callbackify<T1, T2, T3, T4, TResult>(
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<TResult>,
): (
@@ -1082,14 +1023,7 @@ declare module "util" {
) => void;
export function callbackify<T1, T2, T3, T4, T5>(
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise<void>,
): (
arg1: T1,
arg2: T2,
arg3: T3,
arg4: T4,
arg5: T5,
callback: (err: NodeJS.ErrnoException) => void,
) => void;
): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err: NodeJS.ErrnoException) => void) => void;
export function callbackify<T1, T2, T3, T4, T5, TResult>(
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise<TResult>,
): (
@@ -1101,14 +1035,7 @@ declare module "util" {
callback: (err: NodeJS.ErrnoException | null, result: TResult) => void,
) => void;
export function callbackify<T1, T2, T3, T4, T5, T6>(
fn: (
arg1: T1,
arg2: T2,
arg3: T3,
arg4: T4,
arg5: T5,
arg6: T6,
) => Promise<void>,
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Promise<void>,
): (
arg1: T1,
arg2: T2,
@@ -1119,14 +1046,7 @@ declare module "util" {
callback: (err: NodeJS.ErrnoException) => void,
) => void;
export function callbackify<T1, T2, T3, T4, T5, T6, TResult>(
fn: (
arg1: T1,
arg2: T2,
arg3: T3,
arg4: T4,
arg5: T5,
arg6: T6,
) => Promise<TResult>,
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Promise<TResult>,
): (
arg1: T1,
arg2: T2,
@@ -1136,21 +1056,15 @@ declare module "util" {
arg6: T6,
callback: (err: NodeJS.ErrnoException | null, result: TResult) => void,
) => void;
export interface CustomPromisifyLegacy<
TCustom extends (...args: unknown[]) => unknown,
> {
(...args: unknown[]): unknown;
export interface CustomPromisifyLegacy<TCustom extends Function> extends Function {
__promisify__: TCustom;
}
export interface CustomPromisifySymbol<
TCustom extends (...args: unknown[]) => unknown,
> {
(...args: unknown[]): unknown;
export interface CustomPromisifySymbol<TCustom extends Function> extends Function {
[promisify.custom]: TCustom;
}
export type CustomPromisify<TCustom extends (...args: unknown[]) => unknown> =
CustomPromisifySymbol<TCustom> | CustomPromisifyLegacy<TCustom>;
export type CustomPromisify<TCustom extends Function> =
| CustomPromisifySymbol<TCustom>
| CustomPromisifyLegacy<TCustom>;
/**
* Takes a function following the common error-first callback style, i.e. taking
* an `(err, value) => ...` callback as the last argument, and returns a version
@@ -1220,88 +1134,40 @@ declare module "util" {
* ```
* @since v8.0.0
*/
export function promisify<TCustom extends (...args: unknown[]) => unknown>(
fn: CustomPromisify<TCustom>,
): TCustom;
export function promisify<TCustom extends Function>(fn: CustomPromisify<TCustom>): TCustom;
export function promisify<TResult>(
fn: (callback: (err: unknown, result: TResult) => void) => void,
fn: (callback: (err: any, result: TResult) => void) => void,
): () => Promise<TResult>;
export function promisify(
fn: (callback: (err?: unknown) => void) => void,
): () => Promise<void>;
export function promisify(fn: (callback: (err?: any) => void) => void): () => Promise<void>;
export function promisify<T1, TResult>(
fn: (arg1: T1, callback: (err: unknown, result: TResult) => void) => void,
fn: (arg1: T1, callback: (err: any, result: TResult) => void) => void,
): (arg1: T1) => Promise<TResult>;
export function promisify<T1>(
fn: (arg1: T1, callback: (err?: unknown) => void) => void,
): (arg1: T1) => Promise<void>;
export function promisify<T1>(fn: (arg1: T1, callback: (err?: any) => void) => void): (arg1: T1) => Promise<void>;
export function promisify<T1, T2, TResult>(
fn: (
arg1: T1,
arg2: T2,
callback: (err: unknown, result: TResult) => void,
) => void,
fn: (arg1: T1, arg2: T2, callback: (err: any, result: TResult) => void) => void,
): (arg1: T1, arg2: T2) => Promise<TResult>;
export function promisify<T1, T2>(
fn: (arg1: T1, arg2: T2, callback: (err?: unknown) => void) => void,
fn: (arg1: T1, arg2: T2, callback: (err?: any) => void) => void,
): (arg1: T1, arg2: T2) => Promise<void>;
export function promisify<T1, T2, T3, TResult>(
fn: (
arg1: T1,
arg2: T2,
arg3: T3,
callback: (err: unknown, result: TResult) => void,
) => void,
fn: (arg1: T1, arg2: T2, arg3: T3, callback: (err: any, result: TResult) => void) => void,
): (arg1: T1, arg2: T2, arg3: T3) => Promise<TResult>;
export function promisify<T1, T2, T3>(
fn: (
arg1: T1,
arg2: T2,
arg3: T3,
callback: (err?: unknown) => void,
) => void,
fn: (arg1: T1, arg2: T2, arg3: T3, callback: (err?: any) => void) => void,
): (arg1: T1, arg2: T2, arg3: T3) => Promise<void>;
export function promisify<T1, T2, T3, T4, TResult>(
fn: (
arg1: T1,
arg2: T2,
arg3: T3,
arg4: T4,
callback: (err: unknown, result: TResult) => void,
) => void,
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err: any, result: TResult) => void) => void,
): (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<TResult>;
export function promisify<T1, T2, T3, T4>(
fn: (
arg1: T1,
arg2: T2,
arg3: T3,
arg4: T4,
callback: (err?: unknown) => void,
) => void,
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, callback: (err?: any) => void) => void,
): (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<void>;
export function promisify<T1, T2, T3, T4, T5, TResult>(
fn: (
arg1: T1,
arg2: T2,
arg3: T3,
arg4: T4,
arg5: T5,
callback: (err: unknown, result: TResult) => void,
) => void,
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err: any, result: TResult) => void) => void,
): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise<TResult>;
export function promisify<T1, T2, T3, T4, T5>(
fn: (
arg1: T1,
arg2: T2,
arg3: T3,
arg4: T4,
arg5: T5,
callback: (err?: unknown) => void,
) => void,
fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, callback: (err?: any) => void) => void,
): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Promise<void>;
export function promisify<T extends (...args: unknown[]) => void>(
fn: T,
): (...funcArgs: Parameters<T>) => Promise<void>;
export function promisify(fn: Function): Function;
export namespace promisify {
/**
* That can be used to declare custom promisified variants of functions.
@@ -1406,32 +1272,27 @@ declare module "util" {
*/
encodeInto(src: string, dest: Uint8Array): EncodeIntoResult;
}
import {
TextDecoder as _TextDecoder,
TextEncoder as _TextEncoder,
} from "util";
import { TextDecoder as _TextDecoder, TextEncoder as _TextEncoder } from "util";
global {
/**
* `TextDecoder` class is a global reference for `require('util').TextDecoder`
* https://nodejs.org/api/globals.html#textdecoder
* @since v11.0.0
*/
let TextDecoder: typeof globalThis extends {
onmessage: unknown;
var TextDecoder: typeof globalThis extends {
onmessage: any;
TextDecoder: infer TextDecoder;
}
? TextDecoder
} ? TextDecoder
: typeof _TextDecoder;
/**
* `TextEncoder` class is a global reference for `require('util').TextEncoder`
* https://nodejs.org/api/globals.html#textencoder
* @since v11.0.0
*/
let TextEncoder: typeof globalThis extends {
onmessage: unknown;
var TextEncoder: typeof globalThis extends {
onmessage: any;
TextEncoder: infer TextEncoder;
}
? TextEncoder
} ? TextEncoder
: typeof _TextEncoder;
}
@@ -1464,9 +1325,7 @@ declare module "util" {
* @param config Used to provide arguments for parsing and to configure the parser. `config` supports the following properties:
* @return The parsed command line arguments:
*/
export function parseArgs<T extends ParseArgsConfig>(
config?: T,
): ParsedResults<T>;
export function parseArgs<T extends ParseArgsConfig>(config?: T): ParsedResults<T>;
interface ParseArgsOptionConfig {
/**
* Type of argument.
@@ -1529,46 +1388,31 @@ declare module "util" {
This is technically incorrect but is a much nicer UX for the common case.
The IfDefaultsTrue version is for things which default to true; the IfDefaultsFalse version is for things which default to false.
*/
type IfDefaultsTrue<T, IfTrue, IfFalse> = T extends true
? IfTrue
: T extends false
? IfFalse
type IfDefaultsTrue<T, IfTrue, IfFalse> = T extends true ? IfTrue
: T extends false ? IfFalse
: IfTrue;
// we put the `extends false` condition first here because `undefined` compares like `any` when `strictNullChecks: false`
type IfDefaultsFalse<T, IfTrue, IfFalse> = T extends false
? IfFalse
: T extends true
? IfTrue
type IfDefaultsFalse<T, IfTrue, IfFalse> = T extends false ? IfFalse
: T extends true ? IfTrue
: IfFalse;
type ExtractOptionValue<
T extends ParseArgsConfig,
O extends ParseArgsOptionConfig,
> = IfDefaultsTrue<
type ExtractOptionValue<T extends ParseArgsConfig, O extends ParseArgsOptionConfig> = IfDefaultsTrue<
T["strict"],
O["type"] extends "string"
? string
: O["type"] extends "boolean"
? boolean
: string | boolean,
O["type"] extends "string" ? string : O["type"] extends "boolean" ? boolean : string | boolean,
string | boolean
>;
type ParsedValues<T extends ParseArgsConfig> = IfDefaultsTrue<
T["strict"],
unknown,
{ [longOption: string]: undefined | string | boolean }
> &
(T["options"] extends ParseArgsOptionsConfig
? {
type ParsedValues<T extends ParseArgsConfig> =
& IfDefaultsTrue<T["strict"], unknown, { [longOption: string]: undefined | string | boolean }>
& (T["options"] extends ParseArgsOptionsConfig ? {
-readonly [LongOption in keyof T["options"]]: IfDefaultsFalse<
T["options"][LongOption]["multiple"],
undefined | Array<ExtractOptionValue<T, T["options"][LongOption]>>,
undefined | ExtractOptionValue<T, T["options"][LongOption]>
>;
}
: object);
: {});
type ParsedPositionals<T extends ParseArgsConfig> = IfDefaultsTrue<
T["strict"],
@@ -1579,8 +1423,7 @@ declare module "util" {
type PreciseTokenForOptions<
K extends string,
O extends ParseArgsOptionConfig,
> = O["type"] extends "string"
? {
> = O["type"] extends "string" ? {
kind: "option";
index: number;
name: K;
@@ -1588,8 +1431,7 @@ declare module "util" {
value: string;
inlineValue: boolean;
}
: O["type"] extends "boolean"
? {
: O["type"] extends "boolean" ? {
kind: "option";
index: number;
name: K;
@@ -1603,35 +1445,20 @@ declare module "util" {
T extends ParseArgsConfig,
K extends keyof T["options"] = keyof T["options"],
> = K extends unknown
? T["options"] extends ParseArgsOptionsConfig
? PreciseTokenForOptions<K & string, T["options"][K]>
? T["options"] extends ParseArgsOptionsConfig ? PreciseTokenForOptions<K & string, T["options"][K]>
: OptionToken
: never;
type ParsedOptionToken<T extends ParseArgsConfig> = IfDefaultsTrue<
T["strict"],
TokenForOptions<T>,
OptionToken
>;
type ParsedOptionToken<T extends ParseArgsConfig> = IfDefaultsTrue<T["strict"], TokenForOptions<T>, OptionToken>;
type ParsedPositionalToken<T extends ParseArgsConfig> = IfDefaultsTrue<
T["strict"],
IfDefaultsFalse<
T["allowPositionals"],
{ kind: "positional"; index: number; value: string },
never
>,
IfDefaultsTrue<
T["allowPositionals"],
{ kind: "positional"; index: number; value: string },
never
>
IfDefaultsFalse<T["allowPositionals"], { kind: "positional"; index: number; value: string }, never>,
IfDefaultsTrue<T["allowPositionals"], { kind: "positional"; index: number; value: string }, never>
>;
type ParsedTokens<T extends ParseArgsConfig> = Array<
| ParsedOptionToken<T>
| ParsedPositionalToken<T>
| { kind: "option-terminator"; index: number }
ParsedOptionToken<T> | ParsedPositionalToken<T> | { kind: "option-terminator"; index: number }
>;
type PreciseParsedResults<T extends ParseArgsConfig> = IfDefaultsFalse<
@@ -1648,14 +1475,7 @@ declare module "util" {
>;
type OptionToken =
| {
kind: "option";
index: number;
name: string;
rawName: string;
value: string;
inlineValue: boolean;
}
| { kind: "option"; index: number; name: string; rawName: string; value: string; inlineValue: boolean }
| {
kind: "option";
index: number;
@@ -1672,14 +1492,9 @@ declare module "util" {
// If ParseArgsConfig extends T, then the user passed config constructed elsewhere.
// So we can't rely on the `"not definitely present" implies "definitely not present"` assumption mentioned above.
type ParsedResults<T extends ParseArgsConfig> = ParseArgsConfig extends T
? {
type ParsedResults<T extends ParseArgsConfig> = ParseArgsConfig extends T ? {
values: {
[longOption: string]:
| undefined
| string
| boolean
| Array<string | boolean>;
[longOption: string]: undefined | string | boolean | Array<string | boolean>;
};
positionals: string[];
tokens?: Token[];
@@ -1939,7 +1754,7 @@ declare module "util/types" {
* ```
* @since v10.0.0
*/
function isBooleanObject(object: unknown): object is boolean;
function isBooleanObject(object: unknown): object is Boolean;
/**
* Returns `true` if the value is any boxed primitive object, e.g. created
* by `new Boolean()`, `new String()` or `Object(Symbol())`.
@@ -1955,9 +1770,7 @@ declare module "util/types" {
* ```
* @since v10.11.0
*/
function isBoxedPrimitive(
object: unknown,
): object is string | number | bigint | boolean | symbol;
function isBoxedPrimitive(object: unknown): object is String | Number | BigInt | Boolean | Symbol;
/**
* Returns `true` if the value is a built-in [`DataView`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) instance.
*
@@ -2110,11 +1923,8 @@ declare module "util/types" {
* @since v10.0.0
*/
function isMap<T>(
object: T | object,
): object is T extends ReadonlyMap<unknown, unknown>
? unknown extends T
? never
: ReadonlyMap<unknown, unknown>
object: T | {},
): object is T extends ReadonlyMap<any, any> ? (unknown extends T ? never : ReadonlyMap<any, any>)
: Map<unknown, unknown>;
/**
* Returns `true` if the value is an iterator returned for a built-in [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) instance.
@@ -2152,7 +1962,7 @@ declare module "util/types" {
* Subclasses of the native error types are also native errors:
*
* ```js
* class MyError extends Error object
* class MyError extends Error {}
* console.log(util.types.isNativeError(new MyError())); // true
* ```
*
@@ -2161,7 +1971,7 @@ declare module "util/types" {
*
* ```js
* const vm = require('node:vm');
* const context = vm.createContext(object);
* const context = vm.createContext({});
* const myError = vm.runInContext('new Error()', context);
* console.log(util.types.isNativeError(myError)); // true
* console.log(myError instanceof Error); // false
@@ -2189,7 +1999,7 @@ declare module "util/types" {
* ```
* @since v10.0.0
*/
function isNumberObject(object: unknown): object is number;
function isNumberObject(object: unknown): object is Number;
/**
* Returns `true` if the value is a built-in [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
*
@@ -2230,12 +2040,8 @@ declare module "util/types" {
* @since v10.0.0
*/
function isSet<T>(
object: T | object,
): object is T extends ReadonlySet<unknown>
? unknown extends T
? never
: ReadonlySet<unknown>
: Set<unknown>;
object: T | {},
): object is T extends ReadonlySet<any> ? (unknown extends T ? never : ReadonlySet<any>) : Set<unknown>;
/**
* Returns `true` if the value is an iterator returned for a built-in [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) instance.
*
@@ -2271,7 +2077,7 @@ declare module "util/types" {
* ```
* @since v10.0.0
*/
function isStringObject(object: unknown): object is string;
function isStringObject(object: unknown): object is String;
/**
* Returns `true` if the value is a symbol object, created
* by calling `Object()` on a `Symbol` primitive.
@@ -2283,7 +2089,7 @@ declare module "util/types" {
* ```
* @since v10.0.0
*/
function isSymbolObject(object: unknown): object is symbol;
function isSymbolObject(object: unknown): object is Symbol;
/**
* Returns `true` if the value is a built-in [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) instance.
*

View File

@@ -58,9 +58,9 @@
<span v-else>
<router-link
:to="{ name: 'new-edit-account' }"
class="text-xs bg-blue-500 text-white px-1.5 py-1 rounded-md"
class="block w-full text-center text-md text-slate-500 uppercase border border-dashed border-slate-400 px-1.5 py-2 rounded-md mb-2"
>
(set name)
(Set Your Name)
</router-link>
</span>
@@ -89,15 +89,23 @@
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8">
<label
for="toggleNotifications"
class="flex items-center cursor-pointer"
class="flex items-center justify-between cursor-pointer"
@click="
this.$notify(
!toggleNotifications
? this.$notify(
{
group: 'modal',
type: 'notification-permission',
},
-1,
)
: this.$notify(
{
group: 'modal',
type: 'notification-off',
},
-1,
)
"
>
<!-- label -->
@@ -121,7 +129,7 @@
</label>
<label
for="toggleMuteNotifications"
class="flex items-center cursor-pointer mt-4"
class="flex items-center justify-between cursor-pointer mt-4"
@click="
this.$notify(
{
@@ -157,7 +165,6 @@
<router-link
:to="{ name: 'seed-backup' }"
href=""
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
>
Backup Identifier Seed
@@ -172,30 +179,42 @@
</a>
<a ref="downloadLink" />
<div v-if="activeDid" class="flex py-2">
<button class="text-center text-md text-blue-500" @click="checkLimits()">
<div v-if="activeDid" class="my-8">
<h3 class="text-sm uppercase font-semibold mb-3">Rate Limits</h3>
<button
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
@click="checkLimits()"
>
Check Limits
</button>
<!-- show spinner if loading limits -->
<div v-if="loadingLimits" class="ml-2">
Checking... <fa icon="spinner" class="fa-spin"></fa>
<div v-if="loadingLimits" class="text-center mb-4">
Checking&hellip; <fa icon="spinner" class="fa-spin"></fa>
</div>
<div class="ml-2">
<div class="mb-4">
{{ limitsMessage }}
</div>
<div v-if="!!limits?.nextWeekBeginDateTime" class="px-9">
<span class="font-bold">Rate Limits</span>
<p>
You have done {{ limits.doneClaimsThisWeek }} claims out of
{{ limits.maxClaimsPerWeek }} for this week. Your claims counter
resets at {{ readableTime(limits.nextWeekBeginDateTime) }}
<div v-if="!!limits?.nextWeekBeginDateTime">
<p class="mb-3 text-sm">
You have done <b>{{ limits.doneClaimsThisWeek }}</b> claims out of
<b>{{ limits.maxClaimsPerWeek }}</b> for this week. Your claims
counter resets at
<b class="whitespace-nowrap">{{
readableTime(limits.nextWeekBeginDateTime)
}}</b>
</p>
<p>
You have done {{ limits.doneRegistrationsThisMonth }} registrations
out of {{ limits.maxRegistrationsPerMonth }} for this month. (You can
register nobody on your first day, and after that only one a day in
your first month.) Your registration counter resets at
<p class="text-sm">
You have done
<b>{{ limits.doneRegistrationsThisMonth }}</b> registrations out of
<b>{{ limits.maxRegistrationsPerMonth }}</b> for this month.
<i
>(You can register nobody on your first day, and after that only one
a day in your first month.)</i
>
Your registration counter resets at
<b class="whitespace-nowrap">
{{ readableTime(limits.nextMonthBeginDateTime) }}
</b>
</p>
</div>
</div>
@@ -209,13 +228,13 @@
Advanced
</h3>
<div v-if="showAdvanced">
<p>
<p class="text-rose-600 mb-8">
Beware: the features here can be confusing and even change data in ways
you do not expect. But we support your freedoms!
</p>
<!-- Deep Identity Details -->
<h2 class="text-slate-500 text-sm font-bold mb-2 py-2">
<h2 class="text-sm uppercase font-semibold mb-3">
Deep Identity Details
</h2>
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
@@ -273,13 +292,11 @@
<label
for="toggleShowAmounts"
class="flex items-center cursor-pointer py-2"
class="flex items-center justify-between cursor-pointer my-4"
@click="handleChange"
>
<!-- label -->
<h2 class="text-slate-500 text-sm font-bold mb-2">
Show amounts given with contacts
</h2>
<h2>Show amounts given with contacts</h2>
<!-- toggle -->
<div class="relative ml-2">
<!-- input -->
@@ -298,26 +315,28 @@
</div>
</label>
<div class="flex py-2">
<button class="text-blue-500">
<router-link :to="{ name: 'statistics' }" class="block text-center">
<router-link
:to="{ name: 'statistics' }"
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
>
See Global Animated History of Giving
</router-link>
</button>
</div>
<div class="flex py-2">
<button class="text-blue-500">
<!-- id used by puppeteer test script -->
<router-link
id="switch-identity-link"
:to="{ name: 'identity-switcher' }"
class="block text-center"
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
>
Switch Identity / No Identity
</router-link>
<button
@click="alertWebPushSubscription()"
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
>
Show Subscription from Web Push Server
</button>
</div>
<div class="flex py-4">
<h2 class="text-slate-500 text-sm font-bold mb-2">Claim Server</h2>
@@ -457,12 +476,12 @@ export default class AccountViewView extends Vue {
showAdvanced = false;
private isSubscribed = false;
subscription: PushSubscription | null = null;
private isSubscribed = false;
get toggleNotifications() {
return this.isSubscribed;
}
set toggleNotifications(value) {
this.isSubscribed = value;
}
@@ -549,7 +568,6 @@ export default class AccountViewView extends Vue {
* @throws Will display specific messages to the user based on different errors.
*/
async created() {
console.error("created");
try {
await db.open();
@@ -569,13 +587,12 @@ export default class AccountViewView extends Vue {
}
async mounted() {
console.error("mounted()");
try {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
this.toggleNotifications = !!subscription;
this.subscription = await registration.pushManager.getSubscription();
this.toggleNotifications = !!this.subscription;
} catch (error) {
console.error(error);
console.error("Mount error:", error);
this.toggleNotifications = false;
}
}
@@ -927,6 +944,23 @@ export default class AccountViewView extends Vue {
webPushServer: this.webPushServerInput,
});
this.webPushServer = this.webPushServerInput;
this.$notify(
{
group: "alert",
type: "warning",
title: "Reload",
text: "Now reload the app to get a new VAPID to use with this push server.",
},
-1,
);
}
alertWebPushSubscription() {
console.log(
"Web push subscription:",
JSON.parse(JSON.stringify(this.subscription)), // gives more info than plain console logging
);
alert(JSON.stringify(this.subscription));
}
}
</script>

View File

@@ -137,7 +137,7 @@
<div>
<h2 class="font-bold text-2xl mt-8">Claim</h2>
<pre>{{ yamlVeriClaim }}</pre>
<pre>{{ util.inspect(veriClaim, false, null) }}</pre>
</div>
<h2 class="font-bold text-2xl mt-8">Full Claim</h2>
@@ -158,7 +158,7 @@
</button>
</div>
<div v-else>
<pre>{{ yamlFullClaim }}</pre>
<pre>{{ util.inspect(fullClaim, false, null) }}</pre>
</div>
<a :href="apiServer + '/api/claim/' + veriClaim.id" target="_blank">
@@ -186,7 +186,6 @@ import * as serverUtil from "@/libs/endorserServer";
import QuickNav from "@/components/QuickNav.vue";
import EntityIcon from "@/components/EntityIcon.vue";
import { Account } from "@/db/tables/accounts";
import * as yaml from 'js-yaml';
interface Notification {
group: string;
@@ -301,8 +300,7 @@ export default class ClaimView extends Vue {
try {
const resp = await this.axios.get(url, { headers });
if (resp.status === 200) {
this.veriClaim = resp.json;
this.yamlVeriClaim = yaml.dumps(resp.json);
this.veriClaim = resp.data;
} else {
// actually, axios typically throws an error so we never get here
console.log("Error getting claim:", resp);
@@ -381,8 +379,7 @@ export default class ClaimView extends Vue {
try {
const resp = await this.axios.get(url, { headers });
if (resp.status === 200) {
this.fullClaim = resp.json;
this.yamlFullClaim = yaml.dump(resp.json);
this.fullClaim = resp.data;
} else {
// actually, axios typically throws an error so we never get here
console.log("Error getting full claim:", resp);

View File

@@ -18,6 +18,16 @@
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4">
Your Contact Info
</h1>
<p v-if="!givenName" class="text-center mt-2">
<span class="text-red">Beware!</span>
You aren't sharing your name, so hurry and
<router-link
:to="{ name: 'new-edit-account' }"
class="bg-blue-500 text-white px-1.5 py-1 rounded-md"
>
go here to set it for them.
</router-link>
</p>
</div>
<div @click="onCopyToClipboard()" v-if="activeDid">
@@ -87,6 +97,7 @@ export default class ContactQRScanShow extends Vue {
activeDid = "";
apiServer = "";
givenName = "";
qrValue = "";
public async getIdentity(activeDid: string) {
@@ -111,6 +122,7 @@ export default class ContactQRScanShow extends Vue {
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
this.activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || "";
this.givenName = settings?.firstName || "";
await accountsDB.open();
const accounts = await accountsDB.accounts.toArray();

View File

@@ -19,12 +19,13 @@
</div>
<!-- New Contact -->
<div class="mb-4 flex">
<span class="self-center bg-slate-500 text-white px-1.5 py-1 rounded-md">
<router-link :to="{ name: 'contact-qr' }">
<fa icon="qrcode" class="fa-fw" />
<div class="mb-4 flex items-stretch">
<router-link
:to="{ name: 'contact-qr' }"
class="flex items-center bg-slate-500 text-white px-1.5 py-1 mr-1 rounded-md"
>
<fa icon="qrcode" class="fa-fw text-2xl" />
</router-link>
</span>
<input
type="text"
placeholder="DID, Name, Public Key (base 16 or 64)"

View File

@@ -214,9 +214,7 @@
</p>
<h2 class="text-xl font-semibold">What app version is this?</h2>
<p>
{{ package.version }}
</p>
<p>{{ package.version }} ({{ commitHash }})</p>
<h2 class="text-xl font-semibold">
For any other questions, including removing your data:
@@ -246,6 +244,7 @@ export default class Help extends Vue {
$notify!: (notification: Notification, timeout?: number) => void;
package = Package;
commitHash = process.env.VUE_APP_GIT_HASH;
showOnboardInfo() {
this.$notify(

View File

@@ -8,28 +8,44 @@
<!-- show the actions for recognizing a give -->
<div class="mb-8">
<div v-if="!activeDid">
To record others' giving,
<router-link :to="{ name: 'start' }" class="text-blue-500">
create your identifier.</router-link
<div
v-if="!activeDid"
class="bg-amber-200 rounded-md overflow-hidden text-center px-4 py-3 mb-4"
>
<p class="text-lg mb-3">
You need an <b>identifier</b> before you can record others' giving.
</p>
<router-link
:to="{ name: 'start' }"
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
>
Create Your Identifier</router-link
>
</div>
<div v-else-if="!isRegistered">
To record others' giving, someone must register your account, so show
them
<router-link :to="{ name: 'contact-qr' }" class="text-blue-500">
your identity info</router-link
<div
v-else-if="!isRegistered"
class="bg-amber-200 rounded-md overflow-hidden text-center px-4 py-3 mb-4"
>
and then
<router-link :to="{ name: 'account' }" class="text-blue-500">
check your limits.</router-link
Someone must register your account before you can record others' giving.
To do this:
<router-link
:to="{ name: 'contact-qr' }"
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
>
1. Show Them Your Identity Info</router-link
>
<router-link
:to="{ name: 'account' }"
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
>
2. Check Your Limits</router-link
>
</div>
<div v-else>
<!-- activeDid && isRegistered -->
<h2 class="text-xl font-bold">Record Something Given</h2>
<h2 class="text-xl font-bold mb-4">Record Something Given</h2>
<ul class="grid grid-cols-4 gap-x-3 gap-y-5 text-center mb-5">
<li @click="openDialog()">

View File

@@ -68,7 +68,7 @@ export default class NewEditAccountView extends Vue {
});
localStorage.setItem("firstName", this.givenName as string);
localStorage.setItem("lastName", ""); // deprecated, pre v 0.1.3
this.$router.push({ name: "account" });
this.$router.back();
}
onClickCancel() {

View File

@@ -3,7 +3,7 @@
<section id="Content" class="p-6 pb-24">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Your Plans
Your Ideas
</h1>
<!-- Quick Search -->

View File

@@ -5,7 +5,7 @@ importScripts(
);
self.addEventListener("install", (event) => {
console.error("Adding event listener for:", event);
console.log("Adding event listener for:", event);
importScripts(
"safari-notifications.js",
"nacl.js",

View File

@@ -395,12 +395,12 @@ async function setMostRecentNotified(id) {
data["lastNotifiedClaimId"] = id;
await updateRecord(store, data);
} else {
console.error("Record not found");
console.error("IndexedDB settings record not found.");
}
transaction.oncomplete = () => db.close();
} catch (error) {
console.error("Database error: " + error.message);
console.error("IndexedDB error:", error);
}
}
@@ -520,7 +520,11 @@ async function getNotificationCount() {
const most_recent_notified = claims[0]["id"];
await setMostRecentNotified(most_recent_notified);
} else {
console.error("The service worker got a bad response status when fetching claims:", response.status, response);
console.error(
"The service worker got a bad response status when fetching claims:",
response.status,
response,
);
}
break;
}

View File

@@ -1,4 +1,8 @@
const { defineConfig } = require("@vue/cli-service");
const { gitDescribeSync } = require("git-describe");
process.env.VUE_APP_GIT_HASH = gitDescribeSync().hash;
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {