diff --git a/esbuildconf.js b/esbuildconf.js index 8062f34..59e5fe4 100644 --- a/esbuildconf.js +++ b/esbuildconf.js @@ -20,6 +20,7 @@ export const options = { 'src/main.css', 'src/main.js', 'src/manifest.json', + 'src/worker.js', ], outdir: 'dist', //entryNames: '[name]-[hash]', TODO: replace urls in index.html with hashed paths diff --git a/src/cards.css b/src/cards.css index 2a407b4..255d421 100644 --- a/src/cards.css +++ b/src/cards.css @@ -10,7 +10,7 @@ } @media (orientation: portrait) { .mbox { - padding: 0 calc(.5 * var(--gap)); + padding: 0 var(--gap-half); } } .mbox:last-child { @@ -97,6 +97,16 @@ overflow: visible; position: relative; } +.mbox .buttons { + margin-top: .2rem; +} +.mbox button:not(#publish) { + --bg-color: none; + --border-color: none; +} +.mbox button img + small { + padding-left: .5rem; +} .mobx-replies { flex-grow: 1; position: relative; @@ -158,6 +168,4 @@ max-width: 48rem; padding: 1.5rem 1.8rem; width: 100%; - /* TODO: revert when things calm down or we find an alternative */ - display: none; } diff --git a/src/cryptoutils.js b/src/cryptoutils.js new file mode 100644 index 0000000..2c2b265 --- /dev/null +++ b/src/cryptoutils.js @@ -0,0 +1,24 @@ +/** + * evaluate the difficulty of hex32 according to nip-13. + * @param hex32 a string of 64 chars - 32 bytes in hex representation + */ +export const zeroLeadingBitsCount = (hex32) => { + let count = 0; + for (let i = 0; i < 64; i += 2) { + const hexbyte = hex32.slice(i, i + 2); // grab next byte + if (hexbyte == '00') { + count += 8; + continue; + } + // reached non-zero byte; count number of 0 bits in hexbyte + const bits = parseInt(hexbyte, 16).toString(2).padStart(8, '0'); + for (let b = 0; b < 8; b++) { + if (bits[b] == '1' ) { + break; // reached non-zero bit; stop + } + count += 1; + } + break; + } + return count; +}; diff --git a/src/error.css b/src/error.css new file mode 100644 index 0000000..8e24758 --- /dev/null +++ b/src/error.css @@ -0,0 +1,36 @@ +#errorOverlay { + background: var(--bgcolor-danger); + bottom: 0; + display: flex; + flex-direction: column; + left: 0; + overflow: auto; + padding: var(--gap); + position: fixed; + right: 0; + top: 0; + z-index: 100; +} + +.error-title { + margin-top: 0; +} + +#errorOverlay button { + background-color: rgba(0 0 0 / .5); + border: none; + display: inline-block; +} +#errorOverlay button:focus { + outline: 2px solid white; + outline-offset: var(--focus-outline-offset); +} + +#errorOverlay .buttons { + max-width: var(--max-width); +} +@media (orientation: portrait) { + #errorOverlay .buttons { + flex-basis: 4rem; + } +} diff --git a/src/form.css b/src/form.css index 5a0151b..562c7a0 100644 --- a/src/form.css +++ b/src/form.css @@ -43,6 +43,7 @@ label { transition: background-color var(--transition-duration); } +input[type="number"], input[type="password"], input[type="text"], input[type="url"], @@ -54,6 +55,7 @@ textarea { margin: 0 0 1.2rem 0; padding: var(--padding); } +input[type="number"]:focus, input[type="password"]:focus, input[type="text"]:focus, input[type="url"]:focus, @@ -95,14 +97,22 @@ textarea:focus { align-items: center; display: flex; flex-basis: 100%; - justify-content: flex-end; gap: var(--gap); - margin-top: 2rem; + justify-content: start; + margin-top: var(--gap-half); min-height: 3.2rem; } +form .buttons, +.form .buttons, .form-inline .buttons { flex-basis: fit-content; - margin-top: 0; + justify-content: end; +} + +.buttons img, +.buttons small, +.buttons span { + vertical-align: middle; } button { @@ -121,24 +131,11 @@ button:focus { .btn-inline { --border-color: transparent; - align-items: center; background: transparent; - color: var(--color); - display: inline-flex; - gap: .5ch; + color: var(--color-accent); + display: inline-block; line-height: 1; - padding: .6rem; -} -.btn-inline img { - max-height: 18px; - max-width: 18px; -} -.btn-inline img[alt] { - color: #7f7f7f; - line-height: 1px; -} -.btn-inline img[alt]::before { - font-size: 3.4rem; + padding: 0 .6rem; } .btn-danger { @@ -154,6 +151,7 @@ button:disabled { .form-status { flex-basis: 100%; flex-grow: 1; + min-height: 1.8rem; padding: var(--padding); } @@ -169,11 +167,13 @@ button:disabled { margin-left: var(--gap); } .form-inline button, +.form-inline input[type="number"], .form-inline input[type="text"], .form-inline textarea { margin: .4rem 0; } +.form-inline input[type="number"], .form-inline input[type="text"], .form-inline textarea { flex-basis: 50%; @@ -187,6 +187,46 @@ button:disabled { flex-grow: 0; } +label.number { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + gap: var(--gap); + padding: 0; +} +* + label.number { + margin: var(--gap) 0 0 0; +} +label.number span { + flex-grow: 1; + padding: 0 0 0 var(--padding); +} +label.number input[type="number"] { + align-self: baseline; + margin-bottom: 0; +} +@media (orientation: landscape) { + label.number span { + align-self: center; + } + label.number input[type="number"] + span { + padding: 0 var(--padding) 0 0; + } +} +@media (orientation: portrait) { + label.number { + flex-direction: column; + gap: var(--gap-half); + padding: 0; + } + label.number span { + padding: 0 var(--padding); + } + label.number input[type="number"] { + align-self: stretch; + } +} + button#publish { align-self: end; order: 2; diff --git a/src/index.html b/src/index.html index 23f0f3e..31493a0 100644 --- a/src/index.html +++ b/src/index.html @@ -83,6 +83,27 @@ +