- Added several new dependencies related to the Applesauce library, including 'applesauce-accounts', 'applesauce-common', 'applesauce-core', 'applesauce-loaders', 'applesauce-relay', and 'applesauce-signers', all at version 5.1.0. - Updated the development script in package.json to specify a port for Vite and added new seed scripts for profiles and activity. - Removed outdated image files from the public directory to clean up unused assets. - Enhanced the App.vue structure by integrating shared components like AppHeader and AuthModal for improved user experience. - Refactored ContentDetailModal and MobileNav components to support new features and improve usability. These changes improve the overall functionality and maintainability of the application while ensuring it utilizes the latest libraries for better performance.
152 lines
4.1 KiB
TypeScript
152 lines
4.1 KiB
TypeScript
import { ref, computed, onUnmounted } from 'vue'
|
|
import { Accounts } from 'applesauce-accounts'
|
|
import { accountManager } from '../lib/accounts'
|
|
import { TEST_PERSONAS, TASTEMAKER_PERSONAS } from '../data/testPersonas'
|
|
import type { Subscription } from 'rxjs'
|
|
|
|
type Persona = { name: string; nsec: string; pubkey: string }
|
|
|
|
/**
|
|
* Vue composable for Nostr account management.
|
|
* Wraps applesauce AccountManager observables as Vue reactive refs.
|
|
* Provides login methods for Extension, test personas, and private keys.
|
|
*/
|
|
export function useAccounts() {
|
|
const activeAccount = ref<any>(null)
|
|
const allAccounts = ref<any[]>([])
|
|
const isLoggingIn = ref(false)
|
|
const loginError = ref<string | null>(null)
|
|
|
|
const subscriptions: Subscription[] = []
|
|
|
|
// Subscribe to active account changes
|
|
const activeSub = accountManager.active$.subscribe((account) => {
|
|
activeAccount.value = account ?? null
|
|
})
|
|
subscriptions.push(activeSub)
|
|
|
|
// Subscribe to all accounts changes
|
|
const accountsSub = accountManager.accounts$.subscribe((accounts) => {
|
|
allAccounts.value = [...accounts]
|
|
})
|
|
subscriptions.push(accountsSub)
|
|
|
|
const isLoggedIn = computed(() => activeAccount.value !== null)
|
|
const activePubkey = computed(() => activeAccount.value?.pubkey ?? null)
|
|
|
|
const activeName = computed(() => {
|
|
if (!activeAccount.value) return null
|
|
// Check test personas for name
|
|
const allPersonas: Persona[] = [
|
|
...(TEST_PERSONAS as unknown as Persona[]),
|
|
...(TASTEMAKER_PERSONAS as unknown as Persona[]),
|
|
]
|
|
const match = allPersonas.find(
|
|
(p) => p.pubkey === activeAccount.value?.pubkey,
|
|
)
|
|
return match?.name ?? activeAccount.value?.pubkey?.slice(0, 8) ?? 'Unknown'
|
|
})
|
|
|
|
/**
|
|
* Login with a browser extension (NIP-07)
|
|
*/
|
|
async function loginWithExtension() {
|
|
isLoggingIn.value = true
|
|
loginError.value = null
|
|
try {
|
|
const account = await Accounts.ExtensionAccount.fromExtension()
|
|
accountManager.addAccount(account)
|
|
accountManager.setActive(account)
|
|
} catch (err: any) {
|
|
loginError.value = err.message || 'Extension login failed'
|
|
console.error('Extension login error:', err)
|
|
} finally {
|
|
isLoggingIn.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Login with a test persona (for development)
|
|
*/
|
|
async function loginWithPersona(persona: Persona) {
|
|
isLoggingIn.value = true
|
|
loginError.value = null
|
|
try {
|
|
const account = Accounts.PrivateKeyAccount.fromKey(persona.nsec)
|
|
accountManager.addAccount(account)
|
|
accountManager.setActive(account)
|
|
} catch (err: any) {
|
|
loginError.value = err.message || 'Persona login failed'
|
|
console.error('Persona login error:', err)
|
|
} finally {
|
|
isLoggingIn.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Login with a private key (nsec)
|
|
*/
|
|
async function loginWithPrivateKey(nsec: string) {
|
|
isLoggingIn.value = true
|
|
loginError.value = null
|
|
try {
|
|
const account = Accounts.PrivateKeyAccount.fromKey(nsec)
|
|
accountManager.addAccount(account)
|
|
accountManager.setActive(account)
|
|
} catch (err: any) {
|
|
loginError.value = err.message || 'Private key login failed'
|
|
console.error('Private key login error:', err)
|
|
} finally {
|
|
isLoggingIn.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Logout current account
|
|
*/
|
|
function logout() {
|
|
const current = accountManager.active
|
|
if (current) {
|
|
accountManager.removeAccount(current)
|
|
}
|
|
accountManager.setActive(null as any)
|
|
}
|
|
|
|
/**
|
|
* Get all available test personas
|
|
*/
|
|
const testPersonas = computed(() => [
|
|
...(TEST_PERSONAS as unknown as Persona[]),
|
|
])
|
|
|
|
const tastemakerPersonas = computed(() => [
|
|
...(TASTEMAKER_PERSONAS as unknown as Persona[]),
|
|
])
|
|
|
|
// Cleanup on unmount
|
|
onUnmounted(() => {
|
|
subscriptions.forEach((sub) => sub.unsubscribe())
|
|
})
|
|
|
|
return {
|
|
// State
|
|
activeAccount,
|
|
allAccounts,
|
|
isLoggedIn,
|
|
isLoggingIn,
|
|
loginError,
|
|
activePubkey,
|
|
activeName,
|
|
|
|
// Login methods
|
|
loginWithExtension,
|
|
loginWithPersona,
|
|
loginWithPrivateKey,
|
|
logout,
|
|
|
|
// Personas for dev UI
|
|
testPersonas,
|
|
tastemakerPersonas,
|
|
}
|
|
}
|