mirror of
https://github.com/Radiquum/AniX.git
synced 2025-09-05 05:55:36 +05:00
Compare commits
9 commits
762c2f324a
...
84698dafca
Author | SHA1 | Date | |
---|---|---|---|
84698dafca | |||
bdbb8cc548 | |||
ff2dbdfac1 | |||
4a45b7af56 | |||
de6dcabbc7 | |||
3f85d0e340 | |||
5bc65da8e3 | |||
b9bf9e9bd8 | |||
e363838e98 |
10 changed files with 331 additions and 42 deletions
|
@ -1,4 +1,4 @@
|
|||
export const CURRENT_APP_VERSION = "3.5.0";
|
||||
export const CURRENT_APP_VERSION = "3.6.0";
|
||||
|
||||
export const API_URL = "https://api.anixart.tv";
|
||||
export const API_PREFIX = "/api/proxy";
|
||||
|
|
90
app/components/ContinueWatching/ContinueWatching.tsx
Normal file
90
app/components/ContinueWatching/ContinueWatching.tsx
Normal file
|
@ -0,0 +1,90 @@
|
|||
"use client";
|
||||
|
||||
import { Card } from "flowbite-react";
|
||||
import { ReleaseLinkList } from "#/components/ReleaseLink/ReleaseLinkList";
|
||||
import { useUserStore } from "#/store/auth";
|
||||
import { ENDPOINTS } from "#/api/config";
|
||||
import { BookmarksList, useSWRfetcher } from "#/api/utils";
|
||||
import useSWR from "swr";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const ContinueWatching = () => {
|
||||
const userStore = useUserStore();
|
||||
|
||||
function useFetchReleases(listName: string) {
|
||||
let url: string;
|
||||
if (userStore.token) {
|
||||
url = `${ENDPOINTS.user.bookmark}/all/${BookmarksList[listName]}/0?sort=1&token=${userStore.token}`;
|
||||
}
|
||||
const { data, isLoading, error } = useSWR(url, useSWRfetcher);
|
||||
return [data, isLoading, error];
|
||||
}
|
||||
|
||||
const [watchingData, watchingLoading, watchingError] =
|
||||
useFetchReleases("watching");
|
||||
const [plannedData, plannedLoading, plannedError] =
|
||||
useFetchReleases("planned");
|
||||
const [delayedData, delayedLoading, delayedError] =
|
||||
useFetchReleases("delayed");
|
||||
|
||||
const [releaseData, setReleaseData] = useState<any[]>([]);
|
||||
|
||||
const firstN = (arr, n = 1) => arr.slice(0, n);
|
||||
function _randomize(array: any[], limit: number) {
|
||||
const toRand = array.slice();
|
||||
let currentIndex = toRand.length;
|
||||
while (currentIndex != 0) {
|
||||
let randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex--;
|
||||
[toRand[currentIndex], toRand[randomIndex]] = [
|
||||
toRand[randomIndex],
|
||||
toRand[currentIndex],
|
||||
];
|
||||
}
|
||||
return firstN(toRand, limit);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!watchingLoading && !plannedLoading && !delayedLoading) {
|
||||
const data = [
|
||||
...(watchingData.content || []),
|
||||
...(plannedData.content || []),
|
||||
...(delayedData.content || []),
|
||||
];
|
||||
console.log("loaded data:", data);
|
||||
const randomizedData = _randomize(data, 3);
|
||||
setReleaseData(randomizedData);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [watchingLoading, plannedLoading, delayedLoading]);
|
||||
|
||||
if (
|
||||
!userStore.isAuth ||
|
||||
watchingLoading ||
|
||||
plannedLoading ||
|
||||
delayedLoading ||
|
||||
releaseData.length == 0
|
||||
)
|
||||
return <></>;
|
||||
|
||||
console.log("randomized data:", releaseData);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<div className="flex justify-between py-2 border-b-2 border-black dark:border-white">
|
||||
<h1>Продолжить просмотр</h1>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 mt-2">
|
||||
{releaseData.map((release: any) => {
|
||||
return (
|
||||
<ReleaseLinkList
|
||||
key={release.id}
|
||||
{...release}
|
||||
settings={{ showDescription: false }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
|
@ -17,7 +17,7 @@ export const ProfileActivityComment = (props: {
|
|||
key={`comment-${comment.id}`}
|
||||
>
|
||||
<footer className="flex items-center justify-between mb-2">
|
||||
<div className="flex flex-col items-start gap-1 sm:items-center sm:flex-row">
|
||||
<div className="flex items-center gap-1">
|
||||
<Link
|
||||
href={`/profile/${comment.profile.id}`}
|
||||
className="inline-flex items-center mr-3 text-sm font-semibold text-gray-900 dark:text-white hover:underline"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { Card, Carousel } from "flowbite-react";
|
||||
import { ReleaseLink } from "#/components/ReleaseLink/ReleaseLinkUpdate";
|
||||
import { Card } from "flowbite-react";
|
||||
import { ReleaseLinkList } from "#/components/ReleaseLink/ReleaseLinkList";
|
||||
import Link from "next/link";
|
||||
|
||||
export const ReleaseInfoRelated = (props: {
|
||||
|
@ -22,25 +22,23 @@ export const ReleaseInfoRelated = (props: {
|
|||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex justify-center mt-2">
|
||||
<Carousel pauseOnHover={true}>
|
||||
{props.related_releases
|
||||
.filter((release: any) => {
|
||||
if (release.id == props.release_id) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((release: any) => {
|
||||
return (
|
||||
<ReleaseLink
|
||||
key={release.id}
|
||||
{...release}
|
||||
settings={{ showGenres: false, showDescription: false }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Carousel>
|
||||
<div className="flex flex-col gap-4 mt-2">
|
||||
{props.related_releases
|
||||
.filter((release: any) => {
|
||||
if (release.id == props.release_id) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((release: any) => {
|
||||
return (
|
||||
<ReleaseLinkList
|
||||
key={release.id}
|
||||
{...release}
|
||||
settings={{ showGenres: false, showDescription: false }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
|
|
|
@ -1,21 +1,63 @@
|
|||
import { Card, Carousel } from "flowbite-react";
|
||||
import { Card } from "flowbite-react";
|
||||
import Image from "next/image";
|
||||
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import "swiper/css";
|
||||
import "swiper/css/navigation";
|
||||
import "swiper/css/pagination";
|
||||
import "swiper/css/autoplay";
|
||||
import { Navigation, Pagination, Autoplay } from "swiper/modules";
|
||||
|
||||
export const ReleaseInfoScreenshots = (props: { images: string[] }) => {
|
||||
return (
|
||||
<Card>
|
||||
<Carousel className="aspect-[16/10]">
|
||||
{props.images.map((image: string, index: number) => (
|
||||
<Image
|
||||
key={index}
|
||||
className="object-cover"
|
||||
src={image}
|
||||
width={400}
|
||||
height={300}
|
||||
alt=""
|
||||
/>
|
||||
))}
|
||||
</Carousel>
|
||||
<Swiper
|
||||
modules={[Navigation, Pagination, Autoplay]}
|
||||
spaceBetween={8}
|
||||
slidesPerView={2}
|
||||
direction={"horizontal"}
|
||||
allowTouchMove={true}
|
||||
autoplay={true}
|
||||
pagination={true}
|
||||
breakpoints={{
|
||||
1024: {
|
||||
slidesPerView: 1,
|
||||
},
|
||||
}}
|
||||
style={{
|
||||
height: "100%",
|
||||
minHeight: 0,
|
||||
maxHeight: "100%",
|
||||
width: "100%",
|
||||
minWidth: 0,
|
||||
maxWidth: "100%",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{props.images.map((image: string, index: number) => {
|
||||
return (
|
||||
<SwiperSlide
|
||||
key={`release-screenshot-${index}`}
|
||||
style={{
|
||||
width: "fit-content",
|
||||
flexShrink: 0,
|
||||
display: "block",
|
||||
height: "100%",
|
||||
maxHeight: "100%",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
key={index}
|
||||
className="object-cover"
|
||||
src={image}
|
||||
width={400}
|
||||
height={225}
|
||||
alt=""
|
||||
/>
|
||||
</SwiperSlide>
|
||||
);
|
||||
})}
|
||||
</Swiper>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
|
118
app/components/ReleaseLink/ReleaseLinkList.tsx
Normal file
118
app/components/ReleaseLink/ReleaseLinkList.tsx
Normal file
|
@ -0,0 +1,118 @@
|
|||
import Link from "next/link";
|
||||
import { Poster } from "../ReleasePoster/Poster";
|
||||
import { ReleaseChips } from "../ReleasePoster/Chips";
|
||||
|
||||
const profile_lists = {
|
||||
// 0: "Не смотрю",
|
||||
1: { name: "Смотрю", bg_color: "bg-green-500" },
|
||||
2: { name: "В планах", bg_color: "bg-purple-500" },
|
||||
3: { name: "Просмотрено", bg_color: "bg-blue-500" },
|
||||
4: { name: "Отложено", bg_color: "bg-yellow-500" },
|
||||
5: { name: "Брошено", bg_color: "bg-red-500" },
|
||||
};
|
||||
|
||||
export const ReleaseLinkList = (props: {
|
||||
image: string;
|
||||
title_ru: string;
|
||||
title_original: string;
|
||||
description?: string;
|
||||
genres?: string;
|
||||
grade?: number;
|
||||
id: number;
|
||||
settings?: {
|
||||
showGenres?: boolean;
|
||||
showDescription?: boolean;
|
||||
showOrigTitle?: boolean;
|
||||
};
|
||||
chipsSettings?: {
|
||||
enabled: boolean;
|
||||
gradeHidden?: boolean;
|
||||
statusHidden?: boolean;
|
||||
categoryHidden?: boolean;
|
||||
episodesHidden?: boolean;
|
||||
listHidden?: boolean;
|
||||
favHidden?: boolean;
|
||||
lastWatchedHidden?: boolean;
|
||||
};
|
||||
profile_list_status?: number;
|
||||
status?: {
|
||||
name: string;
|
||||
};
|
||||
category?: {
|
||||
name: string;
|
||||
};
|
||||
status_id?: number;
|
||||
episodes_released?: string;
|
||||
episodes_total?: string;
|
||||
is_favorite?: boolean;
|
||||
}) => {
|
||||
const genres = [];
|
||||
const settings = {
|
||||
showGenres: true,
|
||||
showDescription: true,
|
||||
showOrigTitle: true,
|
||||
...props.settings,
|
||||
};
|
||||
const chipsSettings = props.chipsSettings || {};
|
||||
|
||||
const grade = props.grade ? Number(props.grade.toFixed(1)) : null;
|
||||
const profile_list_status = props.profile_list_status || null;
|
||||
let user_list = null;
|
||||
if (profile_list_status != null || profile_list_status != 0) {
|
||||
user_list = profile_lists[profile_list_status];
|
||||
}
|
||||
if (props.genres) {
|
||||
const genres_array = props.genres.split(",");
|
||||
genres_array.forEach((genre) => {
|
||||
genres.push(genre.trim());
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Link href={`/release/${props.id}`}>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-shrink-0 w-32">
|
||||
<Poster image={props.image} className="h-auto" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<ReleaseChips
|
||||
{...props}
|
||||
user_list={user_list}
|
||||
grade={grade}
|
||||
settings={{ lastWatchedHidden: false }}
|
||||
/>
|
||||
<div>
|
||||
{settings.showGenres &&
|
||||
genres.length > 0 &&
|
||||
genres.map((genre: string, index: number) => {
|
||||
return (
|
||||
<span
|
||||
key={`release_${props.id}_genre_${genre}_${index}`}
|
||||
className="text-sm font-light leading-none dark:text-white"
|
||||
>
|
||||
{index > 0 && ", "}
|
||||
{genre}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{props.title_ru && (
|
||||
<p className="text-lg font-bold line-clamp-2 dark:text-white">
|
||||
{props.title_ru}
|
||||
</p>
|
||||
)}
|
||||
{settings.showOrigTitle && props.title_original && (
|
||||
<p className="text-sm text-gray-600 line-clamp-2 dark:text-gray-300">
|
||||
{props.title_original}
|
||||
</p>
|
||||
)}
|
||||
{settings.showDescription && props.description && (
|
||||
<p className="mt-2 text-sm font-light leading-none text-white lg:text-base xl:text-lg line-clamp-4">
|
||||
{props.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
};
|
|
@ -18,6 +18,7 @@ import { CommentsMain } from "#/components/Comments/Comments.Main";
|
|||
import { InfoLists } from "#/components/InfoLists/InfoLists";
|
||||
import { ENDPOINTS } from "#/api/config";
|
||||
import { usePreferencesStore } from "#/store/preferences";
|
||||
import { ContinueWatching } from "#/components/ContinueWatching/ContinueWatching";
|
||||
|
||||
export const ReleasePage = (props: any) => {
|
||||
const userStore = useUserStore();
|
||||
|
@ -71,7 +72,7 @@ export const ReleasePage = (props: any) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex flex-col gap-2 pb-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-[70%_30%] gap-2 grid-flow-row-dense">
|
||||
<ReleaseInfoBasics
|
||||
image={data.release.image}
|
||||
|
@ -122,11 +123,13 @@ export const ReleasePage = (props: any) => {
|
|||
: <ReleasePlayer id={props.id} />}
|
||||
</>
|
||||
)}
|
||||
<CommentsMain
|
||||
release_id={props.id}
|
||||
token={userStore.token}
|
||||
comments={data.release.comments}
|
||||
/>
|
||||
<div className="hidden lg:block">
|
||||
<CommentsMain
|
||||
release_id={props.id}
|
||||
token={userStore.token}
|
||||
comments={data.release.comments}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
{data.release.status &&
|
||||
|
@ -165,6 +168,14 @@ export const ReleasePage = (props: any) => {
|
|||
related_releases={data.release.related_releases}
|
||||
/>
|
||||
)}
|
||||
{userStore.token && <ContinueWatching />}
|
||||
<div className="block lg:hidden">
|
||||
<CommentsMain
|
||||
release_id={props.id}
|
||||
token={userStore.token}
|
||||
comments={data.release.comments}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
11
package-lock.json
generated
11
package-lock.json
generated
|
@ -39,6 +39,7 @@
|
|||
"copy-webpack-plugin": "^12.0.2",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.5",
|
||||
"eslint-plugin-react-refresh": "^0.4.19",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1"
|
||||
}
|
||||
|
@ -2984,6 +2985,16 @@
|
|||
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react-refresh": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.19.tgz",
|
||||
"integrity": "sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"eslint": ">=8.40"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react/node_modules/doctrine": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
"copy-webpack-plugin": "^12.0.2",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.5",
|
||||
"eslint-plugin-react-refresh": "^0.4.19",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1"
|
||||
}
|
||||
|
|
18
public/changelog/3.6.0.md
Normal file
18
public/changelog/3.6.0.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
# 3.6.0
|
||||
|
||||
## Добавлено
|
||||
|
||||
- Добавлена возможность смотреть заблокированных пользователей (в меню редактирования профиля)
|
||||
- Добавлена возможность смотреть друзей пользователя
|
||||
- Добавлена возможность смотреть, принимать и скрывать заявки в друзья
|
||||
- Добавлен просмотр популярных комментариев пользователя
|
||||
- Добавлен блок "Продолжить просмотр" на странице релиза если был произведён вход в аккаунт (3 рандомных релиза из списков сморю, в планах и отложено)
|
||||
|
||||
## Изменено
|
||||
|
||||
- Стиль некоторых элементов был изменён в связи с обновление библиотеки компонентов
|
||||
- Блок скриншотов был перенесён на другую библиотеку
|
||||
- Изменён вид блока связанных релизов на странице релиза с карусели карточек на список
|
||||
- Изменён блок активности на странице профиля
|
||||
- Изменены виды блоков "Оценки" и "Недавно просмотренные" на странице профиля с карусели карточек на список
|
||||
- Изменён вид блока профиля (соц. сети и роли)
|
Loading…
Add table
Add a link
Reference in a new issue