mirror of
https://github.com/Radiquum/AniX.git
synced 2025-04-06 00:04:39 +00:00
Merge pull request #3 from Radiquum/feat__Saving-of-the-preferred-voiceover-and-player
Feat: Merge PR #2 saving of the preferred voiceover and player to the V3 branch
This commit is contained in:
commit
d46075c88c
2 changed files with 175 additions and 73 deletions
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import { Spinner } from "#/components/Spinner/Spinner";
|
import { Spinner } from "#/components/Spinner/Spinner";
|
||||||
import { useUserStore } from "#/store/auth";
|
import { useUserStore } from "#/store/auth";
|
||||||
|
import { useUserPlayerPreferencesStore } from "#/store/player";
|
||||||
import { Card, Dropdown, Button } from "flowbite-react";
|
import { Card, Dropdown, Button } from "flowbite-react";
|
||||||
import { ENDPOINTS } from "#/api/config";
|
import { ENDPOINTS } from "#/api/config";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
|
@ -38,27 +39,14 @@ const getAnonEpisodesWatched = (
|
||||||
) => {
|
) => {
|
||||||
const anonEpisodesWatched =
|
const anonEpisodesWatched =
|
||||||
JSON.parse(localStorage.getItem("anonEpisodesWatched")) || {};
|
JSON.parse(localStorage.getItem("anonEpisodesWatched")) || {};
|
||||||
console.log("anonEpisodesWatched", anonEpisodesWatched);
|
|
||||||
|
|
||||||
if (!anonEpisodesWatched.hasOwnProperty(Release)) {
|
if (!anonEpisodesWatched.hasOwnProperty(Release)) {
|
||||||
console.log(
|
|
||||||
`no key found for R: ${Release}`,
|
|
||||||
anonEpisodesWatched.hasOwnProperty(Release)
|
|
||||||
);
|
|
||||||
anonEpisodesWatched[Release] = {};
|
anonEpisodesWatched[Release] = {};
|
||||||
}
|
}
|
||||||
if (!anonEpisodesWatched[Release].hasOwnProperty(Source)) {
|
if (!anonEpisodesWatched[Release].hasOwnProperty(Source)) {
|
||||||
console.log(
|
|
||||||
`no key found for R: ${Release} S: ${Source}`,
|
|
||||||
anonEpisodesWatched.hasOwnProperty(Release)
|
|
||||||
);
|
|
||||||
anonEpisodesWatched[Release][Source] = {};
|
anonEpisodesWatched[Release][Source] = {};
|
||||||
}
|
}
|
||||||
if (!anonEpisodesWatched[Release][Source].hasOwnProperty(Voiceover)) {
|
if (!anonEpisodesWatched[Release][Source].hasOwnProperty(Voiceover)) {
|
||||||
console.log(
|
|
||||||
`no key found for R: ${Release} S: ${Source} V: ${Voiceover}`,
|
|
||||||
anonEpisodesWatched.hasOwnProperty(Release)
|
|
||||||
);
|
|
||||||
anonEpisodesWatched[Release][Source][Voiceover] = {};
|
anonEpisodesWatched[Release][Source][Voiceover] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,33 +63,17 @@ const getAnonCurrentEpisodeWatched = (
|
||||||
JSON.parse(localStorage.getItem("anonEpisodesWatched")) || {};
|
JSON.parse(localStorage.getItem("anonEpisodesWatched")) || {};
|
||||||
|
|
||||||
if (!anonEpisodesWatched.hasOwnProperty(Release)) {
|
if (!anonEpisodesWatched.hasOwnProperty(Release)) {
|
||||||
console.log(
|
|
||||||
`no key found for R: ${Release}`,
|
|
||||||
anonEpisodesWatched.hasOwnProperty(Release)
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!anonEpisodesWatched[Release].hasOwnProperty(Source)) {
|
if (!anonEpisodesWatched[Release].hasOwnProperty(Source)) {
|
||||||
console.log(
|
|
||||||
`no key found for R: ${Release} S: ${Source}`,
|
|
||||||
anonEpisodesWatched.hasOwnProperty(Release)
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!anonEpisodesWatched[Release][Source].hasOwnProperty(Voiceover)) {
|
if (!anonEpisodesWatched[Release][Source].hasOwnProperty(Voiceover)) {
|
||||||
console.log(
|
|
||||||
`no key found for R: ${Release} S: ${Source} V: ${Voiceover}`,
|
|
||||||
anonEpisodesWatched.hasOwnProperty(Release)
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
!anonEpisodesWatched[Release][Source][Voiceover].hasOwnProperty(Episode)
|
!anonEpisodesWatched[Release][Source][Voiceover].hasOwnProperty(Episode)
|
||||||
) {
|
) {
|
||||||
console.log(
|
|
||||||
`no key found for R: ${Release} S: ${Source} V: ${Voiceover} E: ${Episode}`,
|
|
||||||
anonEpisodesWatched.hasOwnProperty(Release)
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,65 +111,148 @@ const saveAnonEpisodeWatched = (
|
||||||
|
|
||||||
export const ReleasePlayer = (props: { id: number }) => {
|
export const ReleasePlayer = (props: { id: number }) => {
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
const preferredVoiceoverStore = useUserPlayerPreferencesStore();
|
||||||
|
const storedPreferredVoiceover =
|
||||||
|
preferredVoiceoverStore.getPreferredVoiceover(props.id);
|
||||||
|
const storedPreferredPlayer = preferredVoiceoverStore.getPreferredPlayer(
|
||||||
|
props.id
|
||||||
|
);
|
||||||
const [voiceoverInfo, setVoiceoverInfo] = useState(null);
|
const [voiceoverInfo, setVoiceoverInfo] = useState(null);
|
||||||
const [selectedVoiceover, setSelectedVoiceover] = useState(null);
|
const [selectedVoiceover, setSelectedVoiceover] = useState(null);
|
||||||
const [sourcesInfo, setSourcesInfo] = useState(null);
|
const [sourcesInfo, setSourcesInfo] = useState(null);
|
||||||
const [selectedSource, setSelectedSource] = useState(null);
|
const [selectedSource, setSelectedSource] = useState(null);
|
||||||
const [episodeInfo, setEpisodeInfo] = useState(null);
|
const [episodeInfo, setEpisodeInfo] = useState(null);
|
||||||
const [selectedEpisode, setSelectedEpisode] = useState(null);
|
const [selectedEpisode, setSelectedEpisode] = useState(null);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
const setSelectedVoiceoverAndSaveAsPreferred = (voiceover: any) => {
|
||||||
|
setSelectedVoiceover(voiceover);
|
||||||
|
preferredVoiceoverStore.setPreferredVoiceover(props.id, voiceover.name);
|
||||||
|
};
|
||||||
|
const setSelectedPlayerAndSaveAsPreferred = (player: any) => {
|
||||||
|
setSelectedSource(player);
|
||||||
|
preferredVoiceoverStore.setPreferredPlayer(props.id, player.name);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
function _setError(error: string) {
|
||||||
async function _fetchInfo() {
|
setVoiceoverInfo(null);
|
||||||
const voiceover = await _fetch(
|
setSelectedVoiceover(null);
|
||||||
`${ENDPOINTS.release.episode}/${props.id}`
|
setSourcesInfo(null);
|
||||||
);
|
setSelectedSource(null);
|
||||||
setVoiceoverInfo(voiceover.types);
|
setEpisodeInfo(null);
|
||||||
setSelectedVoiceover(voiceover.types[0]);
|
setSelectedEpisode(null);
|
||||||
|
setError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _fetchInfo(
|
||||||
|
url: string,
|
||||||
|
type: "voiceover" | "sources" | "episodes"
|
||||||
|
) {
|
||||||
|
let data: any = {};
|
||||||
|
data = await fetch(url)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.ok) {
|
||||||
|
return res.json();
|
||||||
|
} else {
|
||||||
|
throw new Error("Error fetching data");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
_setError("Ошибка получение ответа от сервера");
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data && Object.keys(data).length == 0) {
|
||||||
|
_setError("Ошибка получение данных с сервера");
|
||||||
}
|
}
|
||||||
_fetchInfo();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
if (type == "voiceover") {
|
||||||
async function _fetchInfo() {
|
if (data.types.length > 0) {
|
||||||
const sources = await _fetch(
|
setVoiceoverInfo(data.types);
|
||||||
`${ENDPOINTS.release.episode}/${props.id}/${selectedVoiceover.id}`
|
const preferredVoiceover =
|
||||||
);
|
data.types.find(
|
||||||
setSourcesInfo(sources.sources);
|
(voiceover: any) => voiceover.name === storedPreferredVoiceover
|
||||||
setSelectedSource(sources.sources[0]);
|
) || data.types[0];
|
||||||
}
|
setSelectedVoiceover(preferredVoiceover);
|
||||||
if (selectedVoiceover) {
|
} else {
|
||||||
_fetchInfo();
|
_setError("Ошибка получения озвучек");
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
} else if (type == "sources") {
|
||||||
}, [selectedVoiceover]);
|
if (data.sources.length > 0) {
|
||||||
|
setSourcesInfo(data.sources);
|
||||||
useEffect(() => {
|
const preferredSource =
|
||||||
async function _fetchInfo(url: string) {
|
data.sources.find(
|
||||||
const episodes = await _fetch(url);
|
(source: any) => source.name === storedPreferredPlayer
|
||||||
|
) || data.sources[0];
|
||||||
if (episodes.episodes.length === 0) {
|
setSelectedSource(preferredSource);
|
||||||
|
} else {
|
||||||
|
_setError("Ошибка получения источников");
|
||||||
|
}
|
||||||
|
} else if (type == "episodes") {
|
||||||
|
if (data.episodes.length === 0) {
|
||||||
const remSources = sourcesInfo.filter(
|
const remSources = sourcesInfo.filter(
|
||||||
(source) => source.id !== selectedSource.id
|
(source) => source.id !== selectedSource.id
|
||||||
);
|
);
|
||||||
setSourcesInfo(remSources);
|
setSourcesInfo(remSources);
|
||||||
setSelectedSource(remSources[0]);
|
setSelectedSource(remSources[0]);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
} else if (data.episodes.length > 0) {
|
||||||
|
setEpisodeInfo(data.episodes);
|
||||||
|
setSelectedEpisode(data.episodes[0]);
|
||||||
|
|
||||||
setEpisodeInfo(episodes.episodes);
|
const WatchedEpisodes = getAnonEpisodesWatched(
|
||||||
setSelectedEpisode(episodes.episodes[0]);
|
props.id,
|
||||||
|
selectedSource.id,
|
||||||
|
selectedVoiceover.id
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
Object.keys(
|
||||||
|
WatchedEpisodes[props.id][selectedSource.id][selectedVoiceover.id]
|
||||||
|
).length != 0
|
||||||
|
) {
|
||||||
|
const watchedEpisodes =
|
||||||
|
WatchedEpisodes[props.id][selectedSource.id][selectedVoiceover.id];
|
||||||
|
let lastWatchedEpisode = Number(Object.keys(watchedEpisodes).pop());
|
||||||
|
if (
|
||||||
|
!["Sibnet", "Sibnet (не работает)"].includes(selectedSource.name)
|
||||||
|
) {
|
||||||
|
lastWatchedEpisode = Number(lastWatchedEpisode) - 1;
|
||||||
|
}
|
||||||
|
setSelectedEpisode(data.episodes[lastWatchedEpisode]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_setError("Ошибка получения эпизодов");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_setError("Неизвестный тип запроса");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
_fetchInfo(`${ENDPOINTS.release.episode}/${props.id}`, "voiceover");
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [props.id]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedVoiceover) {
|
||||||
|
_fetchInfo(
|
||||||
|
`${ENDPOINTS.release.episode}/${props.id}/${selectedVoiceover.id}`,
|
||||||
|
"sources"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [props.id, selectedVoiceover]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
if (selectedSource) {
|
if (selectedSource) {
|
||||||
let url = `${ENDPOINTS.release.episode}/${props.id}/${selectedVoiceover.id}/${selectedSource.id}`;
|
let url = `${ENDPOINTS.release.episode}/${props.id}/${selectedVoiceover.id}/${selectedSource.id}`;
|
||||||
if (userStore.token) {
|
if (userStore.token) {
|
||||||
url = `${ENDPOINTS.release.episode}/${props.id}/${selectedVoiceover.id}/${selectedSource.id}?token=${userStore.token}`;
|
url = `${ENDPOINTS.release.episode}/${props.id}/${selectedVoiceover.id}/${selectedSource.id}?token=${userStore.token}`;
|
||||||
}
|
}
|
||||||
_fetchInfo(url);
|
_fetchInfo(url, "episodes");
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [selectedSource, userStore.token]);
|
}, [props.id, selectedSource, userStore.token]);
|
||||||
|
|
||||||
async function _addToHistory(episode: any) {
|
async function _addToHistory(episode: any) {
|
||||||
if (episode && userStore.token) {
|
if (episode && userStore.token) {
|
||||||
|
@ -214,7 +269,7 @@ export const ReleasePlayer = (props: { id: number }) => {
|
||||||
<Card>
|
<Card>
|
||||||
{!voiceoverInfo || !sourcesInfo || !episodeInfo ? (
|
{!voiceoverInfo || !sourcesInfo || !episodeInfo ? (
|
||||||
<div className="flex items-center justify-center w-full aspect-video">
|
<div className="flex items-center justify-center w-full aspect-video">
|
||||||
<Spinner />
|
{!error ? <Spinner /> : <p>{error}</p>}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
@ -227,7 +282,9 @@ export const ReleasePlayer = (props: { id: number }) => {
|
||||||
{voiceoverInfo.map((voiceover: any) => (
|
{voiceoverInfo.map((voiceover: any) => (
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
key={`voiceover_${voiceover.id}`}
|
key={`voiceover_${voiceover.id}`}
|
||||||
onClick={() => setSelectedVoiceover(voiceover)}
|
onClick={() =>
|
||||||
|
setSelectedVoiceoverAndSaveAsPreferred(voiceover)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{voiceover.name}
|
{voiceover.name}
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
|
@ -241,7 +298,7 @@ export const ReleasePlayer = (props: { id: number }) => {
|
||||||
{sourcesInfo.map((source: any) => (
|
{sourcesInfo.map((source: any) => (
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
key={`source_${source.id}`}
|
key={`source_${source.id}`}
|
||||||
onClick={() => setSelectedSource(source)}
|
onClick={() => setSelectedPlayerAndSaveAsPreferred(source)}
|
||||||
>
|
>
|
||||||
{source.name}
|
{source.name}
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
|
@ -249,11 +306,15 @@ export const ReleasePlayer = (props: { id: number }) => {
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div className="aspect-video">
|
<div className="aspect-video">
|
||||||
<iframe
|
{selectedEpisode ? (
|
||||||
allowFullScreen={true}
|
<iframe
|
||||||
src={selectedEpisode.url}
|
allowFullScreen={true}
|
||||||
className="w-full h-full rounded-md"
|
src={selectedEpisode.url}
|
||||||
></iframe>
|
className="w-full h-full rounded-md"
|
||||||
|
></iframe>
|
||||||
|
) : (
|
||||||
|
<p>Ошибка загрузки плеера</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Swiper
|
<Swiper
|
||||||
|
@ -301,7 +362,9 @@ export const ReleasePlayer = (props: { id: number }) => {
|
||||||
{episode.name
|
{episode.name
|
||||||
? episode.name
|
? episode.name
|
||||||
: `${
|
: `${
|
||||||
selectedSource.name != "Sibnet"
|
!["Sibnet", "Sibnet (не работает)"].includes(
|
||||||
|
selectedSource.name
|
||||||
|
)
|
||||||
? episode.position
|
? episode.position
|
||||||
: episode.position + 1
|
: episode.position + 1
|
||||||
} серия`}
|
} серия`}
|
||||||
|
|
39
app/store/player.ts
Normal file
39
app/store/player.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
"use client";
|
||||||
|
import { create } from "zustand";
|
||||||
|
import { persist } from "zustand/middleware";
|
||||||
|
|
||||||
|
interface userPlayerPreferencesState {
|
||||||
|
voiceover: Record<number, string>;
|
||||||
|
player: Record<number, string>;
|
||||||
|
getPreferredVoiceover: (id: number) => string | undefined;
|
||||||
|
setPreferredVoiceover: (id: number, voiceover: string) => void;
|
||||||
|
getPreferredPlayer: (id: number) => string | undefined;
|
||||||
|
setPreferredPlayer: (id: number, player: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useUserPlayerPreferencesStore =
|
||||||
|
create<userPlayerPreferencesState>()(
|
||||||
|
persist(
|
||||||
|
(set, get) => ({
|
||||||
|
voiceover: {},
|
||||||
|
player: {},
|
||||||
|
getPreferredVoiceover: (id: number) => get().voiceover[id],
|
||||||
|
setPreferredVoiceover: (id: number, voiceover: string) => {
|
||||||
|
set({
|
||||||
|
voiceover: { ...get().voiceover, [id]: voiceover },
|
||||||
|
player: get().player,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getPreferredPlayer: (id: number) => get().player[id],
|
||||||
|
setPreferredPlayer: (id: number, player: string) => {
|
||||||
|
set({
|
||||||
|
player: { ...get().player, [id]: player },
|
||||||
|
voiceover: get().voiceover,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "player-preferences",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
Loading…
Add table
Reference in a new issue