Files
archy/packages/app/src/App.vue
T

60 lines
1.5 KiB
Vue
Raw Normal View History

<template>
<div class="h-dvh flex flex-col" :class="currentTheme">
<RouterView />
<ArticleOverlay />
<PassphraseDialog
:visible="showPassphrase"
:is-creating="isCreatingPassphrase"
@submit="handlePassphraseSubmit"
@skip="showPassphrase = false"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { RouterView } from 'vue-router'
import { useTheme } from '@/composables/useTheme'
import ArticleOverlay from '@/components/content/ArticleOverlay.vue'
import PassphraseDialog from '@/components/ui/PassphraseDialog.vue'
import {
isCryptoEnabled,
deriveKey,
generateSalt,
setSessionKey,
} from '@/utils/crypto'
const { currentTheme, initTheme } = useTheme()
const showPassphrase = ref(false)
const isCreatingPassphrase = ref(false)
const SALT_KEY = 'aiui-crypto-salt'
async function handlePassphraseSubmit(passphrase: string) {
let saltHex = localStorage.getItem(SALT_KEY)
let salt: Uint8Array
if (saltHex) {
salt = new Uint8Array(saltHex.match(/.{2}/g)!.map(b => parseInt(b, 16)))
} else {
salt = await generateSalt()
saltHex = Array.from(salt).map(b => b.toString(16).padStart(2, '0')).join('')
localStorage.setItem(SALT_KEY, saltHex)
}
const key = await deriveKey(passphrase, salt)
setSessionKey(key, salt)
showPassphrase.value = false
}
onMounted(() => {
initTheme()
if (isCryptoEnabled()) {
const hasSalt = !!localStorage.getItem(SALT_KEY)
isCreatingPassphrase.value = !hasSalt
showPassphrase.value = true
}
})
</script>