diff --git a/package.json b/package.json
index b2ae9edc..6f32adcd 100644
--- a/package.json
+++ b/package.json
@@ -57,7 +57,7 @@
"@getalby/lightning-tools": "^6.1.0",
"@getalby/sdk": "^5.1.2",
"@noble/curves": "^1.9.7",
- "@pomade/core": "^0.1.1",
+ "@pomade/core": "^0.2.0",
"@poppanator/sveltekit-svg": "^4.2.1",
"@sveltejs/adapter-static": "^3.0.10",
"@tiptap/core": "^2.27.2",
@@ -65,16 +65,16 @@
"@types/throttle-debounce": "^5.0.2",
"@vite-pwa/assets-generator": "^0.2.6",
"@vite-pwa/sveltekit": "^0.6.8",
- "@welshman/app": "^0.8.7",
- "@welshman/content": "^0.8.7",
- "@welshman/editor": "^0.8.7",
- "@welshman/feeds": "^0.8.7",
- "@welshman/lib": "^0.8.7",
- "@welshman/net": "^0.8.7",
- "@welshman/router": "^0.8.7",
- "@welshman/signer": "^0.8.7",
- "@welshman/store": "^0.8.7",
- "@welshman/util": "^0.8.7",
+ "@welshman/app": "^0.8.8",
+ "@welshman/content": "^0.8.8",
+ "@welshman/editor": "^0.8.8",
+ "@welshman/feeds": "^0.8.8",
+ "@welshman/lib": "^0.8.8",
+ "@welshman/net": "^0.8.8",
+ "@welshman/router": "^0.8.8",
+ "@welshman/signer": "^0.8.8",
+ "@welshman/store": "^0.8.8",
+ "@welshman/util": "^0.8.8",
"compressorjs-next": "^1.1.2",
"daisyui": "^4.12.24",
"date-picker-svelte": "^2.17.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d447fc03..98946c21 100644
Binary files a/pnpm-lock.yaml and b/pnpm-lock.yaml differ
diff --git a/src/app/components/LogIn.svelte b/src/app/components/LogIn.svelte
index 3b3768cf..ca4b5a9a 100644
--- a/src/app/components/LogIn.svelte
+++ b/src/app/components/LogIn.svelte
@@ -34,7 +34,6 @@
const onSuccess = async (session: Session) => {
addSession(session)
- pushToast({message: "Successfully logged in!"})
setChecked("*")
clearModals()
}
diff --git a/src/app/components/LogInEmail.svelte b/src/app/components/LogInEmail.svelte
index d63f9566..133b2778 100644
--- a/src/app/components/LogInEmail.svelte
+++ b/src/app/components/LogInEmail.svelte
@@ -20,6 +20,7 @@
import {pushModal, clearModals} from "@app/util/modal"
import {setChecked} from "@app/util/notifications"
import {pushToast} from "@app/util/toast"
+ import {deleteOldPomadeSessions} from "@app/core/commands"
interface Props {
email?: string
@@ -51,7 +52,7 @@
if (res.ok && clientOptions) {
loginWithPomade(clientOptions.group.group_pk.slice(2), email, clientOptions)
- pushToast({message: "Successfully logged in!"})
+ deleteOldPomadeSessions()
setChecked("*")
clearModals()
} else {
diff --git a/src/app/components/LogInKey.svelte b/src/app/components/LogInKey.svelte
index 38a6e507..3a31e58d 100644
--- a/src/app/components/LogInKey.svelte
+++ b/src/app/components/LogInKey.svelte
@@ -57,7 +57,6 @@
}
loginWithNip01(secret)
- pushToast({message: "Successfully logged in!"})
setChecked("*")
clearModals()
} catch (e) {
diff --git a/src/app/components/LogInOTPConfirm.svelte b/src/app/components/LogInOTPConfirm.svelte
index 532d70ae..b6cf823c 100644
--- a/src/app/components/LogInOTPConfirm.svelte
+++ b/src/app/components/LogInOTPConfirm.svelte
@@ -17,6 +17,7 @@
import {setChecked} from "@app/util/notifications"
import {pushToast} from "@app/util/toast"
import {POMADE_SIGNERS} from "@app/core/state"
+ import {deleteOldPomadeSessions} from "@app/core/commands"
type Props = {
email: string
@@ -63,7 +64,7 @@
if (res.ok && clientOptions) {
loginWithPomade(clientOptions.group.group_pk.slice(2), email, clientOptions)
- pushToast({message: "Successfully logged in!"})
+ deleteOldPomadeSessions()
setChecked("*")
clearModals()
} else {
diff --git a/src/app/components/LogOut.svelte b/src/app/components/LogOut.svelte
index 39981013..762f9107 100644
--- a/src/app/components/LogOut.svelte
+++ b/src/app/components/LogOut.svelte
@@ -9,8 +9,7 @@
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
- import {Push} from "@app/util/notifications"
- import {kv, db} from "@app/core/storage"
+ import {logout} from "@app/util/logout"
const back = () => history.back()
@@ -18,13 +17,7 @@
loading = true
try {
- await Push.disable()
- await kv.clear()
- await db.clear()
-
- localStorage.clear()
-
- window.location.href = "/"
+ await logout()
} catch (e) {
console.error(e)
loading = false
diff --git a/src/app/components/PomadeSessions.svelte b/src/app/components/PomadeSessions.svelte
index 6567b462..e710c2a2 100644
--- a/src/app/components/PomadeSessions.svelte
+++ b/src/app/components/PomadeSessions.svelte
@@ -1,51 +1,30 @@
@@ -93,28 +72,46 @@
Other Sessions
{#each sessions as sessionItem (sessionItem.client)}
-
-
-
{sessionItem.client.slice(0, 8)}
-
-
- Created {formatDate(sessionItem.created_at)}
-
-
- Last active: {formatDate(sessionItem.last_activity)}
-
+
+
+
+ Session {sessionItem.client.slice(0, 8)}
+
+ {#if sessionItem.deactivated_at}
+ Deactivated
+ {/if}
+
+
+
+
+ {#if menuClient === sessionItem.client}
+
+
+ -
+
+
+
+
+ {/if}
+
+
+
+
+ Created {formatDate(sessionItem.created_at)}
+
+
+ Active {formatDate(sessionItem.last_activity)}
-
{/each}
diff --git a/src/app/components/ProfileDelete.svelte b/src/app/components/ProfileDelete.svelte
index 870bef08..282fb0d5 100644
--- a/src/app/components/ProfileDelete.svelte
+++ b/src/app/components/ProfileDelete.svelte
@@ -23,9 +23,8 @@
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import {INDEXER_RELAYS, PLATFORM_NAME, userSpaceUrls} from "@app/core/state"
- import {kv, db} from "@app/core/storage"
import {pushToast} from "@app/util/toast"
- import {Push} from "@app/util/notifications"
+ import {logout} from "@app/util/logout"
let progress: number | undefined = $state(undefined)
let confirmText = $state("")
@@ -88,13 +87,7 @@
await sleep(2000)
// Goodbye forever!
- await Push.disable()
- await kv.clear()
- await db.clear()
-
- localStorage.clear()
-
- window.location.href = "/"
+ await logout()
}
const confirm = async () => {
diff --git a/src/app/components/SignUpEmail.svelte b/src/app/components/SignUpEmail.svelte
index 7f53072c..8fd919f9 100644
--- a/src/app/components/SignUpEmail.svelte
+++ b/src/app/components/SignUpEmail.svelte
@@ -18,7 +18,7 @@
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import SignUpEmailConfirm from "@app/components/SignUpEmailConfirm.svelte"
- import {pushToast} from "@app/util/toast"
+ import {pushToast, popToast} from "@app/util/toast"
import {pushModal} from "@app/util/modal"
type Props = {
@@ -40,6 +40,11 @@
loading = true
try {
+ const toastId = pushToast({
+ timeout: 60_000,
+ message: "Creating your account, please wait...",
+ })
+
const secret = getKey
("signup.secret")!
const {clientOptions, ...registerRes} = await Client.register(2, 3, secret)
@@ -74,6 +79,7 @@
setKey("signup.email", email)
setKey("signup.clientOptions", clientOptions)
+ popToast(toastId)
pushModal(SignUpEmailConfirm, {next})
} catch (e) {
console.error(e)
diff --git a/src/app/core/commands.ts b/src/app/core/commands.ts
index 2ea604a8..5e749d9b 100644
--- a/src/app/core/commands.ts
+++ b/src/app/core/commands.ts
@@ -1,6 +1,8 @@
import {nwc} from "@getalby/sdk"
import * as nip19 from "nostr-tools/nip19"
import {get, derived} from "svelte/store"
+import {Client} from "@pomade/core"
+import type {SessionItem} from "@pomade/core"
import {
first,
sha256,
@@ -71,6 +73,7 @@ import {
waitForThunkError,
getPubkeyRelays,
userBlossomServerList,
+ isPomadeSession,
getThunkError,
} from "@welshman/app"
import {compressFile} from "@lib/html"
@@ -699,3 +702,58 @@ export const updateProfile = async ({
await publishThunk({event, relays}).complete
}
+
+// Pomade
+
+export type PomadeSessionWithPeers = SessionItem & {peers: string[]}
+
+export const loadOtherPomadeSessions = async () => {
+ const $session = get(session)
+
+ if (isPomadeSession($session)) {
+ const client = new Client($session.clientOptions)
+ const result = await client.listSessions()
+ const pubkey = await client.getPubkey()
+
+ if (result.ok) {
+ // Group sessions by client pubkey and collect peers
+ const sessionMap = new Map()
+
+ for (const message of result.messages) {
+ if (!message.res?.items) continue
+
+ for (const item of message.res.items) {
+ if (item.client === pubkey) {
+ continue
+ }
+
+ const existing = sessionMap.get(item.client)
+
+ if (existing) {
+ existing.peers.push(message.url)
+ } else {
+ sessionMap.set(item.client, {...item, peers: [message.url]})
+ }
+ }
+ }
+
+ return Array.from(sessionMap.values())
+ }
+ }
+
+ return []
+}
+
+export const deleteOldPomadeSessions = async () => {
+ const $session = get(session)
+
+ if (isPomadeSession($session)) {
+ const client = new Client($session.clientOptions)
+
+ for (const item of await loadOtherPomadeSessions()) {
+ if (item.deactivated_at) {
+ await client.deleteSession(item.client, item.peers)
+ }
+ }
+ }
+}
diff --git a/src/app/util/logout.ts b/src/app/util/logout.ts
new file mode 100644
index 00000000..b3b25fe6
--- /dev/null
+++ b/src/app/util/logout.ts
@@ -0,0 +1,25 @@
+import {get} from "svelte/store"
+import {Client} from "@pomade/core"
+import {getPubkey} from "@welshman/util"
+import {session, isPomadeSession} from "@welshman/app"
+import {kv, db} from "@app/core/storage"
+import {Push} from "@app/util/notifications"
+
+export const logout = async () => {
+ const $session = get(session)
+
+ if ($session && isPomadeSession($session)) {
+ await new Client($session.clientOptions).deactivateSession(
+ getPubkey($session.clientOptions.secret),
+ $session.clientOptions.peers,
+ )
+ }
+
+ await Push.disable()
+ await kv.clear()
+ await db.clear()
+
+ localStorage.clear()
+
+ window.location.href = "/"
+}