fix: Google Font

feat: add a todo view
This commit is contained in:
Julien Calixte
2026-01-19 00:36:29 +01:00
parent b6554282f7
commit 3e417ca271
10 changed files with 162 additions and 110 deletions

View File

@@ -9,7 +9,6 @@ import {
watch,
} from "vue"
import LiteLoading from "@/components/LiteLoading.vue"
import StackedNote from "@/components/StackedNote.vue"
import { useLinks } from "@/hooks/useLinks.hook"
import { useMarkdown } from "@/hooks/useMarkdown.hook"
@@ -19,7 +18,6 @@ import { useVisitRepo } from "@/modules/history/hooks/useVisitRepo.hook"
import CacheAllNotes from "@/modules/note/components/CacheAllNote.vue"
import { useUserRepoStore } from "@/modules/repo/store/userRepo.store"
import { useUserSettings } from "@/modules/user/hooks/useUserSettings.hook"
import { useRoute } from "vue-router"
import SkeletonLoader from "@/components/SkeletonLoader.vue"
const HeaderNote = defineAsyncComponent(
@@ -70,8 +68,6 @@ const hasContent = computed(() => !!renderedContent.value)
watch(
renderedContent,
async () => {
console.log(renderedContent.value)
await nextTick()
listenToClick()
},

View File

@@ -107,6 +107,28 @@ defineProps<{ user: string; repo: string }>()
<line x1="9" y1="15" x2="13" y2="15" />
</svg>
</router-link>
<router-link :to="{ name: 'TodoNotes', params: { user, repo } }">
<svg
xmlns="http://www.w3.org/2000/svg"
width="36"
height="36"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
class="icon icon-tabler icons-tabler-outline icon-tabler-list-check"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M3.5 5.5l1.5 1.5l2.5 -2.5" />
<path d="M3.5 11.5l1.5 1.5l2.5 -2.5" />
<path d="M3.5 17.5l1.5 1.5l2.5 -2.5" />
<path d="M11 6l9 0" />
<path d="M11 12l9 0" />
<path d="M11 18l9 0" />
</svg>
</router-link>
<router-link :to="{ name: 'FleetingNotes', params: { user, repo } }">
<svg
xmlns="http://www.w3.org/2000/svg"

View File

@@ -1,33 +1,34 @@
import { computed, Ref, ref, toValue } from 'vue'
import { computed, Ref, ref, toValue } from "vue"
import { useMarkdown } from '@/hooks/useMarkdown.hook'
import { prepareNoteCache } from '@/modules/note/cache/prepareNoteCache'
import { queryFileContent } from '@/modules/repo/services/repo'
import { useUserRepoStore } from '@/modules/repo/store/userRepo.store'
import { useMarkdown } from "@/hooks/useMarkdown.hook"
import { prepareNoteCache } from "@/modules/note/cache/prepareNoteCache"
import { queryFileContent } from "@/modules/repo/services/repo"
import { useUserRepoStore } from "@/modules/repo/store/userRepo.store"
export const useFile = (sha: Ref<string> | string, retrieveContent = true) => {
const store = useUserRepoStore()
const shaValue = toValue(sha)
const path = computed(() => {
const file = store.files.find((file) => file.sha === toValue(sha))
const file = store.files.find((file) => file.sha === shaValue)
return file?.path
})
const {
render,
renderFromUTF8,
getRawContent: getRawContentFromFile
} = useMarkdown(toValue(sha))
getRawContent: getRawContentFromFile,
} = useMarkdown(shaValue)
const { getCachedNote, saveCacheNote } = prepareNoteCache(
toValue(sha),
toValue(path)
shaValue,
toValue(path),
)
const fromCache = ref(false)
const rawContent = ref('')
const rawContent = ref("")
const content = computed(() =>
rawContent.value ? renderFromUTF8(rawContent.value) : ''
rawContent.value ? renderFromUTF8(rawContent.value) : "",
)
const getEditedSha = async () => {
@@ -46,26 +47,22 @@ export const useFile = (sha: Ref<string> | string, retrieveContent = true) => {
fromCache.value = !!cachedNote
if (cachedNote) {
if (from === 'path') {
queryFileContent(store.user, store.repo, toValue(sha)).then(
if (from === "path") {
queryFileContent(store.user, store.repo, shaValue).then(
(fileContent) => {
if (!fileContent) {
return
}
saveCacheNote(fileContent)
rawContent.value = getRawContentFromFile(fileContent)
}
},
)
}
return cachedNote.content
}
const fileContent = await queryFileContent(
store.user,
store.repo,
toValue(sha)
)
const fileContent = await queryFileContent(store.user, store.repo, shaValue)
if (!fileContent) {
return null
@@ -114,6 +111,6 @@ export const useFile = (sha: Ref<string> | string, retrieveContent = true) => {
getCachedFileContent,
getEditedSha,
fromCache,
saveCacheNote
saveCacheNote,
}
}

View File

@@ -1,6 +1,5 @@
import { computed } from 'vue'
import { useUserRepoStore } from '@/modules/repo/store/userRepo.store'
import { computed } from "vue"
import { useUserRepoStore } from "@/modules/repo/store/userRepo.store"
export const useFolderNotes = (folders: string[]) => {
const store = useUserRepoStore()
@@ -9,25 +8,25 @@ export const useFolderNotes = (folders: string[]) => {
store.files.filter(
(file) =>
folders.some((folder) => file.path?.startsWith(folder)) &&
file.path?.endsWith('.md')
)
file.path?.endsWith(".md"),
),
)
const content = computed(() =>
filteredNotes.value?.length > 0
? filteredNotes.value
.map((note) => {
const firstFolder = note.path?.split('/').shift()
const firstFolder = note.path?.split("/").shift()
return `- [${note.path?.replace(`${firstFolder}/`, '')}](${
return `- [${note.path?.replace(`${firstFolder}/`, "")}](${
note.path
})`
})
.join('\n')
: ''
.join("\n")
: "",
)
return {
content
content,
}
}

View File

@@ -1,15 +1,14 @@
import { computed } from 'vue'
import { useUserRepoStore } from '@/modules/repo/store/userRepo.store'
import { computed } from "vue"
import { useUserRepoStore } from "@/modules/repo/store/userRepo.store"
export const useNotes = () => {
const store = useUserRepoStore()
const notes = computed(() =>
store.files.filter((file) => file.path?.endsWith('.md'))
store.files.filter((file) => file.path?.endsWith(".md")),
)
return {
notes
notes,
}
}

View File

@@ -1,73 +1,79 @@
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"
import Home from '@/views/HomeApp.vue'
import Home from "@/views/HomeApp.vue"
const routes: Array<RouteRecordRaw> = [
{
path: '/repo-list',
name: 'RepoList',
component: () => import('@/views/RepoList.vue')
path: "/repo-list",
name: "RepoList",
component: () => import("@/views/RepoList.vue"),
},
{
path: '/:user/:repo',
name: 'FluxNoteView',
path: "/:user/:repo",
name: "FluxNoteView",
props: true,
component: () => import('@/views/FluxNoteView.vue')
component: () => import("@/views/FluxNoteView.vue"),
},
{
path: '/:user/:repo/share/:note',
name: 'ShareNotes',
path: "/:user/:repo/share/:note",
name: "ShareNotes",
props: true,
component: () => import('@/views/ShareNotes.vue')
component: () => import("@/views/ShareNotes.vue"),
},
{
path: '/:user/:repo/inbox',
name: 'FleetingNotes',
path: "/:user/:repo/inbox",
name: "FleetingNotes",
props: true,
component: () => import('@/views/FleetingNotes.vue')
component: () => import("@/views/FleetingNotes.vue"),
},
{
path: '/:user/:repo/draft',
name: 'DraftNotes',
path: "/:user/:repo/draft",
name: "DraftNotes",
props: true,
component: () => import('@/views/DraftNotes.vue')
component: () => import("@/views/DraftNotes.vue"),
},
{
path: '/:user/:repo/history',
name: 'HistoricNotes',
path: "/:user/:repo/todo",
name: "TodoNotes",
props: true,
component: () => import('@/views/HistoricNotes.vue')
component: () => import("@/views/TodoNotes.vue"),
},
{
path: '/:user/:repo/spaced-repetition',
name: 'SpacedRepetitionCard',
path: "/:user/:repo/history",
name: "HistoricNotes",
props: true,
component: () => import('@/views/SpacedRepetitionCard.vue')
component: () => import("@/views/HistoricNotes.vue"),
},
{
path: '/:user/:repo/need-review-cards',
name: 'NeedReviewCards',
path: "/:user/:repo/spaced-repetition",
name: "SpacedRepetitionCard",
props: true,
component: () => import('@/views/NeedReviewCards.vue')
component: () => import("@/views/SpacedRepetitionCard.vue"),
},
{
path: '/about',
name: 'About',
component: () => import('@/views/AboutApp.vue')
path: "/:user/:repo/need-review-cards",
name: "NeedReviewCards",
props: true,
component: () => import("@/views/NeedReviewCards.vue"),
},
{
path: '/',
name: 'Home',
component: Home
path: "/about",
name: "About",
component: () => import("@/views/AboutApp.vue"),
},
{
path: '/:catchAll(.*)',
name: 'SpaceCowboy',
component: () => import('@/views/SpaceCowboy.vue')
}
path: "/",
name: "Home",
component: Home,
},
{
path: "/:catchAll(.*)",
name: "SpaceCowboy",
component: () => import("@/views/SpaceCowboy.vue"),
},
]
export const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
routes,
})

View File

@@ -1,10 +1,9 @@
import FontFaceObserver from "fontfaceobserver"
const assembleFontLink = (font: string) => {
return `https://fonts.googleapis.com/css2?display=swap&family=${font.replaceAll(
" ",
"+",
)}`
return `https://fonts.googleapis.com/css2?display=swap&family=${font
.replaceAll(",", "&family=")
.replaceAll(" ", "+")}`
}
export const downloadGoogleFont = async (font: string): Promise<void> => {

View File

@@ -1,3 +1,17 @@
<script setup lang="ts">
import { computed, defineAsyncComponent } from "vue"
import { useFolderNotes } from "@/modules/note/hooks/useFolderNotes"
const FluxNote = defineAsyncComponent(() => import("@/components/FluxNote.vue"))
const props = defineProps<{ user: string; repo: string }>()
const user = computed(() => props.user)
const repo = computed(() => props.repo)
const DRAFT_FOLDER = ["drafts", "_drafts"]
const { content } = useFolderNotes(DRAFT_FOLDER)
</script>
<template>
<div class="draft-notes">
<flux-note key="draft-notes" :user="user" :repo="repo" :content="content">
@@ -6,34 +20,6 @@
</div>
</template>
<script lang="ts">
import { defineAsyncComponent, defineComponent } from 'vue'
import { useFolderNotes } from '@/modules/note/hooks/useFolderNotes'
const FluxNote = defineAsyncComponent(() => import('@/components/FluxNote.vue'))
const DRAFT_FOLDER = ['drafts', '_drafts']
export default defineComponent({
name: 'DraftNotes',
components: {
FluxNote
},
props: {
user: { type: String, required: true },
repo: { type: String, required: true }
},
setup() {
const { content } = useFolderNotes(DRAFT_FOLDER)
return {
content
}
}
})
</script>
<style scoped lang="scss">
.draft-notes {
display: flex;

48
src/views/TodoNotes.vue Normal file
View File

@@ -0,0 +1,48 @@
<script setup lang="ts">
import { computed, defineAsyncComponent, watch } from "vue"
import { useUserRepoStore } from "@/modules/repo/store/userRepo.store"
import { useFile } from "@/hooks/useFile.hook"
import { computedAsync } from "@vueuse/core"
const FluxNote = defineAsyncComponent(() => import("@/components/FluxNote.vue"))
const props = defineProps<{ user: string; repo: string }>()
const user = computed(() => props.user)
const repo = computed(() => props.repo)
const store = useUserRepoStore()
const todoNote = computed(() =>
store.files.find((file) => file.path?.endsWith("_todo/todo.md")),
)
const content = computedAsync(() => {
if (!todoNote.value) {
return ""
}
const { getContent } = useFile(todoNote.value?.sha ?? "", false)
return getContent()
})
</script>
<template>
<div class="todo-notes">
<flux-note
key="todo-notes"
:user="user"
:repo="repo"
:content="content"
:parse-content="false"
/>
</div>
</template>
<style lang="scss">
.todo-notes {
flex: 1;
input[type="checkbox"] {
margin-right: 0.5rem;
}
}
</style>