mirror of
https://github.com/Radiquum/AniX.git
synced 2025-04-06 16:24:40 +00:00
feat(frontend): add a release page
add a video player to a release page without release info with ability to save and view wathed episodes
This commit is contained in:
parent
bbf8fc5436
commit
75dd8d83bd
4 changed files with 187 additions and 27 deletions
|
@ -1,7 +1,9 @@
|
|||
import requests
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Request
|
||||
from modules.proxy import apiRequest
|
||||
from modules.proxy import ENDPOINTS
|
||||
from modules.proxy import USER_AGENT
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
@ -33,40 +35,39 @@ async def GetReleaseVoiceoverPlayer(
|
|||
summary="Get available episodes for selected voiceover and a player of a release",
|
||||
)
|
||||
async def GetReleaseEpisodes(
|
||||
request: Request, release_id: str, voiceover_id: str, source_id: str
|
||||
request: Request,
|
||||
release_id: str,
|
||||
voiceover_id: str,
|
||||
source_id: str,
|
||||
token: str = "",
|
||||
):
|
||||
return await apiRequest(
|
||||
request,
|
||||
ENDPOINTS["release"]["episode"],
|
||||
f"{release_id}/{voiceover_id}/{source_id}",
|
||||
query=f"?token={token}",
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{release_id}/{episode}/markWatched",
|
||||
summary="mark episode of a selected voiceover as watched",
|
||||
"/{release_id}/{source_id}/{episode}/saveToHistory",
|
||||
summary="mark episode of a selected voiceover as watched and save it to watch history",
|
||||
)
|
||||
async def MarkEpisodeAsWatched(
|
||||
request: Request, release_id: str, source_id: str, episode: str, token: str
|
||||
):
|
||||
return await apiRequest(
|
||||
request,
|
||||
ENDPOINTS["statistic"]["markWatched"],
|
||||
f"${release_id}/${source_id}/${episode}",
|
||||
query=f"?token={token}",
|
||||
headers = {
|
||||
"User-Agent": USER_AGENT,
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
}
|
||||
|
||||
requests.get(
|
||||
f"{ENDPOINTS['statistic']['markWatched']}/{release_id}/{source_id}/{episode}?token={token}",
|
||||
headers=headers,
|
||||
)
|
||||
requests.get(
|
||||
f"{ENDPOINTS['statistic']['addHistory']}/{release_id}/{source_id}/{episode}?token={token}",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{release_id}/{episode}/addHistory",
|
||||
summary="add episode of a selected voiceover to history",
|
||||
)
|
||||
async def AddEpisodeToHistory(
|
||||
request: Request, release_id: str, source_id: str, episode: str, token: str
|
||||
):
|
||||
return await apiRequest(
|
||||
request,
|
||||
ENDPOINTS["statistic"]["addHistory"],
|
||||
f"${release_id}/${source_id}/${episode}",
|
||||
query=f"?token={token}",
|
||||
)
|
||||
return {"success"}
|
||||
|
|
|
@ -20,4 +20,5 @@ export const endpoints = {
|
|||
abandoned: `${API_URL}/favorites/abandoned`,
|
||||
},
|
||||
},
|
||||
release: `${API_URL}/release`,
|
||||
};
|
||||
|
|
162
frontend/app/release/[id]/page.js
Normal file
162
frontend/app/release/[id]/page.js
Normal file
|
@ -0,0 +1,162 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { getData } from "@/app/api/api-utils";
|
||||
import { endpoints } from "@/app/api/config";
|
||||
import { useUserStore } from "@/app/store/user-store";
|
||||
import { useSettingsStore } from "@/app/store/settings-store";
|
||||
|
||||
export default function Release(props) {
|
||||
const userStore = useUserStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const [releaseInfo, setReleaseInfo] = useState();
|
||||
const [voiceoverInfo, setVoiceoverInfo] = useState();
|
||||
const [selectedVoiceover, setSelectedVoiceover] = useState();
|
||||
const [sourcesInfo, setSourcesInfo] = useState();
|
||||
const [selectedSources, setSelectedSources] = useState();
|
||||
const [episodeInfo, setEpisodeInfo] = useState();
|
||||
const [selectedEpisode, setSelectedEpisode] = useState();
|
||||
const [episodeURL, setEpisodeURL] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
async function _fetchInfo() {
|
||||
const release = await getData(`${endpoints.release}/${props.params.id}`);
|
||||
const voiceover = await getData(
|
||||
`${endpoints.release}/${props.params.id}/voiceover`,
|
||||
);
|
||||
setReleaseInfo(release);
|
||||
setVoiceoverInfo(voiceover);
|
||||
setSelectedVoiceover(voiceover.types[0].id);
|
||||
}
|
||||
if (props.params.id) {
|
||||
_fetchInfo();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
async function _fetchInfo() {
|
||||
const sources = await getData(
|
||||
`${endpoints.release}/${props.params.id}/${selectedVoiceover}`,
|
||||
);
|
||||
setSourcesInfo(sources);
|
||||
setSelectedSources(sources.sources[0].id);
|
||||
}
|
||||
if (selectedVoiceover) {
|
||||
_fetchInfo();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedVoiceover]);
|
||||
|
||||
useEffect(() => {
|
||||
async function _fetchInfo() {
|
||||
let url = `${endpoints.release}/${props.params.id}/${selectedVoiceover}/${selectedSources}`;
|
||||
if (userStore.token) {
|
||||
url = `${endpoints.release}/${props.params.id}/${selectedVoiceover}/${selectedSources}?token=${userStore.token}`;
|
||||
}
|
||||
|
||||
const episodes = await getData(url);
|
||||
|
||||
setEpisodeInfo(episodes);
|
||||
setSelectedEpisode(episodes.episodes[0].position);
|
||||
setEpisodeURL(episodes.episodes[0].url);
|
||||
}
|
||||
if (selectedSources) {
|
||||
_fetchInfo();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedSources, userStore.token]);
|
||||
|
||||
useEffect(() => {
|
||||
async function _markAsWatched() {
|
||||
const url = `${endpoints.release}/${props.params.id}/${selectedSources}/${selectedEpisode}`;
|
||||
await getData(`${url}/saveToHistory?token=${userStore.token}`);
|
||||
}
|
||||
if (userStore.token && settingsStore.saveToHistory) {
|
||||
_markAsWatched();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedEpisode]);
|
||||
|
||||
return (
|
||||
<article className="fill grid">
|
||||
<iframe
|
||||
src={episodeURL}
|
||||
className="s9"
|
||||
style={{ aspectRatio: "16/9", width: "100%", height: "auto" }}
|
||||
/>
|
||||
<div className="s3">
|
||||
<div className="tabs">
|
||||
<a data-ui="#vo" className="active">
|
||||
озвучка
|
||||
</a>
|
||||
{sourcesInfo && <a data-ui="#src">плеер</a>}
|
||||
</div>
|
||||
<div
|
||||
className="page padding active scroll"
|
||||
style={{ Height: "438px" }}
|
||||
id="vo"
|
||||
>
|
||||
{voiceoverInfo &&
|
||||
voiceoverInfo.types.map((item) => {
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
className={`small responsive ${
|
||||
item.id == selectedVoiceover ? "primary" : "secondary"
|
||||
}`}
|
||||
style={{ marginTop: "8px" }}
|
||||
onClick={() => {
|
||||
setSelectedVoiceover(item.id);
|
||||
}}
|
||||
>
|
||||
{item.name}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{sourcesInfo && (
|
||||
<div className="page center-align padding" id="src">
|
||||
{sourcesInfo.sources.map((item) => {
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
className={`small responsive ${
|
||||
item.id == selectedSources ? "primary" : "secondary"
|
||||
}`}
|
||||
style={{ marginTop: "8px" }}
|
||||
onClick={() => {
|
||||
setSelectedSources(item.id);
|
||||
}}
|
||||
>
|
||||
{item.name}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="s12 scroll row" style={{ paddingBottom: "8px" }}>
|
||||
{episodeInfo &&
|
||||
episodeInfo.episodes.map((item) => {
|
||||
return (
|
||||
<button
|
||||
key={item.position}
|
||||
className={`${
|
||||
item.position == selectedEpisode ? "primary" : "secondary"
|
||||
}`}
|
||||
onClick={() => {
|
||||
setSelectedEpisode(item.position);
|
||||
setEpisodeURL(item.url);
|
||||
item.is_watched = true;
|
||||
}}
|
||||
>
|
||||
{item.is_watched && <i className="small">check</i>}
|
||||
{item.name}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
|
@ -23,11 +23,7 @@ export const useUserStore = create((set, get) => ({
|
|||
`${endpoints.user.profile}/${jwt.user_id}`,
|
||||
jwt.jwt,
|
||||
);
|
||||
if (me.is_my_profile) {
|
||||
get().login(me, jwt.jwt, jwt.user_id);
|
||||
} else {
|
||||
get().logout();
|
||||
}
|
||||
get().login(me, jwt.jwt, jwt.user_id);
|
||||
} else {
|
||||
get().logout();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue