Remove some files & trying to make the desktop look more fun & I'm going

to sleep now.
This commit is contained in:
yuanhau 2025-05-22 00:09:01 +08:00
parent c8429ee1a3
commit 109a39f6e9
12 changed files with 458 additions and 119 deletions

View file

@ -1,31 +0,0 @@
#!/bin/bash
ask_yes_no() {
while true; do
read -p "$1 (y/n): " answer
case ${answer:0:1} in
y|Y ) return 0 ;;
n|N ) return 1 ;;
* ) echo "Please answer yes or no.";;
esac
done
}
if ask_yes_no "Are you ABSOLUTELY in the root dir of the app?"; then
echo "Proceeding with build..."
cd ./docs/
if ask_yes_no "Have you installed vitepress before?"; then
echo "Skipping"
else
echo "Installing vitepress with bun..."
bun add -D vitepress
fi
bunx vitepress build
cd ..
cp -R ./docs/.vitepress/dist/ ./public/docs/
echo "Done :)"
exit 1
else
echo "Please navigate to the root directory and try again."
exit 1
fi

View file

@ -1,8 +0,0 @@
#!/bin/bash
cd ./docs/
npm install -g vitepress
bunx vitepress build
cd ..
cp -R ./docs/.vitepress/dist/ ./public/docs/
echo "Done :)"
exit 1

8
cleardatabase.ts Normal file
View file

@ -0,0 +1,8 @@
const cleardb = `
DROP TABLE users;
DROP TABLE usertokens;
DROP TABLE newsProviders;
DROP TABLE chat_history;
DROP TABLE news_articles;
DROP TABLE hot_news;
DROP TABLE articles_lt;`;

View file

@ -10,7 +10,7 @@ const props = defineProps<{
black?: boolean | false; black?: boolean | false;
}>(); }>();
const emit = defineEmits(["close", "min", "maximize", "restore"]); const emit = defineEmits(["close", "min", "restore"]);
const title = computed(() => props.title || "Draggable Window"); const title = computed(() => props.title || "Draggable Window");
const isDragging = ref(false); const isDragging = ref(false);
@ -86,12 +86,6 @@ const stopDrag = () => {
> >
</button> </button>
<button
@click="emit('maximize')"
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-600 rounded transition duration-200"
>
</button>
<button <button
@click="emit('close')" @click="emit('close')"
class="p-1 rounded bg-red-500 text-white hover:bg-red-600 transition duration-200" class="p-1 rounded bg-red-500 text-white hover:bg-red-600 transition duration-200"

View file

@ -2,12 +2,26 @@
import BlurPageBeforeLogin from "~/components/blurPageBeforeLogin.vue"; import BlurPageBeforeLogin from "~/components/blurPageBeforeLogin.vue";
const { t } = useI18n(); const { t } = useI18n();
const { data: favData, error, pending } = useFetch("/api/user/fav", {}); const { data: favData, error, pending } = useFetch("/api/user/fav", {});
const openApp = (link: string) => {
console.log(link);
};
</script> </script>
<template> <template>
<BlurPageBeforeLogin> <BlurPageBeforeLogin>
<div> <div
class="justify-center text-center align-center flex flex-row flex-wrap"
>
<div v-for="items in favData.items"> <div v-for="items in favData.items">
{{ items }} <div
@click="openApp(items.article_link)"
class="cursor-pointer p-4 bg-gray-300/80 rounded-xl backdrop-blur-sm hover:-translate-y-2 transition-all duration-200"
>
<h1 class="text-2xl text-bold">{{ items.name }}</h1>
<div class="flex flex-row gap-2 text-center">
<span>Date:</span>
<span>{{ items.favTime }}</span>
</div>
</div>
</div> </div>
</div> </div>
</BlurPageBeforeLogin> </BlurPageBeforeLogin>

View file

@ -76,7 +76,7 @@ uuid text primary key,
title text not null, title text not null,
content text not null, content text not null,
origin text not null, origin text not null,
author text, author text
) )
`; `;

View file

@ -19,6 +19,7 @@
"startusing": "Let's Start!", "startusing": "Let's Start!",
"learnmore": "Learn more", "learnmore": "Learn more",
"documentation": "Documentation", "documentation": "Documentation",
"tools": "Tools",
"qanda": { "qanda": {
"titles": { "titles": {
"whydes": "Why make this platform?", "whydes": "Why make this platform?",

View file

@ -19,6 +19,7 @@
"startusing": "開始使用!", "startusing": "開始使用!",
"learnmore": "了解更多", "learnmore": "了解更多",
"documentation": "如何使用", "documentation": "如何使用",
"tools": "工具",
"qanda": { "qanda": {
"titles": { "titles": {
"whydes": "為什麼要做這個平台?", "whydes": "為什麼要做這個平台?",

View file

@ -176,53 +176,6 @@ const associAppWindow = [
}, },
]; ];
/*
const keyboardShortcuts = {
'Meta+k': {
action: () => toggleMenu(),
description: 'Toggle menu'
},
'Meta+q': {
action: () => router.push(localePath("/home")),
description: 'Quit to home'
},
'Meta+w': {
action: () => closeWindow(activeWindows.value[activeWindows.value.length - 1]?.id),
description: 'Close current window'
},
'Meta+t': {
action: () => findAndOpenWindow('tty'),
description: 'Open terminal'
},
}
// Keyboard shortcuts
const handleKeyboardActions = (e: KeyboardEvent) => {
const key = [
e.metaKey ? "Meta": "",
e.ctrlKey ? "Ctrl": "",
e.shiftKey ? "Shift": "",
e.altKey ? "Alt": "",
e.key.toLowerCase()
].filter(Boolean).join('+')
const shortcut = keyboardShortcuts[key];
if (shortcut) {
console.log(`Shortcut triggered: ${key}`);
e.preventDefault()
shortcut.action()
}
}
onMounted(() => {
window.addEventListener('keydown', handleKeyboardActions)
});
onUnmounted(() => {
window.removeEventListener('keydown', handleKeyboardActions)
});
*/
// Date // Date
const currentDate = ref( const currentDate = ref(
new Date().toLocaleDateString("zh-TW", { new Date().toLocaleDateString("zh-TW", {
@ -385,13 +338,6 @@ const openNewWindowViaApp = (windowId: string) => {
}, 1000); }, 1000);
}; };
const maxWindow = (windowUUId: string) => {
const windowIndex = activeWindows.value.findIndex(
(window) => window.absoluteId === windowUUId,
);
console.log(windowIndex);
};
const toggleMinWindow = (windowUUId: string) => { const toggleMinWindow = (windowUUId: string) => {
const windowIndex = ""; const windowIndex = "";
}; };
@ -557,7 +503,6 @@ watchEffect((cleanupFn) => {
:width="window.width" :width="window.width"
:height="window.height" :height="window.height"
@click="obtainTopWindowPosition(window.id)" @click="obtainTopWindowPosition(window.id)"
@maximize="maxWindow(window.absoluteId)"
:black="window.black" :black="window.black"
> >
<Suspense> <Suspense>

428
pages/fun-desktop.vue Normal file
View file

@ -0,0 +1,428 @@
<script setup lang="ts">
// Make the Desktop funner // TODO
// No layout
definePageMeta({
layout: false,
});
// interfaces
interface currentNavBarInterface {
name: string;
icon: string;
action: any;
flash: boolean;
windowAssociated: string;
minimized: boolean;
}
interface associAppWindowInterface {
name: string;
id: string;
absoluteId: string;
title: string;
component: any;
width: string;
height: string;
black: boolean;
}
// Import plugins
import { v4 as uuidv4 } from "uuid";
import { gsap } from "gsap";
import { TextPlugin } from "gsap/TextPlugin";
gsap.registerPlugin(TextPlugin);
// Import Windows
import LoginWindow from "~/components/app/windows/login.vue";
import HotNewsWindow from "~/components/app/windows/hotnews.vue";
import SourcesWindow from "~/components/app/windows/sources.vue";
import AboutWindow from "~/components/app/windows/about.vue";
import ChatbotWindow from "~/components/app/windows/chatbot.vue";
import AboutNewsOrgWindow from "~/components/app/windows/aboutNewsOrg.vue";
import TTYWindow from "~/components/app/windows/tty.vue";
import FavStaredWindow from "~/components/app/windows/fav.vue";
import Error404Window from "~/components/app/windows/error404.vue";
import NewsViewWindow from "~/components/app/windows/newsView.vue";
// Import Icons
import {
ComputerDesktopIcon,
UserIcon,
LanguageIcon,
ChevronRightIcon,
} from "@heroicons/vue/24/outline";
// i18n
const { t, locale, locales } = useI18n();
const switchLocalePath = useSwitchLocalePath();
const localePath = useLocalePath();
// Router
const router = useRouter();
const route = useRoute();
// values
const popMessage = ref(null);
const menuOpen = ref(false);
const langMenuOpen = ref(false);
const lang = ref(locale.value);
const alertOpen = ref(false);
const currentNavBar = ref<currentNavBarInterface[]>([]);
const bootingAnimation = ref(true);
const activeWindows = ref<associAppWindowInterface[]>([]);
const openApp = ref();
const openAppId = ref();
const openAppNameQuery = ref();
const currentOpenAppId = ref(0);
const progress = ref(0);
const titleAppName = ref("Desktop");
const openingAppViaAnApp = ref(false);
const passedValues = ref();
const globalWindowVal = ref(new Map());
const changeLangAnimation = ref(false);
// Key Data
const menuItems = [
{ name: t("app.hotnews"), windowName: "hotnews" },
{ name: t("app.news"), windowName: "news" },
{ name: t("app.sources"), windowName: "sources" },
{ name: t("app.starred"), windowName: "starred" },
{ name: t("app.chatbot"), windowName: "chatbot" },
{ name: t("app.about"), windowName: "about" },
{ name: t("app.terminal"), windowName: "tty" },
{ name: t("app.settings"), windowName: "settings" },
{ name: t("app.login"), windowName: "login" },
{ name: t("app.leave"), windowName: "leave" },
];
const associAppWindow = [
{
name: "hotnews",
id: "1",
title: t("app.hotnews"),
component: HotNewsWindow,
width: "700px",
height: "500px",
},
{
name: "login",
id: "2",
title: t("app.login"),
component: LoginWindow,
},
{
name: "sources",
id: "3",
title: t("app.sources"),
component: SourcesWindow,
width: "700px",
height: "500px",
},
{
name: "about",
id: "4",
title: t("app.about"),
component: AboutWindow,
},
{
name: "settings",
id: "5",
title: t("app.settings"),
component: Error404Window,
},
{
name: "news",
id: "6",
title: t("app.news"),
component: Error404Window,
},
{
name: "starred",
id: "7",
title: t("app.starred"),
component: FavStaredWindow,
},
{
name: "chatbot",
id: "8",
title: t("app.chatbot"),
component: ChatbotWindow,
width: "400px",
height: "600px",
},
{
name: "error404",
id: "9",
title: t("app.error404"),
component: Error404Window,
},
{
name: "aboutNewsOrg",
id: "10",
title: t("app.aboutNewsOrg"),
component: AboutNewsOrgWindow,
},
{
name: "tty",
id: "11",
title: t("app.terminal"),
component: TTYWindow,
black: true,
},
{
name: "newsView",
id: "12",
title: t("app.newsview"),
component: NewsViewWindow,
},
];
// Date
const currentDate = ref(
new Date().toLocaleDateString("zh-TW", {
month: "2-digit",
day: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
}),
);
onMounted(() => {
setInterval(() => {
currentDate.value = new Date().toLocaleDateString("zh-TW", {
month: "2-digit",
day: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
});
}, 1000);
});
// functions
onMounted(() => {
associAppWindow.forEach((window) => {
globalWindowVal.value.set(window.name, {
id: window.id,
title: window.title,
windowCount: 1,
});
});
});
const openWindow = (windowName?: string) => {
if (windowName === "leave") {
if (confirm("Are you sure?")) {
router.push(localePath("/home"));
} else {
return;
}
} else {
if (windowName) findAndOpenWindow(windowName);
}
menuOpen.value = false;
};
const unMinWindow = (windowName?: string) => {
console.log(windowName);
};
// menus
const toggleMenu = () => {
menuOpen.value = !menuOpen.value;
};
// Lang Menu
const toggleLangMenu = () => {
langMenuOpen.value = !langMenuOpen.value;
};
// ?openapp= component
onMounted(async () => {
openApp.value = route.query.openapp;
openAppId.value = route.query.id;
if (openApp.value) {
// DO NOT REMOVE THIS FUNCTION!! IT WILL ABSOLUTELY 100% FAIL!
if (openApp.value === "newsView") {
return;
}
openWindow(openApp.value);
}
});
const findAndOpenWindow = (windowName: string) => {
const app = associAppWindow.find((app) => app.name === windowName);
// Prevent dual logins
if (
windowName === "login" &&
activeWindows.value.some((window) => window.name === "login")
) {
return;
}
// Prevent dual about
if (
windowName === "about" &&
activeWindows.value.some((window) => window.name === "about")
) {
return;
}
if (app) {
// Use shallowRef for better performance with components
const windowComponent = shallowRef(app.component);
titleAppName.value = app.title;
const abosluteId = uuidv4();
activeWindows.value.push({
id: currentOpenAppId.value,
absoluteId: abosluteId,
component: windowComponent,
name: windowName,
title: app.title,
width: app.width || "600px",
height: app.height || "400px",
black: app.black || false,
});
currentOpenAppId.value++;
// Add to navbar
const windowNameVal2 =
globalWindowVal.value.get(windowName).windowCount === 1
? windowName
: windowName +
"(" +
globalWindowVal.value.get(windowName).windowCount +
")";
currentNavBar.value.push({
name: windowNameVal2,
icon: "anything",
action: "idk",
flash: true,
windowAssociated: abosluteId,
minimized: false,
});
globalWindowVal.value.get(windowName).windowCount++;
}
};
const obtainTopWindowPosition = (windowId: string) => {
if (!openingAppViaAnApp.value) {
const windowIndex = activeWindows.value.findIndex(
(window) => window.id === windowId,
);
if (windowIndex !== -1) {
const [window] = activeWindows.value.splice(windowIndex, 1);
titleAppName.value = window.title;
activeWindows.value.push(window);
}
}
};
const closeWindow = (windowId: string, windowAID: string) => {
activeWindows.value = activeWindows.value.filter(
(window) => window.id !== windowId,
);
currentNavBar.value = currentNavBar.value.filter(
(window) => window.windowAssociated !== windowAID,
);
console.log("activeWindows.value", activeWindows.value);
};
const openNewWindowViaApp = (windowId: string) => {
openingAppViaAnApp.value = true;
findAndOpenWindow(windowId);
setTimeout(() => {
openingAppViaAnApp.value = false;
}, 1000);
};
const maxWindow = (windowUUId: string) => {
const windowIndex = activeWindows.value.findIndex(
(window) => window.absoluteId === windowUUId,
);
console.log(windowIndex);
};
const toggleMinWindow = (windowUUId: string) => {
const windowIndex = "";
};
// Title
useSeoMeta({
title: "Desktop",
});
watchEffect(() => {
useSeoMeta({
title: titleAppName.value + " - Desktop",
});
});
// Booting animation
onMounted(() => {
const changeLang = route.query.changelang;
if (changeLang) {
bootingAnimation.value = false;
changeLangAnimation.value = true;
}
setTimeout(() => {
changeLangAnimation.value = false;
}, 4000);
});
onMounted(() => {
// booting animation bypass
const bootingHeaderParams = route.query.bypass;
if (bootingHeaderParams) {
bootingAnimation.value = false;
}
});
onMounted(() => {
if (bootingAnimation.value) {
gsap.to(popMessage.value, {
duration: 0.5,
text: t("app.booting"),
ease: "none",
});
}
setTimeout(() => {
bootingAnimation.value = false;
}, 2000);
});
watchEffect((cleanupFn) => {
const tier = setTimeout(() => (progress.value = 10), Math.random() * 50);
const timer = setTimeout(() => (progress.value = 30), Math.random() * 100);
const timmer = setTimeout(() => (progress.value = 70), Math.random() * 150);
const timmmer = setTimeout(() => (progress.value = 100), 1800);
cleanupFn(() => clearTimeout(tier));
cleanupFn(() => clearTimeout(timer));
cleanupFn(() => clearTimeout(timmer));
cleanupFn(() => clearTimeout(timmmer));
});
</script>
<template>
<div v-if="changeLangAnimation">
<div
class="flex flex-col justify-center align-center text-center absolute w-full h-screen inset-0 overscroll-none bg-gray-600/50 z-[999999]"
>
<span>{{ t("app.changelangmessage") }}</span>
</div>
</div>
<div v-if="bootingAnimation">
<div
class="flex flex-col justify-center align-center text-center absolute w-full h-screen inset-0 overscroll-none"
>
<Progress
v-model="progress"
class="w-3/5 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-gradient-to-r from-[#2a7b9b] then-[#8d57c7] to-[#ed4242]"
/>
<br />
<span class="text-xl text-bold mt-3 text-sky-200">{{
t("app.launchtext")
}}</span>
</div>
</div>
</template>

View file

@ -40,11 +40,6 @@ const cards = [
title: t("home.cards.title.interface"), title: t("home.cards.title.interface"),
description: t("home.cards.description.interface"), description: t("home.cards.description.interface"),
}, },
{
icon: DocumentDuplicateIcon,
title: t("home.cards.title.documentation"),
description: t("home.cards.description.documentation"),
},
{ {
icon: GithubIcon, icon: GithubIcon,
title: t("home.cards.title.opensource"), title: t("home.cards.title.opensource"),
@ -130,11 +125,11 @@ useSeoMeta({
<span>{{ t("home.startusing") }}</span> <span>{{ t("home.startusing") }}</span>
</button> </button>
</NuxtLink> </NuxtLink>
<NuxtLink :to="localePath('/docs/')"> <NuxtLink :to="localePath('/tools/')">
<button <button
class="m-4 ml-1 mr-1 bg-[#8C9393] text-white p-3 rounded-[10px] bg-gray-700 transition-all duration-150 hover:transform hover:scale-105 hover:shadow-lg" class="m-4 ml-1 mr-1 bg-[#8C9393] text-white p-3 rounded-[10px] bg-gray-700 transition-all duration-150 hover:transform hover:scale-105 hover:shadow-lg"
> >
<span>{{ t("home.documentation") }}</span> <span>{{ t("home.tools") }}</span>
</button> </button>
</NuxtLink> </NuxtLink>
<NuxtLink to="#learnmore"> <NuxtLink to="#learnmore">

View file

@ -1,8 +0,0 @@
<script setup lang="ts">
const { t } = useI18n();
</script>
<template>
<div>
<h1>{{ t("newsOrgs.title") }}</h1>
</div>
</template>