Skip to content

Commit

Permalink
Merge pull request #36 from Open-Webtoon-Reader/improvement/data-saving
Browse files Browse the repository at this point in the history
Merge data saving to Main
  • Loading branch information
Xen0Xys authored Oct 13, 2024
2 parents 4dd47c1 + 5cd3ae6 commit 202bbee
Show file tree
Hide file tree
Showing 21 changed files with 2,560 additions and 2,217 deletions.
2 changes: 2 additions & 0 deletions assets/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-disabled: 210 40% 99%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
Expand Down Expand Up @@ -49,6 +50,7 @@
--primary-foreground:222.2 47.4% 11.2%;

--secondary:217.2 32.6% 17.5%;
--secondary-disabled:217.2 32.6% 12%;
--secondary-foreground:210 40% 98%;

--muted:217.2 32.6% 17.5%;
Expand Down
9 changes: 0 additions & 9 deletions components/top/BurgerMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
import {Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger} from "~/components/ui/sheet";
import NavButton from "~/components/buttons/NavButton.vue";
function clearApiUrl(){
console.log("clear");
clearFromLocalStorage("apiurl");
navigateTo("/apiurl");
}
</script>

<template>
Expand All @@ -30,9 +24,6 @@ function clearApiUrl(){
Settings
</NavButton>
</SheetClose>
<Button variant="destructive" @click="clearApiUrl">
API Url
</Button>
</SheetDescription>
</SheetHeader>
</SheetContent>
Expand Down
14 changes: 14 additions & 0 deletions components/ui/dialog/Dialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script setup lang="ts">
import { DialogRoot, type DialogRootEmits, type DialogRootProps, useForwardPropsEmits } from 'radix-vue'
const props = defineProps<DialogRootProps>()
const emits = defineEmits<DialogRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>

<template>
<DialogRoot v-bind="forwarded">
<slot />
</DialogRoot>
</template>
11 changes: 11 additions & 0 deletions components/ui/dialog/DialogClose.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { DialogClose, type DialogCloseProps } from 'radix-vue'
const props = defineProps<DialogCloseProps>()
</script>

<template>
<DialogClose v-bind="props">
<slot />
</DialogClose>
</template>
50 changes: 50 additions & 0 deletions components/ui/dialog/DialogContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import {
DialogClose,
DialogContent,
type DialogContentEmits,
type DialogContentProps,
DialogOverlay,
DialogPortal,
useForwardPropsEmits,
} from 'radix-vue'
import { X } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
const props = defineProps<DialogContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DialogContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
<DialogPortal>
<DialogOverlay
class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
/>
<DialogContent
v-bind="forwarded"
:class="
cn(
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
props.class,
)"
>
<slot />

<DialogClose
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
>
<X class="w-4 h-4" />
<span class="sr-only">Close</span>
</DialogClose>
</DialogContent>
</DialogPortal>
</template>
24 changes: 24 additions & 0 deletions components/ui/dialog/DialogDescription.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { DialogDescription, type DialogDescriptionProps, useForwardProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>

<template>
<DialogDescription
v-bind="forwardedProps"
:class="cn('text-sm text-muted-foreground', props.class)"
>
<slot />
</DialogDescription>
</template>
19 changes: 19 additions & 0 deletions components/ui/dialog/DialogFooter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{ class?: HTMLAttributes['class'] }>()
</script>

<template>
<div
:class="
cn(
'flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2',
props.class,
)
"
>
<slot />
</div>
</template>
16 changes: 16 additions & 0 deletions components/ui/dialog/DialogHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>

<template>
<div
:class="cn('flex flex-col gap-y-1.5 text-center sm:text-left', props.class)"
>
<slot />
</div>
</template>
59 changes: 59 additions & 0 deletions components/ui/dialog/DialogScrollContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import {
DialogClose,
DialogContent,
type DialogContentEmits,
type DialogContentProps,
DialogOverlay,
DialogPortal,
useForwardPropsEmits,
} from 'radix-vue'
import { X } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
const props = defineProps<DialogContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DialogContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
<DialogPortal>
<DialogOverlay
class="fixed inset-0 z-50 grid place-items-center overflow-y-auto bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
>
<DialogContent
:class="
cn(
'relative z-50 grid w-full max-w-lg my-8 gap-4 border border-border bg-background p-6 shadow-lg duration-200 sm:rounded-lg md:w-full',
props.class,
)
"
v-bind="forwarded"
@pointer-down-outside="(event) => {
const originalEvent = event.detail.originalEvent;
const target = originalEvent.target as HTMLElement;
if (originalEvent.offsetX > target.clientWidth || originalEvent.offsetY > target.clientHeight) {
event.preventDefault();
}
}"
>
<slot />

<DialogClose
class="absolute top-3 right-3 p-0.5 transition-colors rounded-md hover:bg-secondary"
>
<X class="w-4 h-4" />
<span class="sr-only">Close</span>
</DialogClose>
</DialogContent>
</DialogOverlay>
</DialogPortal>
</template>
29 changes: 29 additions & 0 deletions components/ui/dialog/DialogTitle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { DialogTitle, type DialogTitleProps, useForwardProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>

<template>
<DialogTitle
v-bind="forwardedProps"
:class="
cn(
'text-lg font-semibold leading-none tracking-tight',
props.class,
)
"
>
<slot />
</DialogTitle>
</template>
11 changes: 11 additions & 0 deletions components/ui/dialog/DialogTrigger.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { DialogTrigger, type DialogTriggerProps } from 'radix-vue'
const props = defineProps<DialogTriggerProps>()
</script>

<template>
<DialogTrigger v-bind="props">
<slot />
</DialogTrigger>
</template>
9 changes: 9 additions & 0 deletions components/ui/dialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export { default as Dialog } from './Dialog.vue'
export { default as DialogClose } from './DialogClose.vue'
export { default as DialogTrigger } from './DialogTrigger.vue'
export { default as DialogHeader } from './DialogHeader.vue'
export { default as DialogTitle } from './DialogTitle.vue'
export { default as DialogDescription } from './DialogDescription.vue'
export { default as DialogContent } from './DialogContent.vue'
export { default as DialogScrollContent } from './DialogScrollContent.vue'
export { default as DialogFooter } from './DialogFooter.vue'
36 changes: 19 additions & 17 deletions components/webtoons/episodes/EpisodeItem.vue
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
<script setup lang="ts">
import {sumToImageUrl} from "~/utils/api";
import {Collapsible} from "~/components/ui/collapsible";
import {Badge} from "~/components/ui/badge";
import {isEpisodeStarted} from "~/utils/storage";
const {episode} = defineProps<{
episode: any,
}>();
const isStarted = ref<boolean>(isEpisodeStarted(episode.id));
</script>

<template>
<Collapsible>
<div id="main" class="flex items-center cursor-pointer" @click="navigateTo(`/episode/${episode.id}`)">
<NuxtImg :src="sumToImageUrl(episode.thumbnail)" loading="lazy" format="webp" class="aspect-square h-20 sm:h-24 md:h-28 xl:h-32"/>
<div id="infos" class="flex items-center w-full justify-between pl-2 pr-4 h-20 sm:h-24 md:h-28 xl:h-32">
<div id="text-infos" class="flex flex-col w-full h-full justify-center">
<div class="flex flex-row justify-between items-center">
<div id="title" class="flex flex-row gap-2">
<div v-if="episode.isNew" class="flex items-center">
<Badge v-if="episode.isNew" variant="default">New</Badge>
</div>
<h4 class="whitespace-nowrap truncate max-w-64">{{ episode.title }}</h4>
</div>
<div id="number">
<p class="opacity-30">#{{ episode.number }}</p>
<div id="main" class="flex items-center cursor-pointer hover:!bg-inherit" :class="{started: isStarted}" @click="navigateTo(`/episode/${episode.id}`)">
<NuxtImg :src="sumToImageUrl(episode.thumbnail)" loading="lazy" format="webp" class="aspect-square h-20 sm:h-24 md:h-28 xl:h-32"/>
<div id="infos" class="flex items-center w-full justify-between pl-2 pr-4 h-20 sm:h-24 md:h-28 xl:h-32">
<div id="text-infos" class="flex flex-col w-full h-full justify-center">
<div class="flex flex-row justify-between items-center">
<div id="title" class="flex flex-row gap-2">
<div v-if="episode.isNew" class="flex items-center">
<Badge v-if="episode.isNew" variant="default">New</Badge>
</div>
<h4 class="whitespace-nowrap truncate max-w-64">{{ episode.title }}</h4>
</div>
<div id="number">
<p class="opacity-30">#{{ episode.number }}</p>
</div>
</div>
</div>
</div>
</Collapsible>
</div>
</template>

<style scoped>
.started{
@apply bg-secondary-disabled;
}
</style>
17 changes: 11 additions & 6 deletions components/webtoons/episodes/EpisodeList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@ import EpisodeItem from "~/components/webtoons/episodes/EpisodeItem.vue";
import {Skeleton} from "~/components/ui/skeleton";
import EpisodeSkeleton from "~/components/webtoons/episodes/EpisodeSkeleton.vue";
import VisibilityObserver from "~/components/utils/VisibilityObserver.vue";
import {getOrder, saveOrder} from "~/utils/storage";
useSeoMeta({
title: "OWR",
description: "Episodes page",
});
const id = useRoute().params.id as any as number;
const title = ref("");
const episodes = ref<any[]>([]);
const maxIndex = ref<number>(30);
const newFirst = ref<boolean>(true);
const order = ref<boolean>(getOrder(id));
const id = useRoute().params.id as any as number;
function loadEpisodes(){
const webtoonState: any = useState(`webtoon-${id}`);
Expand Down Expand Up @@ -45,11 +47,12 @@ function increaseMaxIndex(){
}
function toggleOrder(){
newFirst.value = !newFirst.value;
order.value = !order.value;
saveOrder(id, order.value);
}
const orderedEpisodes = computed(() => {
return newFirst.value ? episodes.value : [...episodes.value].reverse();
return order.value ? episodes.value : [...episodes.value].reverse();
});
onMounted(() => {
Expand All @@ -62,8 +65,10 @@ onMounted(() => {
<div class="h-full w-full md:w-3/4 lg:w-1/2 2xl:w-1/3 border-x-[1px]">
<div id="header" class="relative flex gap-4 py-4 px-10 justify-center items-center">
<Button variant="outline" class="absolute left-0 ml-4" @click="toggleOrder">
<Icon v-if="newFirst" name="iconoir:arrow-up"/>
<Icon v-else name="iconoir:arrow-down"/>
<ClientOnly>
<Icon v-if="order" name="iconoir:arrow-up"/>
<Icon v-else name="iconoir:arrow-down"/>
</ClientOnly>
</Button>
<h4 v-if="title">{{ title }}</h4>
<Skeleton v-else class="w-1/2 h-8"/>
Expand Down
Loading

0 comments on commit 202bbee

Please sign in to comment.