diff --git a/babel.config.js b/babel.config.js index 162a3ea9..cfbc5715 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,4 @@ module.exports = { + plugins: ["@babel/plugin-transform-private-methods"], presets: ["@vue/cli-plugin-babel/preset"], }; diff --git a/package-lock.json b/package-lock.json index 1cbcd8ad..4c5c5683 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "js-generate-password": "^0.1.9", "js-yaml": "^4.1.0", "localstorage-slim": "^2.5.0", + "lru-cache": "^10.2.0", "luxon": "^3.4.4", "merkletreejs": "^0.3.11", "moment": "^2.29.4", @@ -3052,6 +3053,18 @@ "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", "optional": true }, + "node_modules/@digitalcredentials/jsonld/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@digitalcredentials/keypair": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@digitalcredentials/keypair/-/keypair-1.0.5.tgz", @@ -3149,6 +3162,18 @@ "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", "optional": true }, + "node_modules/@digitalcredentials/vc-status-list/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -4317,6 +4342,19 @@ "node": ">=4" } }, + "node_modules/@expo/cli/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@expo/cli/node_modules/mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -4714,6 +4752,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@expo/config/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@expo/config/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -8912,6 +8963,18 @@ "node": ">=12" } }, + "node_modules/@transmute/jsonld/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@transmute/ld-key-pair": { "version": "0.7.0-unstable.81", "resolved": "https://registry.npmjs.org/@transmute/ld-key-pair/-/ld-key-pair-0.7.0-unstable.81.tgz", @@ -9674,6 +9737,18 @@ "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", "optional": true }, + "node_modules/@veramo-community/lds-ecdsa-secp256k1-recovery2020/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@veramo/core": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/@veramo/core/-/core-5.5.3.tgz", @@ -10378,6 +10453,18 @@ "node": ">=8" } }, + "node_modules/@vue/cli-shared-utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@vue/cli-shared-utils/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12425,6 +12512,19 @@ "node": ">= 10" } }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/cacache/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -17014,6 +17114,19 @@ "node": ">=10" } }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -19269,6 +19382,18 @@ "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", "optional": true }, + "node_modules/jsonld/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsonpointer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", @@ -20246,15 +20371,11 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "devOptional": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "engines": { - "node": ">=10" + "node": "14 || >=16.14" } }, "node_modules/luxon": { @@ -25124,6 +25245,18 @@ "node": ">=10" } }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", diff --git a/package.json b/package.json index 5425d242..2487cff7 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "js-generate-password": "^0.1.9", "js-yaml": "^4.1.0", "localstorage-slim": "^2.5.0", + "lru-cache": "^10.2.0", "luxon": "^3.4.4", "merkletreejs": "^0.3.11", "moment": "^2.29.4", diff --git a/project.task.yaml b/project.task.yaml index 4d1dc378..fe000a1f 100644 --- a/project.task.yaml +++ b/project.task.yaml @@ -1,15 +1,15 @@ tasks : -- finish push server: - - get utcHour parameter working - - add back the explicit wait for browser subscription timing problems +- fix the notification link to the app - 01 change scanning flow - allow them to stay on the QR/scanning screen after scanning someone - 24 contextual tutorials https://docs.google.com/document/d/11C_K3RM0rgo0onih20KFhcIzukZyq_CRWqaWX5om_kM/edit#heading=h.iwiwcydou5hw - 24 Move to Vite assignee:jason +- feeds - add "remote" filter, if they choose 'visible' then warn that they won't see any others, cache list & don't reload front page on change + - .1 add shortcut from project (etc?) to the public project page in a browser - .1 add KindSpring link to ideas - .1 on feed, don't show "to someone anonymous" if it's to a project @@ -23,6 +23,7 @@ tasks : - .2 don't show a warning on a totally new project when the authorized agent is set - .2 anchor hash into BTC - .2 list the "show more" contacts alphabetically +- .5 add back the explicit wait for browser subscription timing problems? - .5 make Time Safari a share_target for images @@ -126,7 +127,7 @@ tasks : - 08 convert to cleaner implementation (maybe Drie -- https://github.com/janvorisek/drie) - .5 show seed phrase in a QR code for transfer to another device -- .5 on DiscoverView, switch to a filter UI (eg. just from friend +- .5 on DiscoverView, switch to a filter UI (eg. just from friend) - .5 don't show "Offer" on project screen if they aren't registered - 01 especially for iOS, check for new version & update, eg. https://stackoverflow.com/questions/52221805/any-way-yet-to-auto-update-or-just-clear-the-cache-on-a-pwa-on-ios diff --git a/src/components/FeedFilters.vue b/src/components/FeedFilters.vue new file mode 100644 index 00000000..e9cbac11 --- /dev/null +++ b/src/components/FeedFilters.vue @@ -0,0 +1,219 @@ + + + + + diff --git a/src/db/tables/settings.ts b/src/db/tables/settings.ts index f95b3839..dbc4cf0c 100644 --- a/src/db/tables/settings.ts +++ b/src/db/tables/settings.ts @@ -16,6 +16,10 @@ export type Settings = { activeDid?: string; // Active Decentralized ID apiServer?: string; // API server URL + + filterFeedByNearby?: boolean; // filter by nearby + filterFeedByVisible?: boolean; // filter by visible users ie. anyone not hidden + firstName?: string; // User's first name isRegistered?: boolean; lastName?: string; // deprecated - put all names in firstName @@ -38,6 +42,10 @@ export type Settings = { webPushServer?: string; // Web Push server URL }; +export function isAnyFeedFilterOn(settings: Settings): boolean { + return !!(settings.filterFeedByNearby || settings.filterFeedByVisible); +} + /** * Schema for the Settings table in the database. */ diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts index 5972708c..7ac68bef 100644 --- a/src/libs/endorserServer.ts +++ b/src/libs/endorserServer.ts @@ -1,9 +1,11 @@ +import { Axios, AxiosResponse, RawAxiosRequestHeaders } from "axios"; +import * as didJwt from "did-jwt"; +import { LRUCache } from "lru-cache"; import * as R from "ramda"; import { IIdentifier } from "@veramo/core"; -import { accessToken, SimpleSigner } from "@/libs/crypto"; -import * as didJwt from "did-jwt"; -import { Axios, AxiosResponse } from "axios"; + import { Contact } from "@/db/tables/contacts"; +import { accessToken, SimpleSigner } from "@/libs/crypto"; export const SCHEMA_ORG_CONTEXT = "https://schema.org"; // the object in RegisterAction claims @@ -49,7 +51,7 @@ export interface GenericVerifiableCredential { [key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any } -export interface GenericServerRecord extends GenericVerifiableCredential { +export interface GenericCredWrapper extends GenericVerifiableCredential { handleId?: string; id: string; issuedAt: string; @@ -58,7 +60,7 @@ export interface GenericServerRecord extends GenericVerifiableCredential { claim: Record; claimType?: string; } -export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = { +export const BLANK_GENERIC_SERVER_RECORD: GenericCredWrapper = { "@context": SCHEMA_ORG_CONTEXT, "@type": "", claim: {}, @@ -68,7 +70,7 @@ export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = { }; // a summary record; the VC is found the fullClaim field -export interface GiveServerRecord { +export interface GiveSummaryRecord { agentDid: string; amount: number; amountConfirmed: number; @@ -83,7 +85,7 @@ export interface GiveServerRecord { } // a summary record; the VC is found the fullClaim field -export interface OfferServerRecord { +export interface OfferSummaryRecord { amount: number; amountGiven: number; amountGivenConfirmed: number; @@ -101,7 +103,7 @@ export interface OfferServerRecord { } // a summary record; the VC is not currently part of this record -export interface PlanServerRecord { +export interface PlanSummaryRecord { agentDid?: string; // optional, if the issuer wants someone else to manage as well description: string; endTime?: string; @@ -110,6 +112,7 @@ export interface PlanServerRecord { issuerDid: string; locLat?: number; locLon?: number; + name?: string; startTime?: string; url?: string; } @@ -256,6 +259,10 @@ export type CreateAndSubmitClaimResult = SuccessResult | ErrorResult; // See https://github.com/trentlarson/endorser-ch/blob/0cb626f803028e7d9c67f095858a9fc8542e3dbd/server/api/services/util.js#L6 const HIDDEN_DID = "did:none:HIDDEN"; +const planCache: LRUCache = new LRUCache({ + max: 500, +}); + export function isDid(did: string) { return did.startsWith("did:"); } @@ -269,7 +276,7 @@ export function isEmptyOrHiddenDid(did?: string) { } /** - * @return true for any nested string where func(input) === true + * @return true for any string within this primitive/object/array where func(input) === true * * Similar logic is found in endorser-mobile. */ @@ -304,6 +311,12 @@ export function containsHiddenDid(obj: any) { return testRecursivelyOnStrings(isHiddenDid, obj); } +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const containsNonHiddenDid = (obj: any) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return testRecursivelyOnStrings((s: any) => isDid(s) && !isHiddenDid(s), obj); +}; + export function stripEndorserPrefix(claimId: string) { if (claimId && claimId.startsWith(ENDORSER_CH_HANDLE_PREFIX)) { return claimId.substring(ENDORSER_CH_HANDLE_PREFIX.length); @@ -403,8 +416,11 @@ export function didInfoForContact( return myId ? { displayName: "You (Alt ID)", known: true } : isHiddenDid(did) - ? { displayName: "Someone Outside Your Network", known: false } - : { displayName: "Someone Outside Contacts", known: false }; + ? { displayName: "Someone Totally Outside Your View", known: false } + : { + displayName: "Someone Visible But Outside Your Contact List", + known: false, + }; } } @@ -423,6 +439,71 @@ export function didInfo( return didInfoForContact(did, activeDid, contact, allMyDids).displayName; } +async function getHeaders(identity: IIdentifier | null) { + const headers: RawAxiosRequestHeaders = { + "Content-Type": "application/json", + }; + if (identity) { + const token = await accessToken(identity); + headers["Authorization"] = "Bearer " + token; + } + return headers; +} + +/** + * @param handleId nullable -- which means that "undefined" will be returned + * @param identity nullable -- which means no private info will be returned + * @param axios + * @param apiServer + */ +export async function getPlanFromCache( + handleId: string | null, + identity: IIdentifier | null, + axios: Axios, + apiServer: string, +) { + if (!handleId) { + return undefined; + } + let cred = planCache.get(handleId); + if (!cred) { + const url = + apiServer + + "/api/v2/report/plans?handleId=" + + encodeURIComponent(handleId); + const headers = await getHeaders(identity); + try { + const resp = await axios.get(url, { headers }); + if (resp.status === 200 && resp.data?.data?.length > 0) { + cred = resp.data.data[0]; + planCache.set(handleId, cred); + } else { + console.log( + "Failed to load plan with handle", + handleId, + " Got data:", + resp.data, + ); + } + } catch (error) { + console.log( + "Failed to load plan with handle", + handleId, + " Got error:", + error, + ); + } + } + return cred; +} + +export async function setPlanInCache( + handleId: string, + planSummary: PlanSummaryRecord, +) { + planCache.set(handleId, planSummary); +} + /** * For result, see https://api.endorser.ch/api-docs/#/claims/post_api_v2_claim * @@ -475,7 +556,7 @@ export async function createAndSubmitGive( vcClaim.image = imageUrl; } return createAndSubmitClaim( - vcClaim as GenericServerRecord, + vcClaim as GenericCredWrapper, identity, apiServer, axios, @@ -524,7 +605,7 @@ export async function createAndSubmitOffer( }; } return createAndSubmitClaim( - vcClaim as GenericServerRecord, + vcClaim as GenericCredWrapper, identity, apiServer, axios, @@ -695,7 +776,7 @@ const claimSummary = (claim: Record) => { similar code is also contained in endorser-mobile **/ export const claimSpecialDescription = ( - record: GenericServerRecord, + record: GenericCredWrapper, activeDid: string, identifiers: Array, contacts: Array, @@ -789,7 +870,7 @@ export const claimSpecialDescription = ( "...]" ); } else { - return issuer + " declared " + claimSummary(claim as GenericServerRecord); + return issuer + " declared " + claimSummary(claim as GenericCredWrapper); } }; diff --git a/src/libs/util.ts b/src/libs/util.ts index 58b329c1..10823174 100644 --- a/src/libs/util.ts +++ b/src/libs/util.ts @@ -9,7 +9,7 @@ import { accountsDB, db } from "@/db/index"; import { Account } from "@/db/tables/accounts"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto"; -import { GenericServerRecord, containsHiddenDid } from "@/libs/endorserServer"; +import { GenericCredWrapper, containsHiddenDid } from "@/libs/endorserServer"; import * as serverUtil from "@/libs/endorserServer"; export const PRIVACY_MESSAGE = @@ -70,7 +70,7 @@ export const isGlobalUri = (uri: string) => { return uri && uri.match(new RegExp(/^[A-Za-z][A-Za-z0-9+.-]+:/)); }; -export const giveIsConfirmable = (veriClaim: GenericServerRecord) => { +export const giveIsConfirmable = (veriClaim: GenericCredWrapper) => { return veriClaim.claimType === "GiveAction"; }; @@ -86,7 +86,7 @@ export const doCopyTwoSecRedo = (text: string, fn: () => void) => { * @param veriClaim is expected to have fields: claim, claimType, and issuer */ export const isGiveRecordTheUserCanConfirm = ( - veriClaim: GenericServerRecord, + veriClaim: GenericCredWrapper, activeDid: string, confirmerIdList: string[] = [], ) => { @@ -102,9 +102,9 @@ export const isGiveRecordTheUserCanConfirm = ( * @returns the DID of the person who offered, or undefined if hidden * @param veriClaim is expected to have fields: claim and issuer */ -export const offerGiverDid: ( - arg0: GenericServerRecord, -) => string | undefined = (veriClaim) => { +export const offerGiverDid: (arg0: GenericCredWrapper) => string | undefined = ( + veriClaim, +) => { let giver; if ( veriClaim.claim.offeredBy?.identifier && @@ -121,7 +121,7 @@ export const offerGiverDid: ( * @returns true if the user can fulfill the offer * @param veriClaim is expected to have fields: claim, claimType, and issuer */ -export const canFulfillOffer = (veriClaim: GenericServerRecord) => { +export const canFulfillOffer = (veriClaim: GenericCredWrapper) => { return !!(veriClaim.claimType === "Offer" && offerGiverDid(veriClaim)); }; diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index 1c2ccc50..ef1d3a5d 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -112,6 +112,8 @@
+ +
Settings
- + Troubleshoot your notification setup. + + + Set Search Area… + + + +
+ Topics of Interest +
+ +
+ Separate topics with a comma. +
-
Usage Limits
+
Usage Limits
Checking… @@ -200,7 +224,7 @@
-
Data Export
+
Data Export
Download Settings & Contacts @@ -221,7 +245,7 @@ If no download happened yet, click again here to download now. @@ -952,13 +976,13 @@ export default class AccountViewView extends Vue { public computedStartDownloadLinkClassNames() { return { - invisible: this.downloadUrl, + hidden: this.downloadUrl, }; } public computedDownloadLinkClassNames() { return { - invisible: !this.downloadUrl, + hidden: !this.downloadUrl, }; } diff --git a/src/views/ContactAmountsView.vue b/src/views/ContactAmountsView.vue index a6fc0ff9..1d3654ab 100644 --- a/src/views/ContactAmountsView.vue +++ b/src/views/ContactAmountsView.vue @@ -119,7 +119,7 @@ import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { accessToken, SimpleSigner } from "@/libs/crypto"; import { AgreeVerifiableCredential, - GiveServerRecord, + GiveSummaryRecord, GiveVerifiableCredential, SCHEMA_ORG_CONTEXT, } from "@/libs/endorserServer"; @@ -131,7 +131,7 @@ export default class ContactAmountssView extends Vue { activeDid = ""; apiServer = ""; contact: Contact | null = null; - giveRecords: Array = []; + giveRecords: Array = []; numAccounts = 0; async beforeCreate() { @@ -197,7 +197,7 @@ export default class ContactAmountssView extends Vue { async loadGives(activeDid: string, contact: Contact) { try { const identity = await this.getIdentity(this.activeDid); - let result: Array = []; + let result: Array = []; const url = this.apiServer + "/api/v2/report/gives?agentDid=" + @@ -252,7 +252,7 @@ export default class ContactAmountssView extends Vue { ); } - const sortedResult: Array = R.sort( + const sortedResult: Array = R.sort( (a, b) => new Date(b.issuedAt).getTime() - new Date(a.issuedAt).getTime(), result, @@ -271,7 +271,7 @@ export default class ContactAmountssView extends Vue { } } - async confirm(record: GiveServerRecord) { + async confirm(record: GiveSummaryRecord) { // Make claim // I use clone here because otherwise it gets a Proxy object. // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index 8384163d..2bf4a9a8 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -303,7 +303,7 @@ import { import { CONTACT_CSV_HEADER, CONTACT_URL_PREFIX, - GiveServerRecord, + GiveSummaryRecord, GiveVerifiableCredential, isDid, RegisterVerifiableCredential, @@ -410,7 +410,7 @@ export default class ContactsView extends Vue { } const handleResponse = ( - resp: { status: number; data: { data: GiveServerRecord[] } }, + resp: { status: number; data: { data: GiveSummaryRecord[] } }, descriptions: Record, confirmed: Record, unconfirmed: Record, diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 29a89a39..51071368 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -174,10 +174,19 @@ showGivenToUser="true" /> +
-

Latest Activity

+
+

Latest Activity

+ +
  • - + - + + + + + + {{ giveDescription(record) }} - {{ giveDescription(record) }} - + - +
    @@ -240,11 +248,17 @@ Loading…

+
+

+ No claims match your filters. +

+
diff --git a/src/views/ProjectViewView.vue b/src/views/ProjectViewView.vue index f6b09781..b4602458 100644 --- a/src/views/ProjectViewView.vue +++ b/src/views/ProjectViewView.vue @@ -362,11 +362,11 @@ import { accessToken } from "@/libs/crypto"; import * as libsUtil from "@/libs/util"; import { BLANK_GENERIC_SERVER_RECORD, - GenericServerRecord, + GenericCredWrapper, GiverInputInfo, - GiveServerRecord, - OfferServerRecord, - PlanServerRecord, + GiveSummaryRecord, + OfferSummaryRecord, + PlanSummaryRecord, } from "@/libs/endorserServer"; import * as serverUtil from "@/libs/endorserServer"; @@ -390,14 +390,14 @@ export default class ProjectViewView extends Vue { apiServer = ""; description = ""; expanded = false; - fulfilledByThis: PlanServerRecord | null = null; - fulfillersToThis: Array = []; - givesToThis: Array = []; + fulfilledByThis: PlanSummaryRecord | null = null; + fulfillersToThis: Array = []; + givesToThis: Array = []; issuer = ""; latitude = 0; longitude = 0; name = ""; - offersToThis: Array = []; + offersToThis: Array = []; projectId = localStorage.getItem("projectId") || ""; // handle ID showDidCopy = false; timeSince = ""; @@ -720,8 +720,8 @@ export default class ProjectViewView extends Vue { this.$router.push(route); } - checkIsFulfillable(offer: OfferServerRecord) { - const offerRecord: GenericServerRecord = { + checkIsFulfillable(offer: OfferSummaryRecord) { + const offerRecord: GenericCredWrapper = { ...BLANK_GENERIC_SERVER_RECORD, claim: offer.fullClaim, claimType: "Offer", @@ -730,8 +730,8 @@ export default class ProjectViewView extends Vue { return libsUtil.canFulfillOffer(offerRecord); } - onClickFulfillGiveToOffer(offer: OfferServerRecord) { - const offerRecord: GenericServerRecord = { + onClickFulfillGiveToOffer(offer: OfferSummaryRecord) { + const offerRecord: GenericCredWrapper = { ...BLANK_GENERIC_SERVER_RECORD, claim: offer.fullClaim, issuer: offer.offeredByDid, @@ -770,8 +770,8 @@ export default class ProjectViewView extends Vue { } } - checkIsConfirmable(give: GiveServerRecord) { - const giveDetails: GenericServerRecord = { + checkIsConfirmable(give: GiveSummaryRecord) { + const giveDetails: GenericCredWrapper = { ...BLANK_GENERIC_SERVER_RECORD, claim: give.fullClaim, claimType: "GiveAction", @@ -781,7 +781,7 @@ export default class ProjectViewView extends Vue { } // similar code is found in ClaimView - async confirmClaim(give: GiveServerRecord) { + async confirmClaim(give: GiveSummaryRecord) { if (confirm("Do you personally confirm that this is true?")) { // similar logic is found in endorser-mobile const goodClaim = serverUtil.removeSchemaContext( diff --git a/src/views/ProjectsView.vue b/src/views/ProjectsView.vue index ad0e930b..2639a5be 100644 --- a/src/views/ProjectsView.vue +++ b/src/views/ProjectsView.vue @@ -223,7 +223,7 @@ import InfiniteScroll from "@/components/InfiniteScroll.vue"; import QuickNav from "@/components/QuickNav.vue"; import ProjectIcon from "@/components/ProjectIcon.vue"; import TopMessage from "@/components/TopMessage.vue"; -import { OfferServerRecord, PlanData } from "@/libs/endorserServer"; +import { OfferSummaryRecord, PlanData } from "@/libs/endorserServer"; import EntityIcon from "@/components/EntityIcon.vue"; @Component({ @@ -237,7 +237,7 @@ export default class ProjectsView extends Vue { currentIid: IIdentifier; isLoading = false; numAccounts = 0; - offers: OfferServerRecord[] = []; + offers: OfferSummaryRecord[] = []; showOffers = true; showProjects = false; diff --git a/src/views/QuickActionBvcEndView.vue b/src/views/QuickActionBvcEndView.vue index 930509f5..d21ca96a 100644 --- a/src/views/QuickActionBvcEndView.vue +++ b/src/views/QuickActionBvcEndView.vue @@ -146,7 +146,7 @@ import { createAndSubmitConfirmation, createAndSubmitGive, ErrorResult, - GenericServerRecord, + GenericCredWrapper, GenericVerifiableCredential, } from "@/libs/endorserServer"; import * as libsUtil from "@/libs/util"; @@ -166,7 +166,7 @@ export default class QuickActionBvcBeginView extends Vue { allMyDids: Array = []; apiServer = ""; claimCountWithHidden = 0; - claimsToConfirm: GenericServerRecord[] = []; + claimsToConfirm: GenericCredWrapper[] = []; claimsToConfirmSelected: string[] = []; description = "breakfast"; loadingConfirms = true; @@ -228,7 +228,7 @@ export default class QuickActionBvcBeginView extends Vue { } await response.json().then((data) => { const dataByOthers = R.reject( - (claim: GenericServerRecord) => claim.issuer === this.activeDid, + (claim: GenericCredWrapper) => claim.issuer === this.activeDid, data, ); const dataByOthersWithoutHidden = R.reject( diff --git a/src/views/SearchAreaView.vue b/src/views/SearchAreaView.vue index e4d4444d..e5f5e307 100644 --- a/src/views/SearchAreaView.vue +++ b/src/views/SearchAreaView.vue @@ -209,9 +209,9 @@ export default class DiscoverView extends Vue { group: "alert", type: "success", title: "Saved", - text: "That has been saved in your preferences.", + text: "That has been saved in your preferences. You can now filter by it on your home screen feed.", }, - -1, + 7000, ); this.$router.back(); } catch (err) { @@ -247,6 +247,7 @@ export default class DiscoverView extends Vue { await db.open(); db.settings.update(MASTER_SETTINGS_KEY, { searchBoxes: [], + filterFeedByNearby: false, }); this.searchBox = null; this.localCenterLat = 0;