add sharing & copying instructions when asking contacts for help, and list all the visibleTo DIDs with an English description of their path
This commit is contained in:
@@ -3,6 +3,8 @@ tasks:
|
|||||||
|
|
||||||
- .5 give list of visible IDs on the claim detail page
|
- .5 give list of visible IDs on the claim detail page
|
||||||
- instead of text, make links to share the data with contacts and ask for help
|
- instead of text, make links to share the data with contacts and ask for help
|
||||||
|
- Add TimeSafari as a shareable app https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target
|
||||||
|
- make a shortcut for BVC
|
||||||
- choose an agent via a contact chooser (not just copy-paste a DID)
|
- choose an agent via a contact chooser (not just copy-paste a DID)
|
||||||
- .5 find out why clicking quickly back-and-forth onto the "my project" page often shows error "You need an identifier to load your projects." (easier to reproduce on desktop?)
|
- .5 find out why clicking quickly back-and-forth onto the "my project" page often shows error "You need an identifier to load your projects." (easier to reproduce on desktop?)
|
||||||
- .5 bug - it didn't show the "fulfills offer" on the claim detail page for a give that had one - https://test.timesafari.app/claim/01HMFWRPA3PD6Q9EYFKX3MC41J
|
- .5 bug - it didn't show the "fulfills offer" on the claim detail page for a give that had one - https://test.timesafari.app/claim/01HMFWRPA3PD6Q9EYFKX3MC41J
|
||||||
@@ -17,7 +19,7 @@ tasks:
|
|||||||
- make the "give" on contact screen work like other give (allowing donation vs current blank)
|
- make the "give" on contact screen work like other give (allowing donation vs current blank)
|
||||||
- on ClaimView, the "ask someone" should refer to "visible" IDs, or to confirmations only if confirmations are visible
|
- on ClaimView, the "ask someone" should refer to "visible" IDs, or to confirmations only if confirmations are visible
|
||||||
- notify user when data import is completed
|
- notify user when data import is completed
|
||||||
- "send them to this page" on ClaimView should be a link (for installed app)
|
- message "send them to this page" on ClaimView should be a link (for installed app)
|
||||||
- When we update a version, desktop browser users have seen nothing happen after clicking on the contact page QR and on the account page "Help"; errors show in the console. Reload fixed it. If this happens on mobile, ask the user to reload.
|
- When we update a version, desktop browser users have seen nothing happen after clicking on the contact page QR and on the account page "Help"; errors show in the console. Reload fixed it. If this happens on mobile, ask the user to reload.
|
||||||
|
|
||||||
- 01 show my VCs - most interesting, or via search
|
- 01 show my VCs - most interesting, or via search
|
||||||
@@ -122,6 +124,8 @@ tasks:
|
|||||||
- 16 From the home screen, make the quick action even easier.
|
- 16 From the home screen, make the quick action even easier.
|
||||||
|
|
||||||
- allow some gives even if they aren't registered - maybe someday as a gift to the world, but we really want this to be built via personal connections
|
- allow some gives even if they aren't registered - maybe someday as a gift to the world, but we really want this to be built via personal connections
|
||||||
|
- .1 When Chrome shows compatibility https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API#api.navigator.canshare
|
||||||
|
then change the canShare check in this app to check the real canShare() method.
|
||||||
|
|
||||||
log:
|
log:
|
||||||
- videos for multiple identities https://youtu.be/p8L87AeD76w and for adding time to contacts https://youtu.be/7Yylczevp10 done:2023-03-29
|
- videos for multiple identities https://youtu.be/p8L87AeD76w and for adding time to contacts https://youtu.be/7Yylczevp10 done:2023-03-29
|
||||||
|
|||||||
@@ -174,21 +174,21 @@ export function isEmptyOrHiddenDid(did?: string) {
|
|||||||
* Similar logic is found in endorser-mobile.
|
* Similar logic is found in endorser-mobile.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
function testRecursivelyOnString(func: (arg0: any) => boolean, input: any) {
|
function testRecursivelyOnStrings(func: (arg0: any) => boolean, input: any) {
|
||||||
if (Object.prototype.toString.call(input) === "[object String]") {
|
if (Object.prototype.toString.call(input) === "[object String]") {
|
||||||
return func(input);
|
return func(input);
|
||||||
} else if (input instanceof Object) {
|
} else if (input instanceof Object) {
|
||||||
if (!Array.isArray(input)) {
|
if (!Array.isArray(input)) {
|
||||||
// it's an object
|
// it's an object
|
||||||
for (const key in input) {
|
for (const key in input) {
|
||||||
if (testRecursivelyOnString(func, input[key])) {
|
if (testRecursivelyOnStrings(func, input[key])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// it's an array
|
// it's an array
|
||||||
for (const value of input) {
|
for (const value of input) {
|
||||||
if (testRecursivelyOnString(func, value)) {
|
if (testRecursivelyOnStrings(func, value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@ function testRecursivelyOnString(func: (arg0: any) => boolean, input: any) {
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export function containsHiddenDid(obj: any) {
|
export function containsHiddenDid(obj: any) {
|
||||||
return testRecursivelyOnString(isHiddenDid, obj);
|
return testRecursivelyOnStrings(isHiddenDid, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stripEndorserPrefix(claimId: string) {
|
export function stripEndorserPrefix(claimId: string) {
|
||||||
|
|||||||
@@ -99,13 +99,17 @@ export const canFulfillOffer = (veriClaim: GenericServerRecord) => {
|
|||||||
export function findAllVisibleToDids(
|
export function findAllVisibleToDids(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
input: any,
|
input: any,
|
||||||
|
humanReadable = false,
|
||||||
): Record<string, Array<string>> {
|
): Record<string, Array<string>> {
|
||||||
if (Array.isArray(input)) {
|
if (Array.isArray(input)) {
|
||||||
const result: Record<string, Array<string>> = {};
|
const result: Record<string, Array<string>> = {};
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
const inside = findAllVisibleToDids(input[i]);
|
const inside = findAllVisibleToDids(input[i], humanReadable);
|
||||||
for (const key in inside) {
|
for (const key in inside) {
|
||||||
result["[" + i + "]" + key] = inside[key];
|
const pathKey = humanReadable
|
||||||
|
? "#" + (i + 1) + " " + key
|
||||||
|
: "[" + i + "]" + key;
|
||||||
|
result[pathKey] = inside[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -115,11 +119,15 @@ export function findAllVisibleToDids(
|
|||||||
for (const key in input) {
|
for (const key in input) {
|
||||||
if (key.endsWith("VisibleToDids")) {
|
if (key.endsWith("VisibleToDids")) {
|
||||||
const newKey = key.slice(0, -"VisibleToDids".length);
|
const newKey = key.slice(0, -"VisibleToDids".length);
|
||||||
result["." + newKey] = input[key];
|
const pathKey = humanReadable ? newKey : "." + newKey;
|
||||||
|
result[pathKey] = input[key];
|
||||||
} else {
|
} else {
|
||||||
const inside = findAllVisibleToDids(input[key]);
|
const inside = findAllVisibleToDids(input[key], humanReadable);
|
||||||
for (const insideKey in inside) {
|
for (const insideKey in inside) {
|
||||||
result["." + key + insideKey] = inside[insideKey];
|
const pathKey = humanReadable
|
||||||
|
? key + "'s " + insideKey
|
||||||
|
: "." + key + insideKey;
|
||||||
|
result[pathKey] = inside[insideKey];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +143,10 @@ export function findAllVisibleToDids(
|
|||||||
|
|
||||||
pkgx +deno.land sh
|
pkgx +deno.land sh
|
||||||
|
|
||||||
|
deno
|
||||||
|
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
|
//import { findAllVisibleToDids } from './src/libs/util'; // doesn't work because other dependencies fail so gotta copy-and-paste function
|
||||||
|
|
||||||
console.log(R.equals(findAllVisibleToDids(null), {}));
|
console.log(R.equals(findAllVisibleToDids(null), {}));
|
||||||
console.log(R.equals(findAllVisibleToDids(9), {}));
|
console.log(R.equals(findAllVisibleToDids(9), {}));
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import {
|
|||||||
faLongArrowAltRight,
|
faLongArrowAltRight,
|
||||||
faMagnifyingGlass,
|
faMagnifyingGlass,
|
||||||
faMessage,
|
faMessage,
|
||||||
|
faMinus,
|
||||||
faPen,
|
faPen,
|
||||||
faPersonCircleCheck,
|
faPersonCircleCheck,
|
||||||
faPersonCircleQuestion,
|
faPersonCircleQuestion,
|
||||||
@@ -101,6 +102,7 @@ library.add(
|
|||||||
faLongArrowAltRight,
|
faLongArrowAltRight,
|
||||||
faMagnifyingGlass,
|
faMagnifyingGlass,
|
||||||
faMessage,
|
faMessage,
|
||||||
|
faMinus,
|
||||||
faPen,
|
faPen,
|
||||||
faPersonCircleCheck,
|
faPersonCircleCheck,
|
||||||
faPersonCircleQuestion,
|
faPersonCircleQuestion,
|
||||||
|
|||||||
@@ -469,6 +469,7 @@
|
|||||||
import { AxiosError, AxiosRequestConfig } from "axios";
|
import { AxiosError, AxiosRequestConfig } from "axios";
|
||||||
import Dexie from "dexie";
|
import Dexie from "dexie";
|
||||||
import "dexie-export-import";
|
import "dexie-export-import";
|
||||||
|
import { ImportProgress } from "dexie-export-import/dist/import";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
@@ -481,7 +482,6 @@ import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
|||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
import { ErrorResponse, RateLimits } from "@/libs/endorserServer";
|
import { ErrorResponse, RateLimits } from "@/libs/endorserServer";
|
||||||
import { ImportProgress } from "dexie-export-import/dist/import";
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const Buffer = require("buffer/").Buffer;
|
const Buffer = require("buffer/").Buffer;
|
||||||
@@ -526,14 +526,11 @@ export default class AccountViewView extends Vue {
|
|||||||
limitsMessage = "";
|
limitsMessage = "";
|
||||||
loadingLimits = true; // might as well now that we do it on mount, to avoid flashing the registration message
|
loadingLimits = true; // might as well now that we do it on mount, to avoid flashing the registration message
|
||||||
showContactGives = false;
|
showContactGives = false;
|
||||||
|
|
||||||
showDidCopy = false;
|
showDidCopy = false;
|
||||||
showDerCopy = false;
|
showDerCopy = false;
|
||||||
showB64Copy = false;
|
showB64Copy = false;
|
||||||
showPubCopy = false;
|
showPubCopy = false;
|
||||||
|
|
||||||
showAdvanced = false;
|
showAdvanced = false;
|
||||||
|
|
||||||
subscription: PushSubscription | null = null;
|
subscription: PushSubscription | null = null;
|
||||||
warnIfProdServer = false;
|
warnIfProdServer = false;
|
||||||
warnIfTestServer = false;
|
warnIfTestServer = false;
|
||||||
|
|||||||
@@ -235,29 +235,87 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="font-bold uppercase text-xl mt-8 mb-2">Visible Details</h2>
|
<h2 class="font-bold uppercase text-xl mt-8 mb-2">
|
||||||
<div v-if="Object.keys(veriClaimDidsVisible).length > 0">
|
{{ serverUtil.containsHiddenDid(veriClaim) ? "Visible " : "" }}Details
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
serverUtil.containsHiddenDid(veriClaim) &&
|
||||||
|
R.isEmpty(veriClaimDidsVisible)
|
||||||
|
"
|
||||||
|
class="mb-2"
|
||||||
|
>
|
||||||
|
Some of the details are not visible to you; they show as "HIDDEN". They
|
||||||
|
are not visible to any of your direct contacts, either.
|
||||||
|
<span v-if="canShare">
|
||||||
|
If you'd like to ask any of your contacts to take a look and see if
|
||||||
|
their contacts can see more details,
|
||||||
|
<a @click="onClickShareClaim()" class="text-blue-500"
|
||||||
|
>click to send them this info</a
|
||||||
|
>
|
||||||
|
and see if they are willing to make an introduction.
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
If you'd like to ask any of your contacts to take a look and see if
|
||||||
|
their contacts can see more details,
|
||||||
|
<a @click="copyToClipboard(windowLocation)" class="text-blue-500"
|
||||||
|
>share this page with them</a
|
||||||
|
>
|
||||||
|
and see if they are willing to make an introduction.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!R.isEmpty(veriClaimDidsVisible)">
|
||||||
Some of the details are not visible to you but they are visible to some
|
Some of the details are not visible to you but they are visible to some
|
||||||
of your contacts. If you'd like an introduction, share the information
|
of your contacts.
|
||||||
with them and ask them to connect you.
|
<span v-if="canShare">
|
||||||
|
If you'd like an introduction,
|
||||||
|
<a @click="onClickShareClaim()" class="text-blue-500"
|
||||||
|
>click to share the information with them and ask if they'll tell
|
||||||
|
you more about the participants.</a
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
If you'd like an introduction,
|
||||||
|
<a @click="copyToClipboard(windowLocation)" class="text-blue-500"
|
||||||
|
>share this page with them and ask if they'll tell you more about
|
||||||
|
about the participants.</a
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-for="(visibleDidPath, index) of Object.keys(veriClaimDidsVisible)"
|
v-for="(visibleDidPath, index) of Object.keys(veriClaimDidsVisible)"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="list-disc flex justify-start p-2"
|
class="list-disc p-4"
|
||||||
>
|
>
|
||||||
<div class="text-sm p-4">
|
<div class="text-sm">
|
||||||
{{ visibleDidPath }}
|
<fa icon="minus" class="fa-fw"></fa>
|
||||||
|
The {{ visibleDidPath }} is visible to:
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4">
|
<div class="ml-12 p-1">
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<li
|
||||||
v-for="(visDid, idx2) of veriClaimDidsVisible[visibleDidPath]"
|
v-for="(visDid, idx2) of veriClaimDidsVisible[visibleDidPath]"
|
||||||
:key="idx2"
|
:key="idx2"
|
||||||
class="list-disc"
|
class="list-disc"
|
||||||
>
|
>
|
||||||
<div class="text-sm">
|
<div class="text-sm mt-2">
|
||||||
{{ didInfo(visDid) }}
|
<span>
|
||||||
{{ veriClaim.publicUrls?.[visDid] || "" }}
|
{{ didInfo(visDid)
|
||||||
|
}}<span v-if="veriClaim.publicUrls?.[visDid]"
|
||||||
|
>, found at
|
||||||
|
<fa icon="globe" class="fa-fw text-slate-400"></fa
|
||||||
|
> <a
|
||||||
|
:href="veriClaim.publicUrls?.[visDid]"
|
||||||
|
class="text-blue-500"
|
||||||
|
>{{
|
||||||
|
veriClaim.publicUrls[visDid].substring(
|
||||||
|
veriClaim.publicUrls[visDid].indexOf("//") + 2,
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -308,6 +366,7 @@ import * as yaml from "js-yaml";
|
|||||||
import * as R from "ramda";
|
import * as R from "ramda";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
import { useClipboard } from "@vueuse/core";
|
||||||
|
|
||||||
import GiftedDialog from "@/components/GiftedDialog.vue";
|
import GiftedDialog from "@/components/GiftedDialog.vue";
|
||||||
import OfferDialog from "@/components/OfferDialog.vue";
|
import OfferDialog from "@/components/OfferDialog.vue";
|
||||||
@@ -341,6 +400,7 @@ export default class ClaimView extends Vue {
|
|||||||
allContacts: Array<Contact> = [];
|
allContacts: Array<Contact> = [];
|
||||||
apiServer = "";
|
apiServer = "";
|
||||||
|
|
||||||
|
canShare = false;
|
||||||
confirmerIdList: string[] = []; // list of DIDs that have confirmed this claim excluding the issuer
|
confirmerIdList: string[] = []; // list of DIDs that have confirmed this claim excluding the issuer
|
||||||
confsVisibleErrorMessage = "";
|
confsVisibleErrorMessage = "";
|
||||||
confsVisibleToIdList: string[] = []; // list of DIDs that can see any confirmer
|
confsVisibleToIdList: string[] = []; // list of DIDs that can see any confirmer
|
||||||
@@ -355,7 +415,9 @@ export default class ClaimView extends Vue {
|
|||||||
veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
|
veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
|
||||||
veriClaimDump = "";
|
veriClaimDump = "";
|
||||||
veriClaimDidsVisible = {};
|
veriClaimDidsVisible = {};
|
||||||
|
windowLocation = window.location.href;
|
||||||
|
|
||||||
|
R = R;
|
||||||
yaml = yaml;
|
yaml = yaml;
|
||||||
libsUtil = libsUtil;
|
libsUtil = libsUtil;
|
||||||
serverUtil = serverUtil;
|
serverUtil = serverUtil;
|
||||||
@@ -405,6 +467,10 @@ export default class ClaimView extends Vue {
|
|||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When Chrome compatibility is fixed https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API#api.navigator.canshare
|
||||||
|
// then use this truer check: navigator.canShare && navigator.canShare()
|
||||||
|
this.canShare = !!navigator.share;
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert a space before any capital letters except the initial letter
|
// insert a space before any capital letters except the initial letter
|
||||||
@@ -472,6 +538,7 @@ export default class ClaimView extends Vue {
|
|||||||
this.veriClaimDump = yaml.dump(this.veriClaim);
|
this.veriClaimDump = yaml.dump(this.veriClaim);
|
||||||
this.veriClaimDidsVisible = libsUtil.findAllVisibleToDids(
|
this.veriClaimDidsVisible = libsUtil.findAllVisibleToDids(
|
||||||
this.veriClaim,
|
this.veriClaim,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// actually, axios typically throws an error so we never get here
|
// actually, axios typically throws an error so we never get here
|
||||||
@@ -688,5 +755,29 @@ export default class ClaimView extends Vue {
|
|||||||
this.veriClaim.handleId,
|
this.veriClaim.handleId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copyToClipboard(text: string) {
|
||||||
|
useClipboard()
|
||||||
|
.copy(text)
|
||||||
|
.then(() => {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "toast",
|
||||||
|
title: "Copied",
|
||||||
|
text: "Location was copied to clipboard.",
|
||||||
|
},
|
||||||
|
2000,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickShareClaim() {
|
||||||
|
window.navigator.share({
|
||||||
|
title: "Help Connect Me",
|
||||||
|
text: "I'm trying to find the full details of this claim. Can you help me?",
|
||||||
|
url: this.windowLocation,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user