Skip to content

Commit

Permalink
feat: improve note view
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Feb 3, 2023
1 parent 72a7304 commit 94e5d58
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 32 deletions.
5 changes: 5 additions & 0 deletions packages/client/constants.ts
Expand Up @@ -19,3 +19,8 @@ export const CLASS_VCLICK_GONE = 'slidev-vclick-gone'
export const CLASS_VCLICK_HIDDEN_EXP = 'slidev-vclick-hidden-explicitly'
export const CLASS_VCLICK_CURRENT = 'slidev-vclick-current'
export const CLASS_VCLICK_PRIOR = 'slidev-vclick-prior'

export const TRUST_ORIGINS = [
'localhost',
'127.0.0.1',
]
Expand Up @@ -3,6 +3,7 @@ const props = defineProps<{
class?: string
noteHtml?: string
note?: string
placeholder?: string
}>()
defineEmits(['click'])
Expand All @@ -17,10 +18,19 @@ defineEmits(['click'])
v-html="noteHtml"
/>
<div
v-else
v-else-if="note"
class="prose overflow-auto outline-none"
:class="props.class"
@click="$emit('click')"
v-text="note"
/>
>
<p v-text="note" />
</div>
<div
v-else
class="prose overflow-auto outline-none opacity-50 italic"
:class="props.class"
@click="$emit('click')"
>
<p v-text="props.placeholder || 'No notes.'" />
</div>
</template>
4 changes: 2 additions & 2 deletions packages/client/internals/NoteEditor.vue
Expand Up @@ -3,7 +3,7 @@ import { ignorableWatch, onClickOutside } from '@vueuse/core'
import { nextTick, ref, watch } from 'vue'
import { currentSlideId } from '../logic/nav'
import { useDynamicSlideInfo } from '../logic/note'
import NoteViewer from './NoteViewer.vue'
import NoteDisplay from './NoteDisplay.vue'
const props = defineProps({
class: {
Expand Down Expand Up @@ -60,7 +60,7 @@ onClickOutside(input, () => {
</script>

<template>
<NoteViewer
<NoteDisplay
v-if="!editing && note"
:class="props.class"
:note="note"
Expand Down
4 changes: 2 additions & 2 deletions packages/client/internals/NoteStatic.vue
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed } from 'vue'
import { currentRoute } from '../logic/nav'
import NoteViewer from './NoteViewer.vue'
import NoteDisplay from './NoteDisplay.vue'
const props = defineProps<{
class?: string
Expand All @@ -12,7 +12,7 @@ const noteHtml = computed(() => currentRoute.value?.meta?.slide?.noteHTML)
</script>

<template>
<NoteViewer
<NoteDisplay
:class="props.class"
:note="note"
:note-html="noteHtml"
Expand Down
50 changes: 29 additions & 21 deletions packages/client/internals/NotesView.vue
Expand Up @@ -4,20 +4,22 @@ import { computed } from 'vue'
import { useLocalStorage } from '@vueuse/core'
import { configs } from '../env'
import { sharedState } from '../state/shared'
import { fullscreen } from '../state'
import { total } from '../logic/nav'
import { rawRoutes } from '../routes'
import NoteViewer from './NoteViewer.vue'
import NoteDisplay from './NoteDisplay.vue'
const slideTitle = configs.titleTemplate.replace('%s', configs.title || 'Slidev')
useHead({
title: `Notes - ${slideTitle}`,
})
const { isFullscreen, toggle: toggleFullscreen } = fullscreen
const fontSize = useLocalStorage('slidev-notes-font-size', 18)
const pageNo = computed(() => sharedState.lastUpdate?.type === 'viewer' ? sharedState.viewerPage : sharedState.page)
const route = computed(() => rawRoutes.find(i => i.path === `${pageNo.value}`))
const note = computed(() => route.value?.meta?.slide?.note)
const noteHtml = computed(() => route.value?.meta?.slide?.noteHTML)
const currentRoute = computed(() => rawRoutes.find(i => i.path === `${pageNo.value}`))
const nextRoute = computed(() => rawRoutes.find(i => i.path === `${pageNo.value + 1}`))
function increaseFontSize() {
fontSize.value = fontSize.value + 1
Expand All @@ -38,29 +40,35 @@ function decreaseFontSize() {
class="px-5 flex-auto h-full overflow-auto"
:style="{ fontSize: `${fontSize}px` }"
>
<NoteViewer
v-if="note"
:note="note"
:note-html="noteHtml"
<NoteDisplay
:note="currentRoute?.meta?.slide?.note"
:note-html="currentRoute?.meta?.slide?.noteHTML"
:placeholder="`No notes for Slide ${pageNo}.`"
/>
</div>
<div v-if="nextRoute" class="px-5 py-4 max-h-40 overflow-auto border-t border-gray-400 border-opacity-20">
<NoteDisplay
:note="nextRoute?.meta?.slide?.note"
:note-html="nextRoute?.meta?.slide?.noteHTML"
placeholder="No notes for next slide."
/>
<div v-else class="prose overflow-auto outline-none opacity-50">
<p>
No notes for Slide {{ pageNo }}.
</p>
</div>
</div>
<div class="flex-none">
<div class="flex gap-1 justify-center items-center">
<div class="flex-none border-t border-gray-400 border-opacity-20">
<div class="flex gap-1 items-center px-6 py-3">
<button class="icon-btn" @click="toggleFullscreen">
<carbon:minimize v-if="isFullscreen" />
<carbon:maximize v-else />
</button>
<button class="icon-btn" @click="increaseFontSize">
<carbon:add />
<carbon:zoom-in />
</button>
Font Size
<button class="icon-btn" @click="decreaseFontSize">
<carbon:subtract />
<carbon:zoom-out />
</button>
</div>
<div class="p2 text-center">
{{ pageNo }} / {{ total }}
<div class="flex-auto" />
<div class="p2 text-center">
{{ pageNo }} / {{ total }}
</div>
</div>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions packages/client/internals/PresenterPrint.vue
Expand Up @@ -4,7 +4,7 @@ import { useStyleTag } from '@vueuse/core'
import { useHead } from '@vueuse/head'
import { configs, themeVars } from '../env'
import { rawRoutes, total } from '../logic/nav'
import NoteViewer from './NoteViewer.vue'
import NoteDisplay from './NoteDisplay.vue'
useStyleTag(`
@page {
Expand Down Expand Up @@ -55,7 +55,7 @@ const slidesWithNote = computed(() => rawRoutes
<div class="flex-auto" />
</div>
</h2>
<NoteViewer :note-html="slide!.noteHTML" class="max-w-full" />
<NoteDisplay :note-html="slide!.noteHTML" class="max-w-full" />
</div>
<hr v-if="index < slidesWithNote.length - 1" class="border-gray-400/50 mb-8">
</div>
Expand Down
1 change: 1 addition & 0 deletions packages/client/logic/nav.ts
Expand Up @@ -26,6 +26,7 @@ export const isPrintMode = computed(() => route.value.query.print !== undefined)
export const isPrintWithClicks = computed(() => route.value.query.print === 'clicks')
export const isEmbedded = computed(() => route.value.query.embedded !== undefined)
export const isPresenter = computed(() => route.value.path.startsWith('/presenter'))
export const isNotesViewer = computed(() => route.value.path.startsWith('/notes'))
export const isClicksDisabled = computed(() => isPrintMode.value && !isPrintWithClicks.value)
export const presenterPassword = computed(() => route.value.query.password)
export const showPresenter = computed(() => !isPresenter.value && (!configs.remote || presenterPassword.value === configs.remote))
Expand Down
2 changes: 2 additions & 0 deletions packages/client/routes.ts
@@ -1,5 +1,6 @@
import type { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
import type { TransitionGroupProps } from 'vue'
import Play from './internals/Play.vue'
import Print from './internals/Print.vue'
// @ts-expect-error missing types
Expand Down Expand Up @@ -78,6 +79,7 @@ declare module 'vue-router' {
title?: string
level?: number
}
transition?: string | TransitionGroupProps | undefined
// private fields
__clicksElements: HTMLElement[]
__preloaded?: boolean
Expand Down
12 changes: 10 additions & 2 deletions packages/client/setup/root.ts
Expand Up @@ -5,8 +5,9 @@ import { nanoid } from 'nanoid'
import { configs } from '../env'
import { initSharedState, onPatch, patch } from '../state/shared'
import { initDrawingState } from '../state/drawings'
import { clicks, currentPage, getPath, isPresenter } from '../logic/nav'
import { clicks, currentPage, getPath, isNotesViewer, isPresenter } from '../logic/nav'
import { router } from '../routes'
import { TRUST_ORIGINS } from '../constants'

export default function setupRoot() {
// @ts-expect-error injected in runtime
Expand All @@ -21,10 +22,17 @@ export default function setupRoot() {
initSharedState(`${title} - shared`)
initDrawingState(`${title} - drawings`)

const id = nanoid()
const id = `${location.origin}_${nanoid()}`

// update shared state
function updateSharedState() {
if (isNotesViewer.value)
return

// we allow Presenter mode, or Viewer mode from trusted origins to update the shared state
if (!isPresenter.value && !TRUST_ORIGINS.includes(location.host.split(':')[0]))
return

if (isPresenter.value) {
patch('page', +currentPage.value)
patch('clicks', clicks.value)
Expand Down

0 comments on commit 94e5d58

Please sign in to comment.