mirror of
https://codeberg.org/vlw/victorwesterlund.com.git
synced 2025-09-14 03:23:41 +02:00
dev21w36f-a
This commit is contained in:
parent
b05c451f11
commit
7d80341f34
7 changed files with 219 additions and 64 deletions
|
@ -13,6 +13,10 @@ body .modal.active ~ main .screen {
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
.modal.active + .modal {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
/* -- Boilerplate -- */
|
||||
|
||||
.modal {
|
||||
|
|
|
@ -67,7 +67,9 @@
|
|||
color: var(--swatch-accent);
|
||||
}
|
||||
|
||||
a,
|
||||
picture {
|
||||
text-decoration: none;
|
||||
display: contents;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,64 @@ class Modal extends Interaction {
|
|||
return element;
|
||||
}
|
||||
|
||||
error(message) {
|
||||
const oops = document.createElement("p");
|
||||
const infoButton = document.createElement("p");
|
||||
|
||||
oops.classList.add("error");
|
||||
oops.innerText = "🤯\nSomething went wrong";
|
||||
|
||||
infoButton.innerText = "more info..";
|
||||
infoButton.addEventListener("click",() => {
|
||||
const details = new Dialog();
|
||||
|
||||
details.insertHTML(`<h1>📄 Error report</h1><pre>${message}</pre>`);
|
||||
details.open();
|
||||
|
||||
this.close();
|
||||
});
|
||||
|
||||
this.insertElement(infoButton);
|
||||
this.insertElement(oops);
|
||||
}
|
||||
|
||||
// Open page from "assets/pages"
|
||||
openPage(page) {
|
||||
// Show a spinner while fetching
|
||||
const spinner = document.createElement("div");
|
||||
spinner.classList = "logo spinner";
|
||||
this.element.setAttribute("data-page",page);
|
||||
this.insertElement(spinner);
|
||||
this.open();
|
||||
|
||||
// Fetch the requested page
|
||||
this.getPage(page).then(html => {
|
||||
this.insertHTML(html);
|
||||
this.bindAll(this.inner);
|
||||
})
|
||||
.catch(error => {
|
||||
const tryAgain = new Button({
|
||||
text: "try again",
|
||||
type: "solid"
|
||||
});
|
||||
tryAgain.element.addEventListener("click",() => {
|
||||
// Clear and recreate modal structure
|
||||
destroy(this.inner);
|
||||
this.applyTemplate(this.element);
|
||||
this.init();
|
||||
this.insertElement(spinner);
|
||||
// Attempt to fetch the requested url again (with soft rate-limiting)
|
||||
setTimeout(() => {
|
||||
this.openPage(page);
|
||||
destroy(spinner);
|
||||
},500);
|
||||
});
|
||||
this.insertElement(tryAgain.element);
|
||||
this.error(error);
|
||||
})
|
||||
.finally(() => destroy(spinner));
|
||||
}
|
||||
|
||||
open() {
|
||||
setTimeout(() => this.element.classList.add("active"),this.transition / 2);
|
||||
}
|
||||
|
@ -117,58 +175,4 @@ export class Card extends Modal {
|
|||
this.bind(closeButton.element);
|
||||
this.inner.appendChild(closeButton.element);
|
||||
}
|
||||
|
||||
error(message) {
|
||||
const oops = document.createElement("p");
|
||||
const infoButton = document.createElement("p");
|
||||
|
||||
oops.classList.add("error");
|
||||
oops.innerText = "🤯\nSomething went wrong";
|
||||
|
||||
infoButton.innerText = "more info..";
|
||||
infoButton.addEventListener("click",() => {
|
||||
const details = new Dialog();
|
||||
|
||||
details.insertHTML(`<h1>📄 Error report</h1><pre>${message}</pre>`);
|
||||
details.open();
|
||||
|
||||
this.close();
|
||||
});
|
||||
|
||||
this.insertElement(infoButton);
|
||||
this.insertElement(oops);
|
||||
}
|
||||
|
||||
// Open page from "assets/pages"
|
||||
openPage(page) {
|
||||
// Show a spinner while fetching
|
||||
const spinner = document.createElement("div");
|
||||
spinner.classList = "logo spinner";
|
||||
this.element.setAttribute("data-page",page);
|
||||
this.insertElement(spinner);
|
||||
this.open();
|
||||
|
||||
// Fetch the requested page
|
||||
this.getPage(page).then(html => {
|
||||
this.insertHTML(html);
|
||||
this.bindAll(this.inner);
|
||||
})
|
||||
.catch(error => {
|
||||
const tryAgain = new Button({
|
||||
text: "try again",
|
||||
type: "solid"
|
||||
});
|
||||
tryAgain.element.addEventListener("click",() => {
|
||||
// Clear and recreate modal structure
|
||||
destroy(this.inner);
|
||||
this.applyTemplate(this.element);
|
||||
this.init();
|
||||
// Attempt to fetch the requested url again
|
||||
this.openPage(page);
|
||||
});
|
||||
this.insertElement(tryAgain.element);
|
||||
this.error(error);
|
||||
})
|
||||
.finally(() => destroy(spinner));
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright © Victor Westerlund - No libraries! 😲
|
||||
import { default as Preload } from "./modules/Preload.mjs";
|
||||
import { default as Interaction } from "./modules/UI.mjs";
|
||||
import { default as Interaction, destroy } from "./modules/UI.mjs";
|
||||
import "./modules/Debugging.mjs";
|
||||
|
||||
// Load these assets when the DOM is ready (not needed right away)
|
||||
|
@ -37,7 +37,7 @@ const interactions = {
|
|||
const module = import("./modules/Modals.mjs");
|
||||
const interactions = {
|
||||
getContact: (event) => {
|
||||
const service = event.target.getAttribute("data-value");
|
||||
const service = event.target.dataset.value;
|
||||
module.then(modals => {
|
||||
event.target.closest(".modal").close();
|
||||
const card = new modals.Card(interactions);
|
||||
|
@ -45,12 +45,21 @@ const interactions = {
|
|||
});
|
||||
},
|
||||
copyText: (event) => {
|
||||
const memory = event.target.innerText;
|
||||
event.target.classList.add("bounce");
|
||||
event.target.innerText = "copied!";
|
||||
event.target.classList.add("copied");
|
||||
const copied = document.createElement("p");
|
||||
copied.innerText = "copied!";
|
||||
event.target.appendChild(copied);
|
||||
|
||||
setTimeout(() => {
|
||||
event.target.innerText = memory;
|
||||
event.target.classList.remove("copied");
|
||||
destroy(copied);
|
||||
},1000);
|
||||
},
|
||||
showPgpKey: () => {
|
||||
module.then(modals => {
|
||||
const dialog = new modals.Dialog();
|
||||
dialog.openPage("contact_email_pgp");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -58,10 +67,6 @@ const interactions = {
|
|||
const card = new modals.Card(interactions);
|
||||
card.openPage("contact");
|
||||
});
|
||||
},
|
||||
openSearch: () => {
|
||||
const module = import("./modules/Search.mjs");
|
||||
document.body.classList.add("searchActive");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
64
public/assets/pages/contact_email.html
Normal file
64
public/assets/pages/contact_email.html
Normal file
|
@ -0,0 +1,64 @@
|
|||
<style>
|
||||
.button.copied {
|
||||
pointer-events: none;
|
||||
animation: beat 500ms forwards;
|
||||
animation-delay: 200ms;
|
||||
}
|
||||
|
||||
.button.copied svg,
|
||||
.button.copied p:first-of-type {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.button.copied p:last-of-type {
|
||||
position: absolute;
|
||||
animation: slide 1000ms forwards;
|
||||
}
|
||||
|
||||
@keyframes beat {
|
||||
0% { transform: scale(1); }
|
||||
25% { transform: scale(.95); }
|
||||
55% { transform: scale(1.05); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
@keyframes slide {
|
||||
0% { transform: translateY(calc(var(--padding))); opacity: 0; }
|
||||
30% { transform: translateY(0); opacity: 1; }
|
||||
70% { transform: translateY(0); opacity: 1; }
|
||||
100% { transform: translateY(calc(var(--padding) * -1)); opacity: 0; }
|
||||
}
|
||||
|
||||
#interaction {
|
||||
color: var(--swatch-accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#interaction::before {
|
||||
content: "tap ";
|
||||
}
|
||||
|
||||
@media (max-width: 300px) {
|
||||
.button.copied p:last-of-type {
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
|
||||
@media (pointer: fine) {
|
||||
#interaction::before {
|
||||
content: "click ";
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="button phantom" data-action="showPgpKey">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12.65 10C11.83 7.67 9.61 6 7 6c-3.31 0-6 2.69-6 6s2.69 6 6 6c2.61 0 4.83-1.67 5.65-4H17v4h4v-4h2v-4H12.65zM7 14c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg>
|
||||
<p>show PGP key</p>
|
||||
</div>
|
||||
<p></p>
|
||||
<h1>hello@victorwesterlund.com</h1>
|
||||
<p>You can also <a id="interaction" href="mailto:hello@victorwesterlund.com?subject=Hello Victor!">here</a> to send a mail directly from your mail app</p>
|
||||
<p></p>
|
||||
<div class="button solid" data-action="copyText">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18 2H9c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h9c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H9V4h9v12zM3 15v-2h2v2H3zm0-5.5h2v2H3v-2zM10 20h2v2h-2v-2zm-7-1.5v-2h2v2H3zM5 22c-1.1 0-2-.9-2-2h2v2zm3.5 0h-2v-2h2v2zm5 0v-2h2c0 1.1-.9 2-2 2zM5 6v2H3c0-1.1.9-2 2-2z"/></svg>
|
||||
<p>copy email</p>
|
||||
</div>
|
39
public/assets/pages/contact_email_pgp.html
Normal file
39
public/assets/pages/contact_email_pgp.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
<style>
|
||||
|
||||
</style>
|
||||
<h1>🔑 PGP Public Key</h1>
|
||||
<pre>
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBF/K6MkBCACkRMhMfYdeNP+M3XQoZHQVJgippQvYZ4QqH6F6brWD5989Xy5W
|
||||
kDCvLbmPJ66boqB0dHExswOvMlhfFha65pRmfP6lIoIxZlZKwll1XASP2osS8f6r
|
||||
63T7hAbL3V2Dkm49tiH1tk578xGomDrxOrd4izpH4mn9AyBIL4M+5j34bKFVZKQ+
|
||||
QfMu7tduF/1oQHfDaXJeLXSfn5cNTy8DlLcLJKUSk4cjabf1D88gMVszqAAC5o1a
|
||||
fI0YxoyZ+Fv+CmyrQm2iIZ3+MyDU9JAvoImtlp1h5aNgbFRDi2vKcSlv158Hq97Z
|
||||
XlH1ttRZuFZiJzb8iukgUUFi4RORoXWt2rtNABEBAAG0LlZpY3RvciBXZXN0ZXJs
|
||||
dW5kIDxoZWxsb0B2aWN0b3J3ZXN0ZXJsdW5kLmNvbT6JATUEEAEIACkFAl/K6MkG
|
||||
CwkIBwMCCRBb4MsL47tp2gQVCAIKAxYCAQIZAQIbAwIeAQAAJ5MIAKDl9yHjwTO7
|
||||
20sDrPa6ECsSBU/FwkvkWecuauvY19/OqtacNk8dEeiITLeUeBXkvNzN+P0y8hoF
|
||||
ABZeir59dsY00iIp8gm03eLalhcblR5jYe3c08HssJH8PksczP3kitRNLvPAf2nU
|
||||
BYg3zca5Ka21/4BPRLFb9SAQGxfHyZdy3Poug+o+pokbeK2wLqqfSMtH+waBB6Lg
|
||||
2dRXuEnaZorUpNBpsahxastvNehv31Ke41Brvft15VKpO25GKZDPhm0odXMth1/J
|
||||
pzWRQtndazY2guB0Ft+5wujv28HFCgVgZn2fKiQVytAetO+/wzPijBkGRvdIE+Zb
|
||||
VRd3Nc0mHI65AQ0EX8royQEIALcoWEurmyXD2LoGvR+sYW+YPAPM6KG8KF4cWUn8
|
||||
8+kZ6F4FH9OW64di2npYe3x+zR7DgQ1yHXcmalAsP0nN4JWTavLwsSO+JAv8NpL5
|
||||
bgDs6fGaEQFl+X4fYOpkBkBmb1JrbnBk1a2u3qsEw8t7+wW1LG9z/Si5+G1KQko8
|
||||
x/PEaZ2ZVv7L51ZfIQRnMtl4vL5X23BPVsDywotvuFqlTiSjGP4CR0lVa5CRv3DJ
|
||||
FSmHxAxeI0vMMlwbIIUTrtwJR320sZvh2cRiwAXHQXm6l0ojzRnl46mmXnB3N6q9
|
||||
PyWOaUgPrMFjT24wtgopIOwbFAT3xTr1Un0FbdeaG9JhdJ8AEQEAAYkBHwQYAQgA
|
||||
EwUCX8royQkQW+DLC+O7adoCGwwAAIV/B/9OLYeQOxbXh1/hvW7/oTvN1py8wfFq
|
||||
buvQSrb/MZKm6lZgG+kQy3DWjGTi/xvNqDHfBiObFSGso8RHSbHFldzEuMgrgoWW
|
||||
/4JH1GDiKOp+rmBxfG30/DzOoFSfVcUfP5r8xNQby4Bh6zJhKPKVB3sZjO8cHNZD
|
||||
HcNAqT3Gh5yFzsUna+ZjvPF7iU5RF1YP46dsIdvuo4xFbHpEPoZs7wgZijf+vmKO
|
||||
lP61UFvKuXzwcLiI6s919EBJ9+7je8ZAxe6BCaazk+AhxXeokVvDgwQ150DNk4up
|
||||
1ftWZI0LHqEpVGNejQ09uu+TdC/ISy/Ti0XKlJDER1eUL577YRUl876Y
|
||||
=2qWm
|
||||
-----END PGP PUBLIC KEY BLOCK-----</pre>
|
||||
<h2>5466 B1EB 2F44 6D3D DC34 E9F7 5BE0 CB0B E3BB 69DA</h2>
|
||||
<a href="https://storage.googleapis.com/public.victorwesterlund.com/publickey.gpg"><div class="button solid">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 20h14v-2H5v2zM19 9h-4V3H9v6H5l7 7 7-7z"/></svg>
|
||||
<p>download .gpg</p>
|
||||
</div></a>
|
|
@ -29,10 +29,47 @@
|
|||
padding: 10px 15px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.button.copied {
|
||||
pointer-events: none;
|
||||
animation: beat 500ms forwards;
|
||||
animation-delay: 200ms;
|
||||
}
|
||||
|
||||
.button.copied svg,
|
||||
.button.copied p:first-of-type {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.button.copied p:last-of-type {
|
||||
position: absolute;
|
||||
animation: slide 1000ms forwards;
|
||||
}
|
||||
|
||||
@keyframes beat {
|
||||
0% { transform: scale(1); }
|
||||
25% { transform: scale(.95); }
|
||||
55% { transform: scale(1.05); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
@keyframes slide {
|
||||
0% { transform: translateY(calc(var(--padding))); opacity: 0; }
|
||||
30% { transform: translateY(0); opacity: 1; }
|
||||
70% { transform: translateY(0); opacity: 1; }
|
||||
100% { transform: translateY(calc(var(--padding) * -1)); opacity: 0; }
|
||||
}
|
||||
|
||||
@media (max-width: 300px) {
|
||||
.button.copied p:last-of-type {
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<img id="logo_signal" src="assets/img/icons/signal.svg"/>
|
||||
<h1 id="number">+4670-2452459</h1>
|
||||
<p>Signal is a free and encrypted message platform with apps for all major platforms.</p>
|
||||
<div class="button solid" data-action="copyText">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18 2H9c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h9c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H9V4h9v12zM3 15v-2h2v2H3zm0-5.5h2v2H3v-2zM10 20h2v2h-2v-2zm-7-1.5v-2h2v2H3zM5 22c-1.1 0-2-.9-2-2h2v2zm3.5 0h-2v-2h2v2zm5 0v-2h2c0 1.1-.9 2-2 2zM5 6v2H3c0-1.1.9-2 2-2z"/></svg>
|
||||
<p>copy number</p>
|
||||
</div>
|
Loading…
Add table
Reference in a new issue