diff --git a/static/img/qrcode.png b/static/img/qrcode.png
new file mode 100644
index 0000000..f3e044f
Binary files /dev/null and b/static/img/qrcode.png differ
diff --git a/static/kx-claim.js b/static/kx-claim.js
index 8fa1ff2..378242a 100644
--- a/static/kx-claim.js
+++ b/static/kx-claim.js
@@ -102,51 +102,66 @@ class Claim extends HTMLElement {
if (claim.status === 'verified' && !claim.verification.result && claim.isAmbiguous()) {
shadow.querySelector('.info .subtitle').innerText = '---';
- const subsection0 = elContent.appendChild(document.createElement('div'));
- subsection0.setAttribute('class', 'subsection');
- const subsection0_icon = subsection0.appendChild(document.createElement('img'));
- subsection0_icon.setAttribute('src', '/static/img/alert-decagram.png');
- const subsection0_text = subsection0.appendChild(document.createElement('div'));
+ const subsection_alert = elContent.appendChild(document.createElement('div'));
+ subsection_alert.setAttribute('class', 'subsection');
+ const subsection_alert_icon = subsection_alert.appendChild(document.createElement('img'));
+ subsection_alert_icon.setAttribute('src', '/static/img/alert-decagram.png');
+ const subsection_alert_text = subsection_alert.appendChild(document.createElement('div'));
- const message = subsection0_text.appendChild(document.createElement('p'));
+ const message = subsection_alert_text.appendChild(document.createElement('p'));
message.innerHTML = `None of the matched service providers could be verified. Keyoxide was not able to determine which was the correct service provider or why the verification process failed.`;
return;
}
// Links to profile and proof
- const subsection1 = elContent.appendChild(document.createElement('div'));
- subsection1.setAttribute('class', 'subsection');
- const subsection1_icon = subsection1.appendChild(document.createElement('img'));
- subsection1_icon.setAttribute('src', '/static/img/link.png');
- const subsection1_text = subsection1.appendChild(document.createElement('div'));
+ const subsection_links = elContent.appendChild(document.createElement('div'));
+ subsection_links.setAttribute('class', 'subsection');
+ const subsection_links_icon = subsection_links.appendChild(document.createElement('img'));
+ subsection_links_icon.setAttribute('src', '/static/img/link.png');
+ const subsection_links_text = subsection_links.appendChild(document.createElement('div'));
- const profile_link = subsection1_text.appendChild(document.createElement('p'));
+ const profile_link = subsection_links_text.appendChild(document.createElement('p'));
if (claim.matches[0].profile.uri) {
profile_link.innerHTML = `Profile link: ${claim.matches[0].profile.uri}`;
} else {
profile_link.innerHTML = `Profile link: not accessible from browser`;
}
- const proof_link = subsection1_text.appendChild(document.createElement('p'));
+ const proof_link = subsection_links_text.appendChild(document.createElement('p'));
if (claim.matches[0].proof.uri) {
proof_link.innerHTML = `Proof link: ${claim.matches[0].proof.uri}`;
} else {
proof_link.innerHTML = `Proof link: not accessible from browser`;
}
+ // QR Code
+ if (claim.matches[0].profile.qr) {
+ elContent.appendChild(document.createElement('hr'));
+
+ const subsection_qr = elContent.appendChild(document.createElement('div'));
+ subsection_qr.setAttribute('class', 'subsection');
+ const subsection_qr_icon = subsection_qr.appendChild(document.createElement('img'));
+ subsection_qr_icon.setAttribute('src', '/static/img/qrcode.png');
+ const subsection_qr_text = subsection_qr.appendChild(document.createElement('div'));
+
+ const button_profileQR = subsection_qr_text.appendChild(document.createElement('button'));
+ button_profileQR.innerText = `Show profile QR`;
+ button_profileQR.setAttribute('onClick', `showQR('${claim.matches[0].profile.qr}')`);
+ }
+
elContent.appendChild(document.createElement('hr'));
// Claim verification status
- const subsection2 = elContent.appendChild(document.createElement('div'));
- subsection2.setAttribute('class', 'subsection');
- const subsection2_icon = subsection2.appendChild(document.createElement('img'));
- subsection2_icon.setAttribute('src', '/static/img/decagram.png');
- const subsection2_text = subsection2.appendChild(document.createElement('div'));
+ const subsection_status = elContent.appendChild(document.createElement('div'));
+ subsection_status.setAttribute('class', 'subsection');
+ const subsection_status_icon = subsection_status.appendChild(document.createElement('img'));
+ subsection_status_icon.setAttribute('src', '/static/img/decagram.png');
+ const subsection_status_text = subsection_status.appendChild(document.createElement('div'));
- const verification = subsection2_text.appendChild(document.createElement('p'));
+ const verification = subsection_status_text.appendChild(document.createElement('p'));
if (claim.status === 'verified') {
verification.innerHTML = `Claim verification has completed.`;
- subsection2_icon.setAttribute('src', '/static/img/check-decagram.png');
+ subsection_status_icon.setAttribute('src', '/static/img/check-decagram.png');
} else {
verification.innerHTML = `Claim verification is in progress…`;
return;
@@ -155,26 +170,26 @@ class Claim extends HTMLElement {
elContent.appendChild(document.createElement('hr'));
// Result of claim verification
- const subsection3 = elContent.appendChild(document.createElement('div'));
- subsection3.setAttribute('class', 'subsection');
- const subsection3_icon = subsection3.appendChild(document.createElement('img'));
- subsection3_icon.setAttribute('src', '/static/img/shield-search.png');
- const subsection3_text = subsection3.appendChild(document.createElement('div'));
+ const subsection_result = elContent.appendChild(document.createElement('div'));
+ subsection_result.setAttribute('class', 'subsection');
+ const subsection_result_icon = subsection_result.appendChild(document.createElement('img'));
+ subsection_result_icon.setAttribute('src', '/static/img/shield-search.png');
+ const subsection_result_text = subsection_result.appendChild(document.createElement('div'));
- const result = subsection3_text.appendChild(document.createElement('p'));
+ const result = subsection_result_text.appendChild(document.createElement('p'));
result.innerHTML = `The claim ${claim.verification.result ? 'HAS BEEN' : 'COULD NOT BE'} verified by the proof.`;
// Additional info
if (claim.verification.proof.viaProxy) {
elContent.appendChild(document.createElement('hr'));
- const subsection4 = elContent.appendChild(document.createElement('div'));
- subsection4.setAttribute('class', 'subsection');
- const subsection4_icon = subsection4.appendChild(document.createElement('img'));
- subsection4_icon.setAttribute('src', '/static/img/information.png');
- const subsection4_text = subsection4.appendChild(document.createElement('div'));
+ const subsection_info = elContent.appendChild(document.createElement('div'));
+ subsection_info.setAttribute('class', 'subsection');
+ const subsection_info_icon = subsection_info.appendChild(document.createElement('img'));
+ subsection_info_icon.setAttribute('src', '/static/img/information.png');
+ const subsection_info_text = subsection_info.appendChild(document.createElement('div'));
- const result_proxyUsed = subsection4_text.appendChild(document.createElement('p'));
+ const result_proxyUsed = subsection_info_text.appendChild(document.createElement('p'));
result_proxyUsed.innerHTML = `A proxy was used to fetch the proof: PLACEHOLDER__PROXY_HOSTNAME`;
}
@@ -183,14 +198,14 @@ class Claim extends HTMLElement {
// console.log(claim.verification);
// elContent.appendChild(document.createElement('hr'));
- // const subsection5 = elContent.appendChild(document.createElement('div'));
- // subsection5.setAttribute('class', 'subsection');
- // const subsection5_icon = subsection5.appendChild(document.createElement('img'));
- // subsection5_icon.setAttribute('src', '/static/img/alert-circle.png');
- // const subsection5_text = subsection5.appendChild(document.createElement('div'));
+ // const subsection_errors = elContent.appendChild(document.createElement('div'));
+ // subsection_errors.setAttribute('class', 'subsection');
+ // const subsection_errors_icon = subsection_errors.appendChild(document.createElement('img'));
+ // subsection_errors_icon.setAttribute('src', '/static/img/alert-circle.png');
+ // const subsection_errors_text = subsection_errors.appendChild(document.createElement('div'));
// claim.verification.errors.forEach(message => {
- // const error = subsection5_text.appendChild(document.createElement('p'));
+ // const error = subsection_errors_text.appendChild(document.createElement('p'));
// if (message instanceof Error) {
// error.innerText = message.message;
diff --git a/static/kx-styles.css b/static/kx-styles.css
index 77c6ef1..4f1bd97 100644
--- a/static/kx-styles.css
+++ b/static/kx-styles.css
@@ -164,6 +164,20 @@ details.kx-item .inProgress:after {
bottom: 0;
right: 0;
}
+details.kx-item button {
+ padding: 0.4rem 0.8rem;
+ margin-right: 8px;
+ text-decoration: none;
+ text-transform: uppercase;
+ background-color: var(--purple-50);
+ border: solid 2px var(--purple-400);
+ border-radius: 4px;
+ cursor: pointer;
+}
+details.kx-item button:hover {
+ background-color: var(--purple-400);
+ color: #fff;
+}
@media screen and (max-width: 640px) {
details.kx-item summary .claim__description p {
diff --git a/static/scripts.js b/static/scripts.js
index ef5a3e5..14af431 100644
--- a/static/scripts.js
+++ b/static/scripts.js
@@ -131,6 +131,37 @@ const fetchProfileKey = async function() {
}
}
+// Enable QR modal
+const showQR = function(input) {
+ const qrTarget = document.getElementById('qr');
+ const qrContext = qrTarget.getContext('2d');
+ const qrOpts = {
+ errorCorrectionLevel: 'L',
+ margin: 1,
+ width: 256,
+ height: 256
+ };
+
+ if (input) {
+ input = decodeURIComponent(input);
+
+ QRCode.toCanvas(qrTarget, input, qrOpts, function(error) {
+ if (error) {
+ document.querySelector("#qr--altLink").innerText = "";
+ document.querySelector("#qr--altLink").href = "#";
+ qrContext.clearRect(0, 0, qrTarget.width, qrTarget.height);
+ console.error(error);
+ } else {
+ document.querySelector("#qr--altLink").innerText = input;
+ document.querySelector("#qr--altLink").href = input;
+ document.querySelector('#dialog--qr').showModal();
+ }
+ });
+ } else {
+ qrContext.clearRect(0, 0, qrTarget.width, qrTarget.height);
+ }
+}
+
// let elFormSignatureProfile = document.body.querySelector("#formGenerateSignatureProfile"),
// elProfileUid = document.body.querySelector("#profileUid"),
// elProfileMode = document.body.querySelector("#profileMode"),
diff --git a/static/styles.css b/static/styles.css
index 9fbd8df..1766240 100644
--- a/static/styles.css
+++ b/static/styles.css
@@ -475,7 +475,10 @@ dialog p:first-of-type {
margin-top: 0;
}
-#qrcode {
+#qr {
display: block;
+ width: 100% !important;
+ max-width: 256px !important;
+ height: auto !important;
margin: 0 auto 16px;
}
diff --git a/views/profile.pug b/views/profile.pug
index eb46897..df9685e 100644
--- a/views/profile.pug
+++ b/views/profile.pug
@@ -9,9 +9,10 @@ mixin generateUser(user, isPrimary)
kx-claim(data-claim=claim)
block js
+ script(type='application/javascript' src='/static/qrcode.min.js' charset='utf-8')
script(type='application/javascript' src='/static/dialog-polyfill.js' charset='utf-8')
script(type='application/javascript' src='/static/openpgp.min.js' charset='utf-8')
- script(type='application/javascript' src='/static/doip.js' charset='utf-8')
+ script(type='application/javascript' src='/static/doip.min.js' charset='utf-8')
script(type='application/javascript' src='/static/kx-claim.js' charset='utf-8')
script(type='application/javascript' src='/static/kx-key.js' charset='utf-8')
script(type='application/javascript' src='/static/scripts.js' charset='utf-8')
@@ -50,6 +51,12 @@ block content
form(method="dialog")
input(type="submit" value="Close")
+ dialog#dialog--qr
+ div
+ canvas#qr
+ p
+ a#qr--altLink
+
#profileHeader.card.card--profileHeader
a.avatar(href="#")
img#profileAvatar(src=data.extra.avatarURL alt="avatar")