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:
2024-01-21 15:16:39 -07:00
parent dcfa8d9451
commit 1053b78ab8
6 changed files with 130 additions and 25 deletions

View File

@@ -174,21 +174,21 @@ export function isEmptyOrHiddenDid(did?: string) {
* Similar logic is found in endorser-mobile.
*/
// 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]") {
return func(input);
} else if (input instanceof Object) {
if (!Array.isArray(input)) {
// it's an object
for (const key in input) {
if (testRecursivelyOnString(func, input[key])) {
if (testRecursivelyOnStrings(func, input[key])) {
return true;
}
}
} else {
// it's an array
for (const value of input) {
if (testRecursivelyOnString(func, value)) {
if (testRecursivelyOnStrings(func, value)) {
return true;
}
}
@@ -201,7 +201,7 @@ function testRecursivelyOnString(func: (arg0: any) => boolean, input: any) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function containsHiddenDid(obj: any) {
return testRecursivelyOnString(isHiddenDid, obj);
return testRecursivelyOnStrings(isHiddenDid, obj);
}
export function stripEndorserPrefix(claimId: string) {

View File

@@ -99,13 +99,17 @@ export const canFulfillOffer = (veriClaim: GenericServerRecord) => {
export function findAllVisibleToDids(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
input: any,
humanReadable = false,
): Record<string, Array<string>> {
if (Array.isArray(input)) {
const result: Record<string, Array<string>> = {};
for (let i = 0; i < input.length; i++) {
const inside = findAllVisibleToDids(input[i]);
const inside = findAllVisibleToDids(input[i], humanReadable);
for (const key in inside) {
result["[" + i + "]" + key] = inside[key];
const pathKey = humanReadable
? "#" + (i + 1) + " " + key
: "[" + i + "]" + key;
result[pathKey] = inside[key];
}
}
return result;
@@ -115,11 +119,15 @@ export function findAllVisibleToDids(
for (const key in input) {
if (key.endsWith("VisibleToDids")) {
const newKey = key.slice(0, -"VisibleToDids".length);
result["." + newKey] = input[key];
const pathKey = humanReadable ? newKey : "." + newKey;
result[pathKey] = input[key];
} else {
const inside = findAllVisibleToDids(input[key]);
const inside = findAllVisibleToDids(input[key], humanReadable);
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
deno
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(9), {}));

View File

@@ -46,6 +46,7 @@ import {
faLongArrowAltRight,
faMagnifyingGlass,
faMessage,
faMinus,
faPen,
faPersonCircleCheck,
faPersonCircleQuestion,
@@ -101,6 +102,7 @@ library.add(
faLongArrowAltRight,
faMagnifyingGlass,
faMessage,
faMinus,
faPen,
faPersonCircleCheck,
faPersonCircleQuestion,

View File

@@ -469,6 +469,7 @@
import { AxiosError, AxiosRequestConfig } from "axios";
import Dexie from "dexie";
import "dexie-export-import";
import { ImportProgress } from "dexie-export-import/dist/import";
import { ref } from "vue";
import { Component, Vue } from "vue-facing-decorator";
import { useClipboard } from "@vueuse/core";
@@ -481,7 +482,6 @@ import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto";
import { IIdentifier } from "@veramo/core";
import { ErrorResponse, RateLimits } from "@/libs/endorserServer";
import { ImportProgress } from "dexie-export-import/dist/import";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Buffer = require("buffer/").Buffer;
@@ -526,14 +526,11 @@ export default class AccountViewView extends Vue {
limitsMessage = "";
loadingLimits = true; // might as well now that we do it on mount, to avoid flashing the registration message
showContactGives = false;
showDidCopy = false;
showDerCopy = false;
showB64Copy = false;
showPubCopy = false;
showAdvanced = false;
subscription: PushSubscription | null = null;
warnIfProdServer = false;
warnIfTestServer = false;

View File

@@ -235,29 +235,87 @@
</div>
<div>
<h2 class="font-bold uppercase text-xl mt-8 mb-2">Visible Details</h2>
<div v-if="Object.keys(veriClaimDidsVisible).length > 0">
<h2 class="font-bold uppercase text-xl mt-8 mb-2">
{{ 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
of your contacts. If you'd like an introduction, share the information
with them and ask them to connect you.
of your contacts.
<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
v-for="(visibleDidPath, index) of Object.keys(veriClaimDidsVisible)"
:key="index"
class="list-disc flex justify-start p-2"
class="list-disc p-4"
>
<div class="text-sm p-4">
{{ visibleDidPath }}
<div class="text-sm">
<fa icon="minus" class="fa-fw"></fa>
The {{ visibleDidPath }} is visible to:
</div>
<div class="p-4">
<div class="ml-12 p-1">
<ul>
<li
v-for="(visDid, idx2) of veriClaimDidsVisible[visibleDidPath]"
:key="idx2"
class="list-disc"
>
<div class="text-sm">
{{ didInfo(visDid) }}
{{ veriClaim.publicUrls?.[visDid] || "" }}
<div class="text-sm mt-2">
<span>
{{ didInfo(visDid)
}}<span v-if="veriClaim.publicUrls?.[visDid]"
>, found at
<fa icon="globe" class="fa-fw text-slate-400"></fa
>&nbsp;<a
:href="veriClaim.publicUrls?.[visDid]"
class="text-blue-500"
>{{
veriClaim.publicUrls[visDid].substring(
veriClaim.publicUrls[visDid].indexOf("//") + 2,
)
}}
</a>
</span>
</span>
</div>
</li>
</ul>
@@ -308,6 +366,7 @@ import * as yaml from "js-yaml";
import * as R from "ramda";
import { IIdentifier } from "@veramo/core";
import { Component, Vue } from "vue-facing-decorator";
import { useClipboard } from "@vueuse/core";
import GiftedDialog from "@/components/GiftedDialog.vue";
import OfferDialog from "@/components/OfferDialog.vue";
@@ -341,6 +400,7 @@ export default class ClaimView extends Vue {
allContacts: Array<Contact> = [];
apiServer = "";
canShare = false;
confirmerIdList: string[] = []; // list of DIDs that have confirmed this claim excluding the issuer
confsVisibleErrorMessage = "";
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;
veriClaimDump = "";
veriClaimDidsVisible = {};
windowLocation = window.location.href;
R = R;
yaml = yaml;
libsUtil = libsUtil;
serverUtil = serverUtil;
@@ -405,6 +467,10 @@ export default class ClaimView extends Vue {
-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
@@ -472,6 +538,7 @@ export default class ClaimView extends Vue {
this.veriClaimDump = yaml.dump(this.veriClaim);
this.veriClaimDidsVisible = libsUtil.findAllVisibleToDids(
this.veriClaim,
true,
);
} else {
// actually, axios typically throws an error so we never get here
@@ -688,5 +755,29 @@ export default class ClaimView extends Vue {
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>