-
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b99ae98
commit f2db99b
Showing
6 changed files
with
162 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,136 @@ | ||
<script setup> | ||
import { ArrowUpIcon } from '@heroicons/vue/24/solid' | ||
import { useToggle } from '@vueuse/core' | ||
const [isActive, toggleIsActive] = useToggle(false) | ||
const userSettings = useUserSettings() | ||
import { useRestoreLastSessionPopup } from '~/composables/useRestoreLastSessionPopup' | ||
import { toast } from 'vue-sonner' | ||
import qs from 'qs' | ||
import { Dialog, DialogPanel, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue' | ||
const router = useRouter() | ||
const { isPremium } = useUserData() | ||
const { lastPostsPage, isMenuActive, toggleMenu } = useRestoreLastSessionPopup() | ||
const bodyText = computed(() => { | ||
if (!userSettings.lastPostsPage) { | ||
if (!lastPostsPage.value) { | ||
return null | ||
} | ||
const lastPostsPageRoute = router.resolve(userSettings.lastPostsPage) | ||
/** | ||
* This is a fix, because using router.resolve() does not parse with `qs.parse()` | ||
*/ | ||
const lastPostsPageQuery = qs.parse(lastPostsPage.value) | ||
const lastPostsPageUrl = new URL(lastPostsPageRoute.fullPath, window.location.origin) | ||
let text = `Get back` | ||
const tags = lastPostsPageUrl.searchParams.get('tags')?.split('|') | ||
const page = lastPostsPageUrl.searchParams.get('page') | ||
const filters = lastPostsPageUrl.searchParams.get('filters') | ||
let text = `You were` | ||
if (lastPostsPageQuery.page) { | ||
text += ` to page ${lastPostsPageQuery.page}` | ||
} | ||
if (page) { | ||
text += `on page ${page}` | ||
// Use "to" or "of" depending on the page | ||
if (lastPostsPageQuery.page) { | ||
text += ` of` | ||
} else { | ||
text += ` to` | ||
} | ||
if (tags && tags.length) { | ||
text += `with tags ${tags.join(', ')}` | ||
text += ` posts` | ||
if (lastPostsPageQuery.tags?.length) { | ||
const tags = lastPostsPageQuery.tags.split('|') | ||
text += ` tagged with ${tags.join(', ')}` | ||
} | ||
if (filters) { | ||
// TODO | ||
if (lastPostsPageQuery.filter) { | ||
const filters = Object.keys(lastPostsPageQuery.filter) | ||
text += `, and ${filters.join(', ')} filter` | ||
if (filters.length > 1) { | ||
text += 's' | ||
} | ||
} | ||
return text | ||
}) | ||
// TODO: Only do this once, when the entire app has been booted | ||
onMounted(() => { | ||
if (!userSettings.lastPostsPage) { | ||
function onClick() { | ||
if (!isPremium.value) { | ||
toast.error('[Premium feature] Restore last session is only available for Premium users') | ||
return | ||
} | ||
toggleIsActive(true) | ||
}) | ||
const lastPostsPageRoute = router.resolve(lastPostsPage.value) | ||
function onClick() { | ||
// TODO: Navigate to userSettings.lastPostsPage while doing a full reload | ||
// TODO: Add analytics to URL | ||
// TODO: Skip if not Premium and show a Toast | ||
const lastPostsPageUrl = new URL(lastPostsPageRoute.fullPath, window.location.origin) | ||
window.location.assign(lastPostsPageUrl.toString()) | ||
} | ||
</script> | ||
<template> | ||
<Teleport to="body"> | ||
<transition | ||
enter-active-class="transition ease-out duration-150" | ||
enter-from-class="transform opacity-0 scale-95" | ||
enter-to-class="transform opacity-100 scale-100" | ||
leave-active-class="transition ease-in duration-150" | ||
leave-from-class="transform opacity-100 scale-100" | ||
leave-to-class="transform opacity-0 scale-95" | ||
<TransitionRoot | ||
:show="isMenuActive && lastPostsPage != null" | ||
as="template" | ||
> | ||
<Dialog | ||
as="div" | ||
class="relative z-20" | ||
@close="toggleMenu(false)" | ||
> | ||
<div | ||
v-if="userSettings.lastPostsPage" | ||
class="fixed bottom-10" | ||
<TransitionChild | ||
as="template" | ||
enter="ease-out duration-300" | ||
enter-from="opacity-0" | ||
enter-to="opacity-100" | ||
leave="ease-in duration-200" | ||
leave-from="opacity-100" | ||
leave-to="opacity-0" | ||
> | ||
<span> Restore last session? </span> | ||
<!-- --> | ||
{{ bodyText }} | ||
<button | ||
class="hover:hover-text-util hover:hover-bg-util flex h-12 w-12 items-center justify-center rounded-full bg-base-1000/60 text-base-content-highlight ring-2 ring-base-0/20 backdrop-blur" | ||
type="button" | ||
@click="onClick" | ||
> | ||
Restore | ||
<ArrowUpIcon class="h-6 w-6" /> | ||
</button> | ||
<div class="fixed inset-0 bg-base-1000/80 backdrop-blur transition-opacity" /> | ||
</TransitionChild> | ||
<div class="fixed inset-0 z-10 overflow-y-auto"> | ||
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0"> | ||
<TransitionChild | ||
as="template" | ||
enter="ease-out duration-300" | ||
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" | ||
enter-to="opacity-100 translate-y-0 sm:scale-100" | ||
leave="ease-in duration-200" | ||
leave-from="opacity-100 translate-y-0 sm:scale-100" | ||
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" | ||
> | ||
<DialogPanel | ||
class="relative transform overflow-hidden rounded-lg bg-base-1000 px-4 pb-4 pt-5 text-left shadow-xl ring-1 ring-base-0/10 transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6" | ||
> | ||
<!-- TODO: Add dismiss button --> | ||
<!-- TODO: Add dismiss forever button in dropdown --> | ||
<div> | ||
<DialogTitle | ||
as="h3" | ||
class="text-base font-medium leading-6 tracking-tight text-base-content-highlight" | ||
> | ||
Continue where you left off? | ||
</DialogTitle> | ||
<div class="mt-1 text-sm"> | ||
{{ bodyText }} | ||
</div> | ||
</div> | ||
<div class="mt-5 sm:mt-6"> | ||
<button | ||
class="hover:hover-text-util focus-visible:focus-outline-util hover:hover-bg-util w-full rounded-md px-3 py-2 text-sm shadow-sm ring-1 ring-base-0/20" | ||
type="button" | ||
@click="onClick" | ||
> | ||
Continue | ||
</button> | ||
</div> | ||
</DialogPanel> | ||
</TransitionChild> | ||
</div> | ||
</div> | ||
</transition> | ||
</Teleport> | ||
</Dialog> | ||
</TransitionRoot> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { useStorage, useToggle } from '@vueuse/core' | ||
|
||
const lastPostsPage = useStorage<string | undefined>('settings-lastPostsPage', undefined, localStorage, { | ||
writeDefaults: false | ||
}) | ||
|
||
const [isMenuActive, toggleMenu] = useToggle(false) | ||
|
||
export function useRestoreLastSessionPopup() { | ||
return { | ||
lastPostsPage, | ||
|
||
isMenuActive, | ||
toggleMenu | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,29 @@ | ||
import { useRestoreLastSessionPopup } from '~/composables/useRestoreLastSessionPopup' | ||
|
||
let hasAppBooted = false | ||
|
||
export default defineNuxtRouteMiddleware((to, from) => { | ||
const userSettings = useUserSettings() | ||
const { lastPostsPage, toggleMenu } = useRestoreLastSessionPopup() | ||
|
||
// Show menu on first app boot | ||
// And skip if going to the same page | ||
if (!hasAppBooted && to.fullPath !== lastPostsPage.value) { | ||
hasAppBooted = true | ||
|
||
toggleMenu(true) | ||
return | ||
} | ||
|
||
if (to.name !== 'posts') { | ||
return | ||
} | ||
|
||
// Skip if same route | ||
if (to.fullPath === from.fullPath) { | ||
return | ||
} | ||
|
||
// TODO: Skip if to has default values | ||
|
||
userSettings.lastPostsPage = to.fullPath | ||
lastPostsPage.value = to.fullPath | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters