Graphical overhaul.
Remove all legacy pixeldrain pages, handlers and assets. Remove old theming engine. Make logo responsive to the accent colour. Lots of other stuff.
This commit is contained in:
@@ -1,58 +1,50 @@
|
||||
<script lang="ts">
|
||||
import { onMount, tick } from "svelte";
|
||||
import HomePage from "home_page/HomePage.svelte";
|
||||
import LoginRouter from "login/Router.svelte";
|
||||
import HomeRouter from "user_home/Router.svelte";
|
||||
import AdminRouter from "admin_panel/Router.svelte";
|
||||
import Filesystem from "filesystem/Filesystem.svelte";
|
||||
import { onMount, tick, type Component } from "svelte";
|
||||
import NotFound from "./NotFound.svelte";
|
||||
import SpeedtestPage from "speedtest/SpeedtestPage.svelte";
|
||||
import Appearance from "pages/Appearance.svelte";
|
||||
import Footer from "layout/Footer.svelte";
|
||||
import { current_page_store, type Tab } from "./RouterStore";
|
||||
import { get_user, type User } from "lib/NovaAPI";
|
||||
import { breadcrumbs_store } from "./BreadcrumbStore";
|
||||
import { loading_run } from "lib/Loading";
|
||||
|
||||
// Pages are downloaded when they are opened for the first time. Someone who
|
||||
// opens a shared file doesn't have to download the dashboard and admin panel
|
||||
let pages: Tab[] = [
|
||||
{
|
||||
path: "/",
|
||||
title: "Home",
|
||||
component: HomePage,
|
||||
component: () => import("home_page/HomePage.svelte"),
|
||||
}, {
|
||||
path: "/login",
|
||||
title: "Login",
|
||||
component: LoginRouter,
|
||||
component: () => import("login/Router.svelte"),
|
||||
}, {
|
||||
path: "/register",
|
||||
title: "Register",
|
||||
component: LoginRouter,
|
||||
component: () => import("login/Router.svelte"),
|
||||
}, {
|
||||
path: "/user",
|
||||
prefix: "/user/",
|
||||
title: "Dashboard",
|
||||
component: HomeRouter,
|
||||
component: () => import("user_home/Router.svelte"),
|
||||
login: true,
|
||||
}, {
|
||||
path: "/d/me",
|
||||
prefix: "/d/",
|
||||
title: "Filesystem",
|
||||
component: Filesystem,
|
||||
component: () => import("filesystem/Filesystem.svelte"),
|
||||
footer: false,
|
||||
custom_breadcrumbs: true,
|
||||
}, {
|
||||
path: "/admin",
|
||||
prefix: "/admin/",
|
||||
title: "Admin Panel",
|
||||
component: AdminRouter,
|
||||
component: () => import("admin_panel/Router.svelte"),
|
||||
login: true,
|
||||
}, {
|
||||
path: "/speedtest",
|
||||
title: "Speedtest",
|
||||
component: SpeedtestPage,
|
||||
}, {
|
||||
path: "/appearance",
|
||||
title: "Appearance",
|
||||
component: Appearance,
|
||||
component: () => import("speedtest/SpeedtestPage.svelte"),
|
||||
},
|
||||
]
|
||||
|
||||
@@ -61,6 +53,12 @@ onMount(async () => {
|
||||
})
|
||||
|
||||
let current_page: Tab = $state(null)
|
||||
let Page: Component = $state(null)
|
||||
|
||||
// Every navigation gets a number. A navigation which is still loading when a
|
||||
// newer one starts is abandoned, else it would replace the newer page when it
|
||||
// finishes
|
||||
let navigation_id = 0
|
||||
|
||||
// find_page resolves a URL path to the page which renders it. It returns null
|
||||
// when no page matches, in which case the browser has to handle the navigation
|
||||
@@ -80,7 +78,8 @@ const find_page = (pathname: string): Tab => {
|
||||
|
||||
// href can be a full URL or a path, and may contain a query string and hash.
|
||||
// Those are not used for routing, but they do need to survive the navigation
|
||||
const load_page = async (href: string, history: boolean): Promise<boolean> => {
|
||||
const load_page = async (href: string, history: boolean) => {
|
||||
const id = ++navigation_id
|
||||
const url = new URL(href, window.location.href)
|
||||
console.debug(
|
||||
"Page router: Navigating to page", url.pathname,
|
||||
@@ -93,11 +92,14 @@ const load_page = async (href: string, history: boolean): Promise<boolean> => {
|
||||
current_page = {
|
||||
path: "",
|
||||
title: "Not Found",
|
||||
component: NotFound,
|
||||
}
|
||||
return false
|
||||
Page = NotFound
|
||||
return
|
||||
}
|
||||
|
||||
// Download the page while we check the login
|
||||
const component = loading_run(page.component)
|
||||
|
||||
let user: User
|
||||
try {
|
||||
user = await get_user()
|
||||
@@ -116,6 +118,22 @@ const load_page = async (href: string, history: boolean): Promise<boolean> => {
|
||||
)
|
||||
}
|
||||
|
||||
let new_page: Component
|
||||
try {
|
||||
new_page = (await component).default
|
||||
} catch (err) {
|
||||
// An update deletes the code of the previous version from the server.
|
||||
// Tabs which were opened before the update need a full page load
|
||||
if (current_page === null) {
|
||||
throw err
|
||||
}
|
||||
window.location.assign(url)
|
||||
return
|
||||
}
|
||||
if (id !== navigation_id) {
|
||||
return
|
||||
}
|
||||
|
||||
window.document.title = page.title+" / Nova"
|
||||
|
||||
// The address bar has to be updated before the page is mounted. Pages read
|
||||
@@ -128,6 +146,7 @@ const load_page = async (href: string, history: boolean): Promise<boolean> => {
|
||||
}
|
||||
|
||||
current_page = page
|
||||
Page = new_page
|
||||
|
||||
if (current_page.custom_breadcrumbs !== true) {
|
||||
breadcrumbs_store.set(breadcrumbs)
|
||||
@@ -140,8 +159,6 @@ const load_page = async (href: string, history: boolean): Promise<boolean> => {
|
||||
tick().then(() => {
|
||||
current_page_store.set(current_page)
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const click = (e: MouseEvent) => {
|
||||
@@ -164,24 +181,23 @@ const click = (e: MouseEvent) => {
|
||||
}
|
||||
|
||||
// Other hosts, and protocols like mailto: and magnet:, have no host match
|
||||
const url = URL.parse(origin.href)
|
||||
if (url === null || url.host !== window.location.host) {
|
||||
if (origin.host !== window.location.host) {
|
||||
return
|
||||
}
|
||||
|
||||
// In-page anchors are left to the browser, it knows how to scroll to them
|
||||
if (url.pathname === window.location.pathname && url.hash !== "") {
|
||||
if (origin.pathname === window.location.pathname && origin.hash !== "") {
|
||||
return
|
||||
}
|
||||
|
||||
// Paths without a page of their own are served by the backend, like the API
|
||||
// and file downloads. Loading them here would replace the page the user is
|
||||
// looking at with a Not Found error while the browser navigates away
|
||||
if (find_page(url.pathname) === null) {
|
||||
if (find_page(origin.pathname) === null) {
|
||||
return
|
||||
}
|
||||
|
||||
console.log("Caught link click to", url.pathname)
|
||||
console.log("Caught link click to", origin.pathname)
|
||||
|
||||
// The event has to be cancelled before the first await, after that the
|
||||
// browser has already committed to the navigation
|
||||
@@ -202,7 +218,7 @@ const popstate = (e: PopStateEvent) => {
|
||||
<svelte:window onpopstate={popstate}/>
|
||||
|
||||
{#if current_page !== null}
|
||||
<current_page.component />
|
||||
<Page />
|
||||
|
||||
{#if current_page.footer !== false}
|
||||
<Footer/>
|
||||
|
||||
Reference in New Issue
Block a user