import defaultAvatar from '@/default-avatar.png'; import { getSigner, getUserProfile, ndk } from '@/ndk'; import type { ArxInputChangeEvent } from '@components/General/Input'; import { NDKEvent, type NDKUserProfile } from '@nostr-dev-kit/ndk'; import { LitElement, css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { when } from 'lit/directives/when.js'; import '@components/Breadcrumbs'; import '@components/DateTimeSettings'; import '@components/General/Button'; import '@components/General/Card'; import '@components/General/Fieldset'; import '@components/General/Input'; import '@components/RelayLogs'; @customElement('arx-settings') export class EveSettings extends LitElement { static override styles = css` :host { display: block; font-family: var(--font-family, "Inter", system-ui, sans-serif); margin: 0 auto; line-height: 1.6; color: var(--color-base-content); background-color: var(--color-base-100); } .profile-image { width: 140px; height: 140px; border-radius: 50%; object-fit: cover; border: calc(var(--border) * 2) solid var(--color-base-100); box-shadow: calc(var(--depth) * 3px) calc(var(--depth) * 3px) calc(var(--depth) * 6px) oklch(from var(--color-base-content) l c h / 0.15), calc(var(--depth) * -2px) calc(var(--depth) * -2px) calc(var(--depth) * 4px) oklch(from var(--color-base-100) l c h / 0.6); transition: transform 0.3s, box-shadow 0.3s; margin: 0 auto; } .profile-image:hover { transform: scale(1.05); box-shadow: calc(var(--depth) * 4px) calc(var(--depth) * 4px) calc(var(--depth) * 8px) oklch(from var(--color-accent) l c h / 0.3), calc(var(--depth) * -2px) calc(var(--depth) * -2px) calc(var(--depth) * 6px) oklch(from var(--color-base-100) l c h / 0.6); } .profile-header { display: flex; flex-direction: column; align-items: center; justify-content: center; } `; @state() private loading = true; @state() private saving = false; @state() private profile: NDKUserProfile | undefined; @state() private error: string | undefined; @state() private darkMode = false; @state() private relayStatus: { running: boolean; pid: number | null; logs: string[] } = { running: false, pid: null, logs: [], }; private async updateRelayStatus() { this.relayStatus = await window.relay.getStatus(); if (this.relayStatus.running) setTimeout(() => this.updateRelayStatus(), 2000); } protected override async firstUpdated() { try { this.profile = await getUserProfile(); this.darkMode = localStorage.getItem('darkMode') === 'true'; this.updateRelayStatus(); this.loading = false; } catch (err) { this.error = 'Failed to load profile'; console.error(err); this.loading = false; } } private handleInputChange(field: string, e: ArxInputChangeEvent) { this.profile = { ...this.profile, [field]: e.detail.value, }; } private async saveProfile() { if (this.saving) return; this.saving = true; try { await getSigner(); const event = new NDKEvent(ndk); event.kind = 0; event.content = JSON.stringify(this.profile); await event.sign(); await event.publish(); } catch (err) { alert(err); console.error(err); } finally { this.saving = false; } } private toggleDarkMode() { this.darkMode = !this.darkMode; localStorage.setItem('darkMode', this.darkMode.toString()); document.body.classList.toggle('dark', this.darkMode); } override render() { if (this.error) return html``; if (this.loading) return html``; const breadcrumbItems = [{ text: 'Home', href: '/' }, { text: 'Settings' }]; return html` this.toggleDarkMode()} > ${when( this.profile!.picture, () => html`
Profile { (e.target as HTMLImageElement).src = defaultAvatar; }} />
`, )} this.handleInputChange('name', e)} placeholder="Your display name" > this.handleInputChange('picture', e)} placeholder="https://example.com/your-image.jpg" > this.handleInputChange('banner', e)} placeholder="https://example.com/your-image.jpg" >

${this.relayStatus.running ? `Relay is running. PID: ${this.relayStatus.pid}` : 'Relay is not running'}

`; } }