-
+
+
Torrent Search
-
-
-
- Search
-
+
+
+ Search
+
-
+
-
-
+
diff --git a/src/routes.ts b/src/routes.ts
index 649392f..3bc48af 100644
--- a/src/routes.ts
+++ b/src/routes.ts
@@ -4,6 +4,7 @@ import type { RouteRecordRaw, RouteLocationNormalized } from "vue-router";
/* eslint-disable-next-line import-x/no-cycle */
import store from "./store";
import { usePlexAuth } from "./composables/usePlexAuth";
+
const { getPlexAuthCookie } = usePlexAuth();
declare global {
@@ -58,8 +59,7 @@ const routes: RouteRecordRaw[] = [
},
{
name: "signin",
- path: "/signin",
- alias: "/login",
+ path: "/login",
component: () => import("./pages/SigninPage.vue")
},
{
@@ -76,8 +76,18 @@ const routes: RouteRecordRaw[] = [
// }
// },
{
- name: "404",
- path: "/404",
+ name: "password-gen",
+ path: "/password",
+ component: () => import("./pages/GenPasswordPage.vue")
+ },
+ {
+ name: "missing-plex-auth",
+ path: "/missing/plex",
+ component: () => import("./pages/MissingPlexAuthPage.vue")
+ },
+ {
+ path: "/:pathMatch(.*)*",
+ name: "NotFound",
component: () => import("./pages/404Page.vue")
}
// {
@@ -102,7 +112,7 @@ const hasPlexAccount = () => {
// Check Vuex store first
if (store.getters["user/plexUserId"] !== null) return true;
- // Fallback to localStorage/cookie for page refreshes
+ // Fallback to localStorage
const authToken = getPlexAuthCookie();
return !!authToken;
};
@@ -120,15 +130,14 @@ router.beforeEach(
// send user to signin page.
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!loggedIn()) {
- next({ path: "/signin" });
+ next({ path: "/login" });
}
}
if (to.matched.some(record => record.meta.requiresPlexAccount)) {
if (!hasPlexAccount()) {
next({
- path: "/settings",
- query: { missingPlexAccount: true }
+ path: "/missing/plex"
});
}
}
diff --git a/src/scss/shared-auth.scss b/src/scss/shared-auth.scss
new file mode 100644
index 0000000..e4d7318
--- /dev/null
+++ b/src/scss/shared-auth.scss
@@ -0,0 +1,100 @@
+// Shared styles for authentication pages (signin, register)
+@import "variables";
+@import "media-queries";
+
+// Base auth page layout
+.auth-page {
+ padding: 3rem;
+ max-width: 100%;
+
+ @include mobile-only {
+ padding: 0.75rem;
+ }
+}
+
+.auth-content {
+ max-width: 600px;
+
+ @include mobile-only {
+ max-width: 100%;
+ }
+
+ &--wide {
+ max-width: 700px;
+ }
+}
+
+.auth-header {
+ margin-bottom: 2.5rem;
+
+ @include mobile-only {
+ margin-bottom: 2rem;
+ }
+}
+
+.auth-title {
+ margin: 0 0 0.75rem 0;
+ font-size: 2.5rem;
+ font-weight: 600;
+ color: $text-color;
+ line-height: 1.2;
+
+ @include mobile-only {
+ font-size: 2rem;
+ }
+}
+
+.auth-subtitle {
+ margin: 0;
+ font-size: 1.1rem;
+ font-weight: 300;
+ color: var(--text-color-60);
+ line-height: 1.5;
+
+ @include mobile-only {
+ font-size: 1rem;
+ }
+}
+
+.auth-form {
+ display: flex;
+ flex-direction: column;
+ gap: 1.25rem;
+ margin-bottom: 2rem;
+}
+
+.auth-button {
+ margin-top: 0.5rem;
+ max-width: 200px;
+
+ @include mobile-only {
+ max-width: 100%;
+ }
+}
+
+.auth-footer {
+ padding-top: 2rem;
+ border-top: 1px solid var(--text-color-10);
+}
+
+.auth-footer-text {
+ margin: 0;
+ font-size: 1rem;
+ color: var(--text-color-60);
+
+ @include mobile-only {
+ font-size: 0.95rem;
+ }
+}
+
+.auth-link {
+ color: var(--highlight-color);
+ text-decoration: none;
+ font-weight: 500;
+ transition: opacity 0.2s;
+
+ &:hover {
+ opacity: 0.8;
+ text-decoration: underline;
+ }
+}
diff --git a/src/scss/variables.scss b/src/scss/variables.scss
index b4dfdbe..e27cd91 100644
--- a/src/scss/variables.scss
+++ b/src/scss/variables.scss
@@ -114,10 +114,35 @@ $color-error: var(--color-error) !default;
$color-error-highlight: var(--color-error-highlight) !default;
.halloween {
- --text-color: #6a318c;
- --text-color-secondary: #fb5a33;
- --background-color: #80c350;
- --background-color-secondary: #ff9234;
+ --text-color: #f5f5f5;
+ --text-color-90: rgba(245, 245, 245, 0.9);
+ --text-color-70: rgba(245, 245, 245, 0.7);
+ --text-color-50: rgba(245, 245, 245, 0.5);
+ --text-color-10: rgba(245, 245, 245, 0.1);
+ --text-color-5: rgba(245, 245, 245, 0.05);
+ --text-color-secondary: #ff6600;
+ --background-color: #1a0e2e;
+ --background-color-secondary: #2d1b3d;
+ --background-ui: #3d2550;
+ --background-95: rgba(26, 14, 46, 0.95);
+ --background-90: rgba(26, 14, 46, 0.9);
+ --background-80: rgba(26, 14, 46, 0.8);
+ --background-70: rgba(45, 27, 61, 0.7);
+ --background-40: rgba(61, 37, 80, 0.4);
+ --background-0: rgba(26, 14, 46, 0);
+ --highlight-color: #ff6600;
+ --color-green: #ff6600;
+ --color-green-90: rgba(255, 102, 0, 0.9);
+ --color-green-70: rgba(255, 102, 0, 0.7);
+ --table-background-color: #0d0618;
+ --table-header-text-color: #ff6600;
+ --color-success: rgba(138, 43, 226, 0.8);
+ --color-success-text: #f5f5f5;
+ --color-success-highlight: #8a2be2;
+ --color-warning: rgba(255, 140, 0, 0.7);
+ --color-warning-highlight: #ff8c00;
+ --color-error: rgba(220, 20, 60, 0.8);
+ --color-error-highlight: #dc143c;
}
.dark {
@@ -158,3 +183,98 @@ $color-error-highlight: var(--color-error-highlight) !default;
--table-background-color: #081c24;
--table-header-text-color: white;
}
+
+.ocean {
+ --text-color: #e0f7ff;
+ --text-color-90: rgba(224, 247, 255, 0.9);
+ --text-color-70: rgba(224, 247, 255, 0.7);
+ --text-color-50: rgba(224, 247, 255, 0.5);
+ --text-color-10: rgba(224, 247, 255, 0.1);
+ --text-color-5: rgba(224, 247, 255, 0.05);
+ --text-color-secondary: #00d4ff;
+ --background-color: #0f2027;
+ --background-color-secondary: #203a43;
+ --background-ui: #2c5364;
+ --background-95: rgba(15, 32, 39, 0.95);
+ --background-90: rgba(15, 32, 39, 0.9);
+ --background-80: rgba(15, 32, 39, 0.8);
+ --background-70: rgba(32, 58, 67, 0.7);
+ --background-40: rgba(44, 83, 100, 0.4);
+ --background-0: rgba(15, 32, 39, 0);
+ --highlight-color: #00d4ff;
+ --color-green: #00d4ff;
+ --color-green-90: rgba(0, 212, 255, 0.9);
+ --color-green-70: rgba(0, 212, 255, 0.7);
+ --table-background-color: #0a1519;
+ --table-header-text-color: #00d4ff;
+}
+
+.nordic {
+ --text-color: #2c3e2e;
+ --text-color-90: rgba(44, 62, 46, 0.9);
+ --text-color-70: rgba(44, 62, 46, 0.7);
+ --text-color-50: rgba(44, 62, 46, 0.5);
+ --text-color-10: rgba(44, 62, 46, 0.1);
+ --text-color-5: rgba(44, 62, 46, 0.05);
+ --text-color-secondary: #5a8a68;
+ --background-color: #f5f0e8;
+ --background-color-secondary: #fffef9;
+ --background-ui: #e8dfc8;
+ --background-95: rgba(245, 240, 232, 0.95);
+ --background-90: rgba(245, 240, 232, 0.9);
+ --background-80: rgba(245, 240, 232, 0.8);
+ --background-70: rgba(232, 223, 200, 0.7);
+ --background-40: rgba(232, 223, 200, 0.4);
+ --background-0: rgba(245, 240, 232, 0);
+ --highlight-color: #3d6e4e;
+ --color-green: #3d6e4e;
+ --color-green-90: rgba(61, 110, 78, 0.95);
+ --color-green-70: rgba(61, 110, 78, 0.7);
+ --table-background-color: #6d5a47;
+ --table-header-text-color: #fffef9;
+ --color-success: rgba(61, 110, 78, 0.85);
+ --color-success-text: #fffef9;
+ --color-success-highlight: #2d5e3e;
+ --color-warning: rgba(184, 134, 11, 0.75);
+ --color-warning-highlight: #d4a017;
+ --color-error: rgba(165, 42, 42, 0.85);
+ --color-error-highlight: #a52a2a;
+ --background-nav-logo: #2c3e2e;
+ --white: #fff;
+ --white-70: rgba(255, 255, 255, 0.7);
+}
+
+.seed {
+ --text-color: #fcfcf7;
+ --text-color-90: rgba(252, 252, 247, 0.9);
+ --text-color-70: rgba(252, 252, 247, 0.7);
+ --text-color-50: rgba(252, 252, 247, 0.5);
+ --text-color-10: rgba(252, 252, 247, 0.1);
+ --text-color-5: rgba(252, 252, 247, 0.05);
+ --text-color-secondary: #e9f0ca;
+ --background-color: #1c3a13;
+ --background-color-secondary: #334e2b;
+ --background-ui: #45663c;
+ --background-95: rgba(28, 58, 19, 0.95);
+ --background-90: rgba(28, 58, 19, 0.9);
+ --background-80: rgba(28, 58, 19, 0.8);
+ --background-70: rgba(51, 78, 43, 0.7);
+ --background-40: rgba(69, 102, 60, 0.4);
+ --background-0: rgba(28, 58, 19, 0);
+ --highlight-color: #e9f0ca;
+ --color-green: #e9f0ca;
+ --color-green-90: rgba(233, 240, 202, 0.9);
+ --color-green-70: rgba(233, 240, 202, 0.7);
+ --table-background-color: #142f0c;
+ --table-header-text-color: #e9f0ca;
+ --color-success: rgba(208, 217, 185, 0.85);
+ --color-success-text: #1c3a13;
+ --color-success-highlight: #d0d9b9;
+ --color-warning: rgba(233, 240, 202, 0.75);
+ --color-warning-highlight: #e9f0ca;
+ --color-error: rgba(185, 99, 94, 0.85);
+ --color-error-highlight: #b9635e;
+ --background-nav-logo: #fcfcf7;
+ --white: #fcfcf7;
+ --white-70: rgba(252, 252, 247, 0.7);
+}
diff --git a/src/utils.ts b/src/utils.ts
index 703037d..8d2af7b 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -89,8 +89,9 @@ export function setUrlQueryParameter(parameter: string, value: string): void {
const params = new URLSearchParams();
params.append(parameter, value);
- const url = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""
- }${window.location.pathname}${params.toString().length ? `?${params}` : ""}`;
+ const url = `${window.location.protocol}//${window.location.hostname}${
+ window.location.port ? `:${window.location.port}` : ""
+ }${window.location.pathname}${params.toString().length ? `?${params}` : ""}`;
window.history.pushState({}, "search", url);
}
@@ -141,5 +142,5 @@ export function formatBytes(bytes: number): string {
const k = 1024;
const sizes = ["Bytes", "KB", "MB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
- return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + " " + sizes[i];
+ return `${Math.round((bytes / k ** i) * 100) / 100} ${sizes[i]}`;
}