152 lines
5.2 KiB
Vue
152 lines
5.2 KiB
Vue
<script setup lang="ts">
|
|
import { activeNote, updateNote, notes, activeNotesSource, getNotes } from '@/composables/useNotes'
|
|
import { viewModes, activeViewMode } from '@/composables/useViewMode'
|
|
import {
|
|
getClientKey,
|
|
getEncryptionKey,
|
|
encryptionKey,
|
|
setClientKey,
|
|
passphraseRequired
|
|
} from '@/composables/useEncryption'
|
|
import { initializeSettings } from '@/composables/useSettings'
|
|
import { windowIsMobile } from '@/utils/helpers'
|
|
import SideBar from '@/components/SideBar.vue'
|
|
import { useWindowSize } from '@vueuse/core'
|
|
import { SplashScreen } from '@capacitor/splash-screen'
|
|
|
|
initializeSettings()
|
|
|
|
onMounted(() => SplashScreen.hide())
|
|
|
|
const sideBarCollapsed = ref<boolean>(windowIsMobile())
|
|
|
|
const { width } = useWindowSize()
|
|
watch(width, () => (sideBarCollapsed.value = windowIsMobile()))
|
|
|
|
// const Note = defineAsyncComponent(() => import('@/components/ViewModes/Note.vue'))
|
|
// const ListView = defineAsyncComponent(() => import('@/components/ViewModes/ListView.vue'))
|
|
// const Mindmap = defineAsyncComponent(() => import('@/components/ViewModes/Mindmap.vue'))
|
|
|
|
// const firebaseAuthUI =
|
|
// firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(firebase.auth())
|
|
// provide('firebaseAuthUI', firebaseAuthUI)
|
|
|
|
watch(
|
|
[activeNotesSource, encryptionKey],
|
|
() => {
|
|
if (activeNotesSource.value === 'firebase') {
|
|
getClientKey()
|
|
getEncryptionKey()
|
|
}
|
|
getNotes()
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
const passphrase = ref('')
|
|
const passphraseValid = ref<boolean>()
|
|
|
|
const submitPassphrase = (close: () => void) => {
|
|
const setClientKeyResult = setClientKey(passphrase.value)
|
|
passphraseValid.value = setClientKeyResult
|
|
if (passphraseValid.value) close()
|
|
}
|
|
|
|
const loading = computed(
|
|
() => notes.value.length === 0 || passphraseRequired.value || !activeNotesSource.value
|
|
)
|
|
provide('loading', loading)
|
|
|
|
const topBarHeight = 52
|
|
const topBarHeightWithSafeArea = computed(() => `calc(${topBarHeight}px + var(--safe-area-top))`)
|
|
</script>
|
|
|
|
<template>
|
|
<TopBar
|
|
:side-bar-collapsed="sideBarCollapsed"
|
|
:height="topBarHeight"
|
|
:style="{ height: topBarHeightWithSafeArea }"
|
|
@toggle-side-bar="sideBarCollapsed = !sideBarCollapsed"
|
|
class="pe-[var(--safe-area-right)] ps-[var(--safe-area-left)]"
|
|
/>
|
|
<!-- <div class="absolute bottom-0 left-0 right-0 top-[50px] mx-auto flex flex-grow"> -->
|
|
<div
|
|
class="mx-auto flex w-full max-w-app flex-grow pe-[var(--safe-area-right)] ps-[var(--safe-area-left)]"
|
|
>
|
|
<Transition name="sidebar">
|
|
<SideBar
|
|
:view-modes="viewModes"
|
|
:active-view-mode="activeViewMode"
|
|
@set-view-mode="(viewMode) => (activeViewMode = viewMode)"
|
|
@collapse="(collapse) => (sideBarCollapsed = collapse)"
|
|
class="bg-gray-100 px-3 py-6 transition-[width] delay-200 duration-0 max-sm:z-50 max-sm:border-x-[1px] max-sm:py-3 max-sm:transition-transform max-sm:delay-0 max-sm:duration-200"
|
|
:style="{ 'margin-top': topBarHeightWithSafeArea }"
|
|
v-if="!sideBarCollapsed"
|
|
/>
|
|
</Transition>
|
|
<Transition name="overlay">
|
|
<div
|
|
class="absolute bottom-0 left-0 right-0 top-0 z-40 cursor-pointer bg-neutral-800 bg-opacity-60 transition-opacity duration-200 sm:hidden"
|
|
@click="sideBarCollapsed = true"
|
|
v-if="!sideBarCollapsed"
|
|
/>
|
|
</Transition>
|
|
<main
|
|
class="transition[margin-left] z-10 mx-auto flex h-full w-full max-w-app flex-col overflow-y-auto border-x-[1px] bg-white pb-[var(--safe-area-bottom)] duration-200 ease-out"
|
|
:class="sideBarCollapsed ? 'ml-0' : 'sm:ml-sidebar'"
|
|
>
|
|
<div class="flex flex-grow px-10 py-6 max-sm:px-4 max-sm:py-3">
|
|
<template v-if="!loading">
|
|
<Note
|
|
v-if="activeViewMode.name === 'Note' && activeNote"
|
|
:key="activeNote.id"
|
|
:note="activeNote"
|
|
class=""
|
|
@update="(note) => updateNote(note.id, note)"
|
|
/>
|
|
<ListView v-else-if="activeViewMode.name === 'List'" />
|
|
<Mindmap v-else-if="activeViewMode.name === 'Mindmap'" />
|
|
</template>
|
|
<SkeletonNote v-else />
|
|
</div>
|
|
</main>
|
|
</div>
|
|
<UIModal :open="passphraseRequired" :persistent="true">
|
|
<template #title>Enter your passphrase</template>
|
|
<template #default="{ close }">
|
|
<div>
|
|
Your notes are encrypted. Please enter your encryption key passphrase to decrypt your cloud
|
|
notes.
|
|
</div>
|
|
<form @submit.prevent="submitPassphrase(close)">
|
|
<UIInputText
|
|
type="password"
|
|
class="w-full !max-w-full"
|
|
:color="passphraseValid === false ? 'error' : 'regular'"
|
|
v-model="passphrase"
|
|
></UIInputText>
|
|
</form>
|
|
<UIAlert color="error" class="mt-4" v-if="passphraseValid === false">
|
|
<i class="fa-solid fa-triangle-exclamation"></i>
|
|
The passphrase you entered is incorrect.
|
|
</UIAlert>
|
|
</template>
|
|
<template #actions="{ close }">
|
|
<UIButton color="primary" size="sm" @click="submitPassphrase(close)">Submit</UIButton>
|
|
</template>
|
|
</UIModal>
|
|
</template>
|
|
<style scoped>
|
|
.sidebar-enter-from,
|
|
.sidebar-leave-to {
|
|
@apply max-sm:-translate-x-full;
|
|
}
|
|
.overlay-enter-from,
|
|
.overlay-leave-to {
|
|
@apply opacity-0;
|
|
}
|
|
main {
|
|
contain: size layout style;
|
|
}
|
|
</style>
|