Remove v-if prop anti-pattern, clean up, add reader mode
This commit is contained in:
parent
3853e8fa20
commit
9386c1d158
|
@ -1 +1 @@
|
|||
[{"D:\\Software\\Development\\Websites\\enderman.ch\\index\\assets\\styles\\transitions.scss":"1","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\TransitionY.vue":"2","D:\\Software\\Development\\Websites\\enderman.ch\\index\\app.vue":"3","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\EMail.vue":"4","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\about.vue":"5","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\index.vue":"6","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\projects.vue":"7","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\social.vue":"8","D:\\Software\\Development\\Websites\\enderman.ch\\index\\layouts\\Card.vue":"9","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\Options.vue":"10","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\Flooter.vue":"11","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\SwipeControls.vue":"12","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\Logo.vue":"13","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\Route.vue":"14","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\animations\\Portal.vue":"15","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\ui\\Icon.vue":"16","D:\\Software\\Development\\Websites\\enderman.ch\\index\\assets\\styles\\vuetify.scss":"17","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\[...slug].vue":"18","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\blog\\index.vue":"19","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\blog\\[slug].vue":"20"},{"size":165,"mtime":1700688268778,"hashOfConfig":"21"},{"size":1513,"mtime":1700430002840,"hashOfConfig":"21"},{"size":1550,"mtime":1700850776284,"hashOfConfig":"21"},{"size":804,"mtime":1700688952880,"hashOfConfig":"21"},{"size":2135,"mtime":1700689265787,"hashOfConfig":"21"},{"size":3117,"mtime":1700689271383,"hashOfConfig":"21"},{"size":2304,"mtime":1700689265769,"hashOfConfig":"21"},{"size":3232,"mtime":1700689265781,"hashOfConfig":"21"},{"size":1623,"mtime":1700748530633,"hashOfConfig":"21"},{"size":2187,"mtime":1706788559308,"hashOfConfig":"22"},{"size":2067,"mtime":1708180203174,"hashOfConfig":"22"},{"size":1236,"mtime":1706205683132,"hashOfConfig":"22"},{"size":1135,"mtime":1706030243608,"hashOfConfig":"22"},{"size":979,"mtime":1706003786966,"hashOfConfig":"22"},{"size":16968,"mtime":1708180277353,"hashOfConfig":"22"},{"size":935,"mtime":1706445231843,"hashOfConfig":"22"},{"size":120,"mtime":1706789613657,"hashOfConfig":"23"},{"size":1988,"mtime":1708191547889,"hashOfConfig":"22"},{"size":2560,"mtime":1708202402381,"hashOfConfig":"22"},{"size":983,"mtime":1708206997656,"hashOfConfig":"22"},"5tgxr3","1nljphs","1lk8nat"]
|
||||
[{"D:\\Software\\Development\\Websites\\enderman.ch\\index\\assets\\styles\\transitions.scss":"1","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\TransitionY.vue":"2","D:\\Software\\Development\\Websites\\enderman.ch\\index\\app.vue":"3","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\EMail.vue":"4","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\about.vue":"5","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\index.vue":"6","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\projects.vue":"7","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\social.vue":"8","D:\\Software\\Development\\Websites\\enderman.ch\\index\\layouts\\Card.vue":"9","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\Options.vue":"10","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\Flooter.vue":"11","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\SwipeControls.vue":"12","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\Logo.vue":"13","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\blocks\\Route.vue":"14","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\animations\\Portal.vue":"15","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\ui\\Icon.vue":"16","D:\\Software\\Development\\Websites\\enderman.ch\\index\\assets\\styles\\vuetify.scss":"17","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\[...slug].vue":"18","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\blog\\index.vue":"19","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\blog\\[slug].vue":"20"},{"size":165,"mtime":1700688268778,"hashOfConfig":"21"},{"size":1513,"mtime":1700430002840,"hashOfConfig":"21"},{"size":1550,"mtime":1700850776284,"hashOfConfig":"21"},{"size":804,"mtime":1700688952880,"hashOfConfig":"21"},{"size":2135,"mtime":1700689265787,"hashOfConfig":"21"},{"size":3117,"mtime":1700689271383,"hashOfConfig":"21"},{"size":2304,"mtime":1700689265769,"hashOfConfig":"21"},{"size":3232,"mtime":1700689265781,"hashOfConfig":"21"},{"size":1623,"mtime":1700748530633,"hashOfConfig":"21"},{"size":3065,"mtime":1708254606285,"hashOfConfig":"22"},{"size":1132,"mtime":1708254584095,"hashOfConfig":"22"},{"size":1269,"mtime":1708255068679,"hashOfConfig":"22"},{"size":1147,"mtime":1708248797872,"hashOfConfig":"22"},{"size":979,"mtime":1706003786966,"hashOfConfig":"22"},{"size":16968,"mtime":1708180277353,"hashOfConfig":"22"},{"size":935,"mtime":1706445231843,"hashOfConfig":"22"},{"size":120,"mtime":1706789613657,"hashOfConfig":"23"},{"size":1988,"mtime":1708191547889,"hashOfConfig":"22"},{"size":2560,"mtime":1708202402381,"hashOfConfig":"22"},{"size":983,"mtime":1708206997656,"hashOfConfig":"22"},"5tgxr3","1nljphs","1lk8nat"]
|
25
app.vue
25
app.vue
|
@ -1,6 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
const config = useAppConfig()
|
||||
const vdisp = ref(useVDisplay())
|
||||
const theme = useVThemeSSR()
|
||||
const { reader } = storeToRefs(usePageStore())
|
||||
|
||||
useHead({
|
||||
titleTemplate: (chunk?) => {
|
||||
|
@ -17,10 +19,11 @@ useHead({
|
|||
>
|
||||
<div
|
||||
id="ender-layout"
|
||||
class="d-flex flex-column align-items-center pt-sm-5 h-100"
|
||||
class="p-animated d-flex flex-column align-items-center h-100"
|
||||
:class="{ 'pt-sm-5': !reader }"
|
||||
>
|
||||
<AClientOnly appear render="xs" mode="out-in">
|
||||
<SwipeControls />
|
||||
<AClientOnly appear mode="out-in">
|
||||
<SwipeControls v-if="vdisp.xs" />
|
||||
</AClientOnly>
|
||||
|
||||
<NuxtLayout
|
||||
|
@ -30,30 +33,28 @@ useHead({
|
|||
<template #footer>
|
||||
<AClientOnly
|
||||
appear
|
||||
render="xs"
|
||||
mode="in-out"
|
||||
enter="animate__animated animate__delay-1s animate__fadeIn"
|
||||
leave="animate__animated animate__fadeOut"
|
||||
>
|
||||
<Flooter opaque />
|
||||
<Flooter v-if="vdisp.xs" opaque />
|
||||
</AClientOnly>
|
||||
</template>
|
||||
</NuxtLayout>
|
||||
</div>
|
||||
|
||||
<ClientOnly>
|
||||
<template #fallback> </template>
|
||||
<Portal layout="#ender-layout" animate randomize fade />
|
||||
</ClientOnly>
|
||||
|
||||
<AClientOnly
|
||||
appear
|
||||
render="sm-up"
|
||||
mode="out-in"
|
||||
enter="animate__animated animate__delay-1s animate__fadeInUpBig animate__slow"
|
||||
leave="animate__animated animate__fadeOutDown"
|
||||
>
|
||||
<Flooter class="floaty mb-2 px-2" />
|
||||
<Flooter v-if="vdisp.smAndUp" class="floaty mb-2 px-2" />
|
||||
</AClientOnly>
|
||||
|
||||
<ClientOnly>
|
||||
<template #fallback> </template>
|
||||
<Portal layout="#ender-layout" animate randomize fade />
|
||||
</ClientOnly>
|
||||
</VThemeProvider>
|
||||
</template>
|
||||
|
|
|
@ -61,6 +61,10 @@ body {
|
|||
}
|
||||
|
||||
// Helper classes that don't exist in Bootstrap.
|
||||
.mh-0 {
|
||||
max-height: 100% !important;
|
||||
}
|
||||
|
||||
.nobr {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -112,6 +116,14 @@ body {
|
|||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.h-animated {
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.p-animated {
|
||||
transition: padding 0.3s ease;
|
||||
}
|
||||
|
||||
// Query-overridable classes.
|
||||
.background {
|
||||
background-color: rgb(0 0 0 / 50%);
|
||||
|
@ -122,6 +134,10 @@ body {
|
|||
min-height: 100%;
|
||||
}
|
||||
|
||||
.separator {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
display: grid;
|
||||
|
||||
|
@ -257,6 +273,10 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.radial-gradient {
|
||||
background: radial-gradient(
|
||||
circle at left,
|
||||
|
@ -300,8 +320,6 @@ body {
|
|||
bottom: 0;
|
||||
right: 0;
|
||||
|
||||
padding: 0.5rem;
|
||||
|
||||
text-transform: uppercase;
|
||||
background-color: rgb(153 153 255 / 10%);
|
||||
|
||||
|
@ -313,20 +331,32 @@ body {
|
|||
}
|
||||
|
||||
&-thumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
height: 100%;
|
||||
|
||||
> img {
|
||||
width: 100%;
|
||||
height: 280px;
|
||||
height: 100%;
|
||||
max-height: 280px;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&-tags {
|
||||
> span {
|
||||
padding: 0.35em 0.65em;
|
||||
font-size: 0.85em;
|
||||
|
||||
background-color: rgb(153 153 255 / 10%);
|
||||
|
||||
border: 1px solid rgb(153 153 255 / 60%);
|
||||
border-radius: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-details {
|
||||
}
|
||||
|
||||
&-preamble {
|
||||
&-thumb {
|
||||
max-width: 800px;
|
||||
|
@ -334,12 +364,18 @@ body {
|
|||
}
|
||||
|
||||
&-content {
|
||||
:is(h1, h2, h3, h4, h5, h6) {
|
||||
font-family: Alexandria, sans-serif;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
a {
|
||||
@extend %link;
|
||||
|
||||
}
|
||||
|
||||
padding-left: 0.5rem;
|
||||
|
||||
img {
|
||||
max-height: 400px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -390,10 +426,10 @@ body {
|
|||
|
||||
&-thumb {
|
||||
min-width: 352px;
|
||||
max-height: 198px;
|
||||
|
||||
> img {
|
||||
max-width: 352px;
|
||||
height: 198px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
<script setup>
|
||||
console.log('Transition started')
|
||||
function enter(el, done) {
|
||||
const width = getComputedStyle(el).width
|
||||
console.log('@enter')
|
||||
el.style.width = width
|
||||
el.style.position = 'absolute'
|
||||
el.style.visibility = 'hidden'
|
||||
el.style.height = 'auto'
|
||||
|
||||
const height = getComputedStyle(el).height
|
||||
|
||||
el.style.width = ''
|
||||
el.style.position = ''
|
||||
el.style.visibility = ''
|
||||
el.style.height = '0'
|
||||
|
||||
// Force repaint to make sure the
|
||||
// animation is triggered correctly.
|
||||
getComputedStyle(el).height
|
||||
|
||||
// Trigger the animation.
|
||||
// We use `requestAnimationFrame` because we need
|
||||
// to make sure the browser has finished
|
||||
// painting after setting the `height`
|
||||
// to `0` in the line above.
|
||||
requestAnimationFrame(() => {
|
||||
el.style.height = height
|
||||
})
|
||||
|
||||
done()
|
||||
}
|
||||
|
||||
function afterEnter(element) {
|
||||
console.log('@after-enter')
|
||||
element.style.height = 'auto'
|
||||
}
|
||||
|
||||
function leave(element) {
|
||||
console.log('@leave')
|
||||
const height = getComputedStyle(element).height
|
||||
|
||||
element.style.height = height
|
||||
|
||||
// Force repaint to make sure the
|
||||
// animation is triggered correctly.
|
||||
getComputedStyle(element).height
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
element.style.height = '0'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Transition
|
||||
name="expand"
|
||||
@enter="enter"
|
||||
@after-enter="afterEnter"
|
||||
@leave="leave"
|
||||
>
|
||||
<slot />
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
* {
|
||||
will-change: height;
|
||||
transform: translateZ(0);
|
||||
backface-visibility: hidden;
|
||||
perspective: 1000px;
|
||||
}
|
||||
</style>
|
|
@ -2,35 +2,12 @@
|
|||
import type { PropType } from 'vue'
|
||||
|
||||
type ModeOptions = 'in-out' | 'out-in' | 'default' | undefined
|
||||
type RenderOptions =
|
||||
| 'never'
|
||||
| 'always'
|
||||
| 'xs'
|
||||
| 'sm'
|
||||
| 'sm-down'
|
||||
| 'sm-up'
|
||||
| 'md'
|
||||
| 'md-down'
|
||||
| 'md-up'
|
||||
| 'lg'
|
||||
| 'lg-down'
|
||||
| 'lg-up'
|
||||
| 'xl'
|
||||
| 'xl-down'
|
||||
| 'xl-up'
|
||||
| 'xxl'
|
||||
| undefined
|
||||
|
||||
const vdisp = ref(useVDisplay())
|
||||
const props = defineProps({
|
||||
fallback: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
render: {
|
||||
type: String as PropType<RenderOptions>,
|
||||
default: 'always',
|
||||
},
|
||||
appear: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
@ -48,45 +25,6 @@ const props = defineProps({
|
|||
default: 'animate__fadeOut',
|
||||
},
|
||||
})
|
||||
|
||||
const render = computed(() => {
|
||||
switch (props.render) {
|
||||
case 'never':
|
||||
return false
|
||||
case 'always':
|
||||
return true
|
||||
case 'xs':
|
||||
return vdisp.value.xs
|
||||
case 'sm':
|
||||
return vdisp.value.sm
|
||||
case 'sm-down':
|
||||
return vdisp.value.smAndDown
|
||||
case 'sm-up':
|
||||
return vdisp.value.smAndUp
|
||||
case 'md':
|
||||
return vdisp.value.md
|
||||
case 'md-down':
|
||||
return vdisp.value.mdAndDown
|
||||
case 'md-up':
|
||||
return vdisp.value.mdAndUp
|
||||
case 'lg':
|
||||
return vdisp.value.lg
|
||||
case 'lg-down':
|
||||
return vdisp.value.lgAndDown
|
||||
case 'lg-up':
|
||||
return vdisp.value.lgAndUp
|
||||
case 'xl':
|
||||
return vdisp.value.xl
|
||||
case 'xl-down':
|
||||
return vdisp.value.xlAndDown
|
||||
case 'xl-up':
|
||||
return vdisp.value.xlAndUp
|
||||
case 'xxl':
|
||||
return vdisp.value.xxl
|
||||
default:
|
||||
return false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -99,7 +37,7 @@ const render = computed(() => {
|
|||
:enter-active-class="`animate__animated ${props.enter}`"
|
||||
:leave-active-class="`animate__animated ${props.leave}`"
|
||||
>
|
||||
<slot v-if="render" />
|
||||
<slot />
|
||||
</Transition>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
|
|
@ -4,14 +4,7 @@ const props = defineProps({
|
|||
})
|
||||
|
||||
const config = useAppConfig()
|
||||
const fqdn = config.url.split('//')[1]
|
||||
|
||||
const currentYear = new Date().getFullYear()
|
||||
const mailTemplate = `I've just found a bug on ${config.url} and would like to report it.%0D%0A%0D%0AWebsite version: ${
|
||||
config.build.version
|
||||
}%0D%0ABuild date: ${
|
||||
config.build.date
|
||||
}%0D%0ATimestamp: ${new Date().toISOString()}%0D%0A%0D%0A%0D%0ASteps to reproduce:%0D%0A{ Explain in detail what happened here, or attach a video/screenshot }%0D%0A%0D%0AAdditional information:%0D%0A{ Helpful information, such as developer console output / Leave empty if none }%0D%0A%0D%0A%0D%0A// Keep in mind that it's just a template, you can change it as you wish! :)`
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -25,19 +18,6 @@ const mailTemplate = `I've just found a bug on ${config.url} and would like to r
|
|||
'text-shadow': !props.opaque,
|
||||
}"
|
||||
>
|
||||
<EMail
|
||||
:class="{
|
||||
'link-hi-force-dark': !props.opaque,
|
||||
'link-hi': props.opaque,
|
||||
}"
|
||||
:address="`contact@${fqdn}`"
|
||||
:cc="`admin@${fqdn}`"
|
||||
:subject="`Bug report: ${fqdn}`"
|
||||
:body="mailTemplate"
|
||||
>
|
||||
<strong>Report a bug</strong>
|
||||
</EMail>
|
||||
<br />
|
||||
© 2018-{{ currentYear }},
|
||||
<a
|
||||
:class="{
|
||||
|
|
|
@ -43,7 +43,7 @@ const props = defineProps({
|
|||
/>
|
||||
<div>
|
||||
<h1 class="alex mb-0">{{ props.title }}</h1>
|
||||
<Separator />
|
||||
<Separator class="m-0" />
|
||||
<p class="mb-0">{{ props.description }}</p>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
|
|
|
@ -3,6 +3,14 @@ import cogIcon from '~/assets/images/icons/cog.png'
|
|||
import pearlIcon from '~/assets/images/icons/pearl.gif'
|
||||
|
||||
const theme = useVThemeSSR()
|
||||
const config = useAppConfig()
|
||||
const fqdn = config.url.split('//')[1]
|
||||
|
||||
const mailTemplate = `I've just found a bug on ${config.url} and would like to report it.%0D%0A%0D%0AWebsite version: ${
|
||||
config.build.version
|
||||
}%0D%0ABuild date: ${
|
||||
config.build.date
|
||||
}%0D%0ATimestamp: ${new Date().toISOString()}%0D%0A%0D%0A%0D%0ASteps to reproduce:%0D%0A{ Explain in detail what happened here, or attach a video/screenshot }%0D%0A%0D%0AAdditional information:%0D%0A{ Helpful information, such as developer console output / Leave empty if none }%0D%0A%0D%0A%0D%0A// Keep in mind that it's just a template, you can change it as you wish! :)`
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -48,7 +56,15 @@ const theme = useVThemeSSR()
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Report a bug
|
||||
<EMail
|
||||
class="link-hi"
|
||||
:address="`contact@${fqdn}`"
|
||||
:cc="`admin@${fqdn}`"
|
||||
:subject="`Bug report: ${fqdn}`"
|
||||
:body="mailTemplate"
|
||||
>
|
||||
<strong>Report a bug</strong>
|
||||
</EMail>
|
||||
</VCardText>
|
||||
<VCardActions>
|
||||
<VSpacer></VSpacer>
|
||||
|
|
|
@ -13,7 +13,7 @@ const props = defineProps({
|
|||
|
||||
<template>
|
||||
<hr
|
||||
class="radial-gradient m-0 border-0 w-100"
|
||||
class="separator radial-gradient border-0"
|
||||
:style="{ height: props.height + 'px' }"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -8,7 +8,9 @@ const { pages } = storeToRefs(pageStore)
|
|||
const route = useRoute()
|
||||
const state = computed(() => {
|
||||
const i = pages.value.indexOf(
|
||||
pages.value.find((page) => page.path === route.fullPath)!,
|
||||
pages.value.find(
|
||||
(page) => page.path === '/' + route.fullPath.split('/')[1],
|
||||
)!,
|
||||
)
|
||||
|
||||
return {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
<template></template>
|
|
@ -1 +0,0 @@
|
|||
<template></template>
|
|
@ -1 +0,0 @@
|
|||
<template></template>
|
|
@ -4,7 +4,7 @@ description: We dive in deep into the Windows context menu and how to customize
|
|||
created: 2023-08-13T15:51:19Z
|
||||
updated: 2024-02-18T21:32:12Z
|
||||
draft: false
|
||||
tags: ['windows', 'context-menu']
|
||||
tags: ['windows', 'context-menu', 'customization', 'registry', 'shell', 'shell-extensions', 'context-menu-handlers']
|
||||
thumbnail: '/images/blog/thumbnails/the-windows-context-menu.png'
|
||||
---
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ const router = useRouter()
|
|||
const route = useRoute()
|
||||
const card = ref<HTMLElement | null>(null)
|
||||
|
||||
const pageStore = usePageStore()
|
||||
const { pages } = storeToRefs(pageStore)
|
||||
const { pages, reader } = storeToRefs(usePageStore())
|
||||
|
||||
const swipe = useSwipe(card, {
|
||||
passive: true,
|
||||
onSwipeEnd: (_touch: TouchEvent, _direction: UseSwipeDirection) => {
|
||||
|
@ -41,7 +41,11 @@ const swipe = useSwipe(card, {
|
|||
<template>
|
||||
<main
|
||||
ref="card"
|
||||
class="dimensions background rounded-1-sm overflow-auto d-flex flex-column gap-3 gap-sm-2 px-4 pt-4 pb-3"
|
||||
class="dimensions background h-animated overflow-auto d-flex flex-column gap-3 gap-sm-2 px-4 pt-4 pb-3"
|
||||
:class="{
|
||||
'rounded-1-sm': !reader,
|
||||
'mh-0': reader,
|
||||
}"
|
||||
>
|
||||
<Options />
|
||||
<Navigation />
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
const { reader } = storeToRefs(usePageStore())
|
||||
|
||||
reader.value = /\/blog\/(.*)/.test(to.path)
|
||||
})
|
|
@ -43,14 +43,14 @@ useHead({
|
|||
<template>
|
||||
<section>
|
||||
<h3 class="alex">About me</h3>
|
||||
<hr />
|
||||
<Separator />
|
||||
<p>
|
||||
<strong>🚧 This page is currently under construction.</strong> Expect a
|
||||
lot more content to be added as time passes.
|
||||
<em>Please report all bugs you encounter via the link in the footer</em>,
|
||||
I will make sure to sand them down.
|
||||
</p>
|
||||
<hr />
|
||||
<Separator />
|
||||
<p>
|
||||
Nice to meet you! I'm Andrew, a {{ age }}-year-old guy from Kaluga,
|
||||
Russia. I have been developing software since I was 10, and I have always
|
||||
|
|
|
@ -32,20 +32,36 @@ import { formatDate } from 'date-fns'
|
|||
class="rounded-4"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="w-100">
|
||||
<h3 class="post-title alex">{{ post.title }}</h3>
|
||||
<p class="post-description">{{ post.description }}</p>
|
||||
<p class="post-description mb-0">{{ post.description }}</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6 d-flex flex-row gap-1 align-items-center">
|
||||
<div class="post-tags d-flex flex-row flex-wrap gap-2 py-2">
|
||||
<span
|
||||
v-for="(tag, index) in post.tags.slice(0, 3)"
|
||||
:key="index"
|
||||
class="nobr"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
<span v-if="post.tags.length > 3" class="nobr">
|
||||
{{ post.tags.length - 3 }} more
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Separator class="m-0" />
|
||||
|
||||
<div class="post-details py-2">
|
||||
<div class="d-flex flex-row gap-1 align-items-center">
|
||||
<iconify-icon icon="mdi:calendar" />
|
||||
<small class="nobr">
|
||||
{{ formatDate(post.created, 'LLLL do, y – HH:mm') }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="post.updated" class="row">
|
||||
<div class="col-12 d-flex flex-row gap-1 align-items-center">
|
||||
<div
|
||||
v-if="post.updated"
|
||||
class="d-flex flex-row gap-1 align-items-center"
|
||||
>
|
||||
<iconify-icon icon="mdi:pencil" />
|
||||
<small class="nobr">
|
||||
{{ formatDate(post.updated, 'LLLL do, y – HH:mm') }}
|
||||
|
@ -54,7 +70,9 @@ import { formatDate } from 'date-fns'
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="post-pocket d-flex flex-row gap-1 align-items-center">
|
||||
<div
|
||||
class="post-pocket d-flex flex-row gap-1 align-items-center p-2"
|
||||
>
|
||||
<iconify-icon icon="mdi:clock-outline" />
|
||||
<small class="nobr font-monospace font-small">
|
||||
{{ post.readingTime.text }}
|
||||
|
|
|
@ -69,14 +69,14 @@ useHead({
|
|||
<template>
|
||||
<section>
|
||||
<h3 class="alex">Projects</h3>
|
||||
<hr />
|
||||
<Separator />
|
||||
<p>
|
||||
<strong>🚧 This page is currently under construction.</strong> Expect a
|
||||
lot more content to be added as time passes.
|
||||
<em>Please report all bugs you encounter via the link in the footer</em>,
|
||||
I will make sure to sand them down.
|
||||
</p>
|
||||
<hr />
|
||||
<Separator />
|
||||
<p><strong>My current projects are:</strong></p>
|
||||
<ul>
|
||||
<li v-for="(item, index) in projects" :key="index">
|
||||
|
|
|
@ -117,14 +117,14 @@ useHead({
|
|||
<template>
|
||||
<section>
|
||||
<h3 class="alex">Online presence</h3>
|
||||
<hr />
|
||||
<Separator />
|
||||
<p>
|
||||
<strong>🚧 This page is currently under construction.</strong> Expect a
|
||||
lot more content to be added as time passes.
|
||||
<em>Please report all bugs you encounter via the link in the footer</em>,
|
||||
I will make sure to sand them down.
|
||||
</p>
|
||||
<hr />
|
||||
<Separator />
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-3">
|
||||
<h5 class="alex">Social media</h5>
|
||||
|
|
|
@ -50,6 +50,8 @@ export const usePageStore = defineStore('page', () => {
|
|||
},
|
||||
])
|
||||
|
||||
const reader = ref(false)
|
||||
|
||||
function _autoFetchPages() {
|
||||
while (pages.value.length) pages.value.pop()
|
||||
|
||||
|
@ -68,5 +70,6 @@ export const usePageStore = defineStore('page', () => {
|
|||
description,
|
||||
keywords,
|
||||
pages,
|
||||
reader,
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue