mirror of
https://github.com/hpware/news-analyze.git
synced 2025-06-23 15:51:01 +08:00
Add pending animation (with the help of GitHub Copilot)
This commit is contained in:
parent
0298a5ae90
commit
231a7ce251
@ -6,7 +6,7 @@ import { ScrambleTextPlugin } from "gsap/dist/ScrambleTextPlugin";
|
|||||||
gsap.registerPlugin(ScrambleTextPlugin);
|
gsap.registerPlugin(ScrambleTextPlugin);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
// Great, there are now no errors ig
|
|
||||||
const emit = defineEmits(["windowopener", "error", "loadValue"]);
|
const emit = defineEmits(["windowopener", "error", "loadValue"]);
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -54,61 +54,69 @@ watch(
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="text-center align-center justify-center">
|
<div class="text-center align-center justify-center">
|
||||||
<!--<div
|
|
||||||
class="flex flex-row bg-[#AAACAAFF] rounded-3xl p-3 gap-3 m-3 scale-5"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
:src="fetchNewsOrgInfo?.logoUrl"
|
|
||||||
class="w-48 h-48 rounded-l-3xl object-cover p-0 m-0"
|
|
||||||
draggable="false"
|
|
||||||
/>
|
|
||||||
<div class="flex flex-col gap-3 text-left">
|
|
||||||
<h1 class="text-4xl font-bold m-3 text-left" ref="orgNameAnimation">
|
|
||||||
{{ fetchNewsOrgInfo?.title }}
|
|
||||||
</h1>
|
|
||||||
<span class="text-ms m-1 mt-5 text-left text-wrap">{{
|
|
||||||
fetchNewsOrgInfo?.description
|
|
||||||
}}</span>
|
|
||||||
<div
|
|
||||||
class="gap-[3px] flex flex-row text-center align-center justify-center"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
:href="fetchNewsOrgInfo?.website"
|
|
||||||
target="_blank"
|
|
||||||
v-if="fetchNewsOrgInfo?.website"
|
|
||||||
class="text-gray-800 hover:text-gray-500 transiton-all duration-150 flex flex-row"
|
|
||||||
><GlobeAltIcon class="w-6 h-6" />網站</a
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
:href="fetchNewsOrgInfo?.facebook"
|
|
||||||
target="_blank"
|
|
||||||
v-if="fetchNewsOrgInfo?.facebook"
|
|
||||||
class="text-gray-800 hover:text-gray-500 transiton-all duration-150 flex flex-row"
|
|
||||||
><Facebook class="w-6 h-6" />Facebook
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>-->
|
|
||||||
<div
|
<div
|
||||||
class="flex flex-row bg-gray-400/70 rounded-3xl p-3 gap-3 m-3 scale-5"
|
class="flex flex-row bg-gray-300/70 rounded-3xl p-3 gap-3 m-3 scale-5"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col gap-3 text-left">
|
<div class="flex flex-col gap-3 text-left w-full">
|
||||||
<h1 class="text-4xl font-bold m-2 text-center" ref="orgNameAnimation">
|
<h1
|
||||||
|
v-if="pending"
|
||||||
|
class="h-12 bg-gray-200 animate-pulse rounded m-2 w-3/4 mx-auto"
|
||||||
|
></h1>
|
||||||
|
<h1
|
||||||
|
v-else
|
||||||
|
class="text-4xl font-bold m-2 text-center"
|
||||||
|
ref="orgNameAnimation"
|
||||||
|
>
|
||||||
{{ fetchNewsOrgInfo?.title }}
|
{{ fetchNewsOrgInfo?.title }}
|
||||||
</h1>
|
</h1>
|
||||||
<span class="text-ms m-1 mt-5 text-left text-wrap">{{
|
|
||||||
fetchNewsOrgInfo?.description
|
<div v-if="pending" class="flex flex-col gap-2 m-1 mt-5">
|
||||||
}}</span>
|
<div class="h-4 bg-gray-200 animate-pulse rounded w-full"></div>
|
||||||
|
<div class="h-4 bg-gray-200 animate-pulse rounded w-5/6"></div>
|
||||||
|
<div class="h-4 bg-gray-200 animate-pulse rounded w-4/6"></div>
|
||||||
|
</div>
|
||||||
|
<span v-else class="text-ms m-1 mt-5 text-left text-wrap">
|
||||||
|
{{ fetchNewsOrgInfo?.description }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<div
|
<div class="space-y-3">
|
||||||
v-for="item in fetchNewsOrgInfo?.articles"
|
<template v-if="pending">
|
||||||
class="p-1 bg-gray-300/70 rounded m-1"
|
<div
|
||||||
>
|
v-for="item in 5"
|
||||||
{{ item.title }}
|
:key="item"
|
||||||
</div>
|
class="p-3 bg-gray-300/70 rounded m-1 animate-pulse h-8"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div
|
||||||
|
v-for="item in fetchNewsOrgInfo?.articles"
|
||||||
|
class="p-1 bg-gray-300/70 rounded m-1"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="title text-bold">{{ item.title }}</span>
|
||||||
|
<span class="date text-xs">{{ item.date }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.animate-pulse {
|
||||||
|
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -192,6 +192,7 @@ const openNews = (url: string, titleName: string) => {
|
|||||||
const openPublisher = (slug: string, title: string) => {
|
const openPublisher = (slug: string, title: string) => {
|
||||||
emit("openNewsSourcePage", slug, title);
|
emit("openNewsSourcePage", slug, title);
|
||||||
};
|
};
|
||||||
|
const isLoading = computed(() => contentArray.value.length === 0);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="justify-center align-center text-center">
|
<div class="justify-center align-center text-center">
|
||||||
@ -200,33 +201,82 @@ const openPublisher = (slug: string, title: string) => {
|
|||||||
class="sticky inset-x-0 top-0 bg-gray-300/90 backdrop-blur-xl border shadow-lg rounded-xl p-1 m-1 mt-0 justify-center align-center text-center z-[50] overflow-x-auto scrollbar-xl min-w-min whitespace-nowrap px-2"
|
class="sticky inset-x-0 top-0 bg-gray-300/90 backdrop-blur-xl border shadow-lg rounded-xl p-1 m-1 mt-0 justify-center align-center text-center z-[50] overflow-x-auto scrollbar-xl min-w-min whitespace-nowrap px-2"
|
||||||
>
|
>
|
||||||
<div class="gap-2 flex flex-row justify-center align-center text-center">
|
<div class="gap-2 flex flex-row justify-center align-center text-center">
|
||||||
<button
|
<!-- Tabs Loading State -->
|
||||||
v-for="item in tabs"
|
<template v-if="canNotLoadTabUI">
|
||||||
@click="updateContent(item.url, true)"
|
<div
|
||||||
:class="
|
v-for="n in 5"
|
||||||
isPrimary(item.url, true) ? 'text-sky-600 text-bold' : 'text-black'
|
:key="n"
|
||||||
"
|
class="h-8 w-20 bg-gray-400/50 animate-pulse rounded mx-1"
|
||||||
class="disabled:cursor-not-allowed"
|
></div>
|
||||||
:disabled="isPrimary(item.url, true) || switchTabs"
|
</template>
|
||||||
>
|
|
||||||
<span>{{ item.text }}</span>
|
<!-- Actual Tabs -->
|
||||||
</button>
|
<template v-else>
|
||||||
|
<button
|
||||||
|
v-for="item in tabs"
|
||||||
|
@click="updateContent(item.url, true)"
|
||||||
|
:class="
|
||||||
|
isPrimary(item.url, true)
|
||||||
|
? 'text-sky-600 text-bold'
|
||||||
|
: 'text-black'
|
||||||
|
"
|
||||||
|
class="disabled:cursor-not-allowed"
|
||||||
|
:disabled="isPrimary(item.url, true) || switchTabs"
|
||||||
|
>
|
||||||
|
<span>{{ item.text }}</span>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
<button v-if="canNotLoadTabUI"><RefreshCcwIcon /></button>
|
<button v-if="canNotLoadTabUI"><RefreshCcwIcon /></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Transition
|
|
||||||
enter-active-class="animate__animated animate__fadeIn"
|
<!-- Content Area -->
|
||||||
leave-active-class="animate__animated animate__fadeOut"
|
<div>
|
||||||
>
|
<!-- Loading State -->
|
||||||
<div v-if="switchTabs" class="absolute inset-x-0 top-12 p-2 m-12 z-[50]">
|
<template v-if="isLoading">
|
||||||
Loading...
|
<div v-for="n in 5" :key="n" class="p-2 bg-gray-200 rounded m-1">
|
||||||
</div>
|
<!-- Title Skeleton -->
|
||||||
</Transition>
|
<div
|
||||||
<Transition
|
class="h-8 bg-gray-300 animate-pulse rounded-lg w-3/4 mx-auto mb-2"
|
||||||
enter-active-class="animate__animated animate__fadeIn"
|
></div>
|
||||||
leave-active-class="animate__animated animate__fadeOut"
|
|
||||||
>
|
<!-- Publisher and Date Skeleton -->
|
||||||
<div v-if="!switchTabs">
|
<div class="flex items-center justify-center gap-2 mb-2">
|
||||||
|
<div class="h-4 w-24 bg-gray-300 animate-pulse rounded"></div>
|
||||||
|
<div class="h-4 w-4 bg-gray-300 animate-pulse rounded">--</div>
|
||||||
|
<div class="h-4 w-32 bg-gray-300 animate-pulse rounded"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Action Button Skeleton -->
|
||||||
|
<div class="flex justify-center mb-2">
|
||||||
|
<div class="h-8 w-24 bg-gray-300 animate-pulse rounded"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Similar Articles Skeleton -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<div
|
||||||
|
class="h-6 w-20 bg-gray-300 animate-pulse rounded mb-2 mx-auto"
|
||||||
|
></div>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div
|
||||||
|
v-for="i in 2"
|
||||||
|
:key="i"
|
||||||
|
class="p-2 bg-gray-300 animate-pulse rounded"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="h-4 w-3/4 bg-gray-400/50 animate-pulse rounded mb-1"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
class="h-3 w-1/2 bg-gray-400/50 animate-pulse rounded"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Actual Content -->
|
||||||
|
<template v-else>
|
||||||
<div
|
<div
|
||||||
v-for="item in contentArray"
|
v-for="item in contentArray"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@ -310,12 +360,25 @@ const openPublisher = (slug: string, title: string) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--<p :class="getCheckResult(item.title) ? 'hidden' : ''">
|
|
||||||
{{ item.shortDescription }}
|
|
||||||
</p>-->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</Transition>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.animate-pulse {
|
||||||
|
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user