diff --git a/.vscode/settings.json b/.vscode/settings.json
index 279011fe..2f5fdb18 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -4,5 +4,8 @@
"eslint.format.enable": true,
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[typescriptreact]": {
+ "editor.defaultFormatter": "ms-vsliveshare.vsliveshare"
}
-}
+}
\ No newline at end of file
diff --git a/src/components/player/atoms/Settings.tsx b/src/components/player/atoms/Settings.tsx
index 44126ebe..e2ca4a9c 100644
--- a/src/components/player/atoms/Settings.tsx
+++ b/src/components/player/atoms/Settings.tsx
@@ -1,3 +1,4 @@
+import classNames from "classnames";
import { useCallback, useEffect, useState } from "react";
import { Toggle } from "@/components/buttons/Toggle";
@@ -93,6 +94,31 @@ function QualityView({ id }: { id: string }) {
);
}
+function ColorOption(props: {
+ color: string;
+ active?: boolean;
+ onClick: () => void;
+}) {
+ return (
+
+
+ {props.active ? (
+
+ ) : null}
+
+
+ );
+}
+
function CaptionSettingsView({ id }: { id: string }) {
const router = useOverlayRouter(id);
@@ -102,12 +128,32 @@ function CaptionSettingsView({ id }: { id: string }) {
Custom captions
- Hello!
+
+
Color
+
+ {}} color="#FFFFFF" active />
+ {}} color="#80B1FA" />
+ {}} color="#E2E535" />
+
+
>
);
}
+function CaptionsView({ id }: { id: string }) {
+ const router = useOverlayRouter(id);
+
+ return (
+ <>
+ router.navigate("/captions")}>
+ Captions
+
+ Yee!
+ >
+ );
+}
+
function SettingsOverlay({ id }: { id: string }) {
const router = useOverlayRouter(id);
const currentQuality = usePlayerStore((s) => s.currentQuality);
@@ -165,15 +211,7 @@ function SettingsOverlay({ id }: { id: string }) {
- router.navigate("/")}>
- Captions
-
-
+
diff --git a/src/components/player/internals/ContextUtils.tsx b/src/components/player/internals/ContextUtils.tsx
index 71a7683b..bd5790e7 100644
--- a/src/components/player/internals/ContextUtils.tsx
+++ b/src/components/player/internals/ContextUtils.tsx
@@ -154,18 +154,23 @@ function Anchor(props: { children: React.ReactNode; onClick: () => void }) {
);
}
+function FieldTitle(props: { children: React.ReactNode }) {
+ return {props.children}
;
+}
+
export const Context = {
- Card,
CardWithScrollable,
- Title,
SectionTitle,
- BackLink,
- Section,
- Link,
- LinkTitle,
LinkChevron,
IconButton,
- Divider,
+ FieldTitle,
SmallText,
+ BackLink,
+ LinkTitle,
+ Section,
+ Divider,
Anchor,
+ Title,
+ Link,
+ Card,
};
diff --git a/src/pages/parts/home/BookmarksPart.tsx b/src/pages/parts/home/BookmarksPart.tsx
index 1a7f5671..c75b374d 100644
--- a/src/pages/parts/home/BookmarksPart.tsx
+++ b/src/pages/parts/home/BookmarksPart.tsx
@@ -8,26 +8,38 @@ import { SectionHeading } from "@/components/layout/SectionHeading";
import { MediaGrid } from "@/components/media/MediaGrid";
import { WatchedMediaCard } from "@/components/media/WatchedMediaCard";
import { useBookmarkStore } from "@/stores/bookmarks";
+import { useProgressStore } from "@/stores/progress";
import { MediaItem } from "@/utils/mediaTypes";
export function BookmarksPart() {
const { t } = useTranslation();
+ const progressItems = useProgressStore((s) => s.items);
const bookmarks = useBookmarkStore((s) => s.bookmarks);
const removeBookmark = useBookmarkStore((s) => s.removeBookmark);
const [editing, setEditing] = useState(false);
const [gridRef] = useAutoAnimate();
- // TODO sort on last watched
const items = useMemo(() => {
- const output: MediaItem[] = [];
+ let output: MediaItem[] = [];
Object.entries(bookmarks).forEach((entry) => {
output.push({
id: entry[0],
...entry[1],
});
});
+ output = output.sort((a, b) => {
+ const bookmarkA = bookmarks[a.id];
+ const bookmarkB = bookmarks[b.id];
+ const progressA = progressItems[a.id];
+ const progressB = progressItems[b.id];
+
+ const dateA = Math.max(bookmarkA.updatedAt, progressA?.updatedAt ?? 0);
+ const dateB = Math.max(bookmarkB.updatedAt, progressB?.updatedAt ?? 0);
+
+ return dateB - dateA;
+ });
return output;
- }, [bookmarks]);
+ }, [bookmarks, progressItems]);
if (items.length === 0) return null;
diff --git a/src/pages/parts/home/WatchingPart.tsx b/src/pages/parts/home/WatchingPart.tsx
index 99ccf6a4..62daa769 100644
--- a/src/pages/parts/home/WatchingPart.tsx
+++ b/src/pages/parts/home/WatchingPart.tsx
@@ -21,18 +21,19 @@ export function WatchingPart() {
const sortedProgressItems = useMemo(() => {
let output: MediaItem[] = [];
- Object.entries(progressItems).forEach((entry) => {
- output.push({
- id: entry[0],
- ...entry[1],
+ Object.entries(progressItems)
+ .sort((a, b) => b[1].updatedAt - a[1].updatedAt)
+ .forEach((entry) => {
+ output.push({
+ id: entry[0],
+ ...entry[1],
+ });
});
- });
output = output.filter((v) => {
const isBookMarked = !!bookmarks[v.id];
return !isBookMarked;
});
- // TODO sort on last modified date
return output;
}, [progressItems, bookmarks]);
diff --git a/src/stores/bookmarks/index.ts b/src/stores/bookmarks/index.ts
index bd3ac204..96b1931c 100644
--- a/src/stores/bookmarks/index.ts
+++ b/src/stores/bookmarks/index.ts
@@ -9,6 +9,7 @@ export interface BookmarkMediaItem {
year: number;
poster?: string;
type: "show" | "movie";
+ updatedAt: number;
}
export interface ProgressStore {
@@ -34,6 +35,7 @@ export const useBookmarkStore = create(
title: meta.title,
year: meta.releaseYear,
poster: meta.poster,
+ updatedAt: Date.now(),
};
});
},
diff --git a/src/stores/progress/index.ts b/src/stores/progress/index.ts
index 55b66df7..a52cd978 100644
--- a/src/stores/progress/index.ts
+++ b/src/stores/progress/index.ts
@@ -29,6 +29,7 @@ export interface ProgressMediaItem {
poster?: string;
type: "show" | "movie";
progress?: ProgressItem;
+ updatedAt: number;
seasons: Record;
episodes: Record;
}
@@ -61,11 +62,14 @@ export const useProgressStore = create(
type: meta.type,
episodes: {},
seasons: {},
+ updatedAt: 0,
title: meta.title,
year: meta.releaseYear,
poster: meta.poster,
};
const item = s.items[meta.tmdbId];
+ item.updatedAt = Date.now();
+
if (meta.type === "movie") {
if (!item.progress)
item.progress = {
diff --git a/tailwind.config.js b/tailwind.config.js
index 68c60438..2dac6a03 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -26,23 +26,23 @@ module.exports = {
"ash-400": "#3D394D",
"ash-300": "#2C293A",
"ash-200": "#2B2836",
- "ash-100": "#1E1C26"
+ "ash-100": "#1E1C26",
},
/* fonts */
fontFamily: {
- "open-sans": "'Open Sans'"
+ "open-sans": "'Open Sans'",
},
/* animations */
keyframes: {
"loading-pin": {
"0%, 40%, 100%": { height: "0.5em", "background-color": "#282336" },
- "20%": { height: "1em", "background-color": "white" }
- }
+ "20%": { height: "1em", "background-color": "white" },
+ },
},
- animation: { "loading-pin": "loading-pin 1.8s ease-in-out infinite" }
- }
+ animation: { "loading-pin": "loading-pin 1.8s ease-in-out infinite" },
+ },
},
plugins: [
require("tailwind-scrollbar"),
@@ -52,31 +52,31 @@ module.exports = {
colors: {
// Branding
pill: {
- background: "#1C1C36"
+ background: "#1C1C36",
},
// meta data for the theme itself
global: {
accentA: "#505DBD",
- accentB: "#3440A1"
+ accentB: "#3440A1",
},
// light bar
lightBar: {
- light: "#2A2A71"
+ light: "#2A2A71",
},
// Buttons
buttons: {
toggle: "#8D44D6",
- toggleDisabled: "#202836"
+ toggleDisabled: "#202836",
},
// only used for body colors/textures
background: {
main: "#0A0A10",
accentA: "#6E3B80",
- accentB: "#1F1F50"
+ accentB: "#1F1F50",
},
// typography
@@ -85,7 +85,7 @@ module.exports = {
text: "#73739D",
dimmed: "#926CAD",
divider: "#262632",
- secondary: "#64647B"
+ secondary: "#64647B",
},
// search bar
@@ -94,7 +94,7 @@ module.exports = {
focused: "#24243C",
placeholder: "#4A4A71",
icon: "#545476",
- text: "#FFFFFF"
+ text: "#FFFFFF",
},
// media cards
@@ -106,7 +106,7 @@ module.exports = {
barColor: "#4B4B63",
barFillColor: "#BA7FD6",
badge: "#151522",
- badgeText: "#5F5F7A"
+ badgeText: "#5F5F7A",
},
// video player
@@ -118,34 +118,35 @@ module.exports = {
error: "#E44F4F",
success: "#40B44B",
loading: "#B759D8",
- noresult: "#64647B"
+ noresult: "#64647B",
},
progress: {
background: "#8787A8",
preloaded: "#8787A8",
- watched: "#A75FC9"
+ watched: "#A75FC9",
},
audio: {
- set: "#A75FC9"
+ set: "#A75FC9",
},
context: {
background: "#0C1216",
light: "#4D79A8",
border: "#4F5C66",
+ buttonFocus: "#202836",
type: {
main: "#617A8A",
secondary: "#374A56",
- accent: "#A570FA"
- }
- }
- }
- }
- }
- }
- })
- ]
+ accent: "#A570FA",
+ },
+ },
+ },
+ },
+ },
+ },
+ }),
+ ],
};