Improve home page and letters functionality

- 📝 Add better product descriptions on the home page
- 🎨 Improve styles: fix title that looked "like a button" (reference #7)
- 🛠️ Render markdown for letters (fix #8)
- ⬆️ Update dependencies
This commit is contained in:
Danny Morabito 2024-12-21 21:27:38 +01:00
parent 4966a3ac45
commit 77a9a6842b
Signed by: dannym
GPG key ID: 7CC8056A5A04557E
6 changed files with 127 additions and 43 deletions

View file

@ -13,8 +13,8 @@
},
"devDependencies": {
"@iconify/svelte": "^4.0.2",
"@sveltejs/adapter-node": "^5.2.9",
"@sveltejs/adapter-auto": "^3.3.1",
"@sveltejs/adapter-node": "^5.2.9",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^4.0.2",
"prettier": "^3.4.1",
@ -30,6 +30,8 @@
"@nostr-dev-kit/ndk": "^2.10.7",
"@nostr-dev-kit/ndk-cache-dexie": "^2.5.8",
"@nostr-dev-kit/ndk-svelte": "^2.3.2",
"dompurify": "^3.2.3",
"marked": "^15.0.4",
"qrcode": "^1.5.4"
}
}

View file

@ -169,8 +169,43 @@
<button onclick={nsecOk}>Continue</button>
{/if}
{:else}
<section>
<h3>
<Icon icon="mdi:email-lock" width="32" />
A Better Way to Email
</h3>
<p>
Welcome to npub.email! We've created a new kind of email service that puts your privacy first.
Think of it like regular email, but with extra security and cool features built in.
</p>
</section>
<section>
<h3>Ready to try a better kind of email? Join us and take control of your communications!</h3>
<br />
<div class="button-group">
<button onclick={login}>Login with Nostr Extension</button>
<button onclick={() => isLoggingIn = true}>Login with Nsec</button>
<button onclick={() => (isLoggingIn = true)}>Login with Nsec</button>
</div>
</section>
<section class="center">
<h3>
👀 What's Next? Even Better Privacy
</h3>
<p>
Want to see something really cool? Check out Eve - our upcoming Closed Community Networks project.<br />
We can't say much yet, but if you're into maximum privacy and love having community, you'll want to watch this
space.<br />
Take a peek at <a href="https://arx-ccn.com/">arx-ccn.com</a> if you're curious.
</p>
</section>
<section class="center">
<i>Made by Arx - Making Privacy Simple</i><br />
</section>
{/if}
<style>

View file

@ -7,27 +7,27 @@
<NostrIdentifier user={recipient}>
{#snippet extraButtons()}
<span class="remove" on:click={onRemove}>
<span class="remove" onclick={onRemove}>
<Icon icon="ph:x" />
</span>
{/snippet}
</NostrIdentifier>
<style>
.remove {
cursor: pointer;
opacity: 0.7;
transition: opacity 0.2s ease;
width: 18px;
height: 18px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.remove {
cursor: pointer;
opacity: 0.7;
transition: opacity 0.2s ease;
width: 18px;
height: 18px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.remove:hover {
opacity: 1;
background: rgba(255, 255, 255, 0.1);
}
.remove:hover {
opacity: 1;
background: rgba(255, 255, 255, 0.1);
}
</style>

View file

@ -138,30 +138,31 @@ h3 {
.section-title {
position: fixed;
display: flex;
width: calc(100%);
width: 100%;
margin: calc(var(--spacing-md) * -1);
padding: var(--spacing-md);
background: var(--ternary);
border: 1px solid var(--accent);
z-index: 99999;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
place-content: center;
place-content: center;
align-items: center;
gap: var(--spacing-xs);
font-size: 1.25rem;
font-weight: bold;
&:is(.dialog-content .section-title) {
background: var(--ternary);
border: 1px solid var(--accent);
border-top-left-radius: 16px;
border-bottom-left-radius: 16px;
}
> .close-button {
position: absolute;
top: var(--spacing-md);
right: calc(
var(--spacing-md) * 2 + 1.5rem
);
right: calc(var(--spacing-md) * 2 + 1.5rem);
}
& + * {
margin-top: calc(
1.5rem +
var(--spacing-md) * 3
);
margin-top: calc(1.5rem + var(--spacing-md) * 3);
}
}

View file

@ -1,11 +1,50 @@
p.error {
color: oklch(60% 50% 35);
font-weight: 700;
font-size: 0.9rem;
text-align: center;
text-shadow: -1.5px -1.5px 0 oklch(15% 10% 35),
1.5px -1.5px 0 oklch(15% 10% 35),
-1.5px 1.5px 0 oklch(15% 10% 35),
1.5px 1.5px 0 oklch(15% 10% 35);
letter-spacing: 1px;
color: oklch(60% 50% 35);
font-weight: 700;
font-size: 0.9rem;
text-align: center;
text-shadow: -1.5px -1.5px 0 oklch(15% 10% 35), 1.5px -1.5px 0
oklch(15% 10% 35), -1.5px 1.5px 0 oklch(15% 10% 35), 1.5px 1.5px 0
oklch(15% 10% 35);
letter-spacing: 1px;
}
blockquote {
--hue: calc(var(--base-hue));
border-left: 2px solid oklch(50% 0.2 var(--hue));
margin: 0;
padding: 0;
padding-left: 1em;
}
:is(blockquote blockquote) {
--hue: calc(var(--base-hue) + 45);
}
:is(blockquote blockquote blockquote) {
--hue: calc(var(--base-hue) + 90);
}
:is(blockquote blockquote blockquote blockquote) {
--hue: calc(var(--base-hue) + 135);
}
:is(blockquote blockquote blockquote blockquote blockquote) {
--hue: calc(var(--base-hue) + 180);
}
:is(blockquote blockquote blockquote blockquote blockquote blockquote) {
--hue: calc(var(--base-hue) + 225);
}
:is(blockquote blockquote blockquote blockquote blockquote blockquote blockquote) {
--hue: calc(var(--base-hue) + 270);
}
:is(blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote) {
--hue: calc(var(--base-hue) + 315);
}
:is(blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote blockquote) {
--hue: var(--base-hue);
}

View file

@ -8,6 +8,8 @@
import { Letter } from '$lib/letter';
import Dialog from '../../../components/Dialog.svelte';
import AnimatedQRCode from '../../../components/AnimatedQRCode.svelte';
import DOMPurify from 'dompurify';
import * as marked from 'marked';
const { data } = $props();
const { id } = data;
@ -18,7 +20,7 @@
let stampDialogOpen = $state(false);
onMount(async () => {
let letterEvent = await $ndk.fetchEvent(id);
const letterEvent = await $ndk.fetchEvent(id);
if (!letterEvent) {
loading = false;
error = 'Error fetching letter';
@ -28,12 +30,15 @@
if (!(letter instanceof Letter)) {
error = 'Message is not a letter';
loading = false;
return;
}
renderedContent = DOMPurify.sanitize(await marked.parse(letter.content, {
async: true
}));
loading = false;
});
$inspect(letter);
function handleReply() {
if (!letter) return;
const params = {
@ -49,6 +54,8 @@
const url = `/compose?${queryString}`;
goto(url);
}
let renderedContent = $state('loading...');
</script>
{#if loading}
@ -117,7 +124,7 @@
</div>
</div>
<pre class="content">{letter.content}</pre>
<pre class="content">{@html renderedContent}</pre>
</div>
{/if}