mirror of
https://github.com/AnimeThemes/animethemes-web.git
synced 2026-07-11 01:24:31 +02:00
refactor: Changed all fragments to use the same format
This commit is contained in:
@@ -32,40 +32,38 @@ const StyledRank = styled(Text)`
|
||||
letter-spacing: 1px;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
theme: graphql(`
|
||||
fragment BracketThemeSummaryCardTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
...ThemeMenuTheme
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
song {
|
||||
...SongTitleWithArtistsSong
|
||||
}
|
||||
animethemeentries {
|
||||
...createVideoSlugEntry
|
||||
videos {
|
||||
nodes {
|
||||
...createVideoSlugVideo
|
||||
}
|
||||
export const BRACKET_THEME_SUMMARY_CARD_THEME = graphql(`
|
||||
fragment BracketThemeSummaryCardTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
...ThemeMenuTheme
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
song {
|
||||
...SongTitleWithArtistsSong
|
||||
}
|
||||
animethemeentries {
|
||||
...createVideoSlugEntry
|
||||
videos {
|
||||
nodes {
|
||||
...createVideoSlugVideo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export interface BracketWithThemes extends Bracket {
|
||||
currentRound: BracketRoundWithThemes | null;
|
||||
@@ -79,7 +77,7 @@ export interface BracketPairingWithThemes extends BracketPairing {
|
||||
characterB: BracketCharacterWithTheme;
|
||||
}
|
||||
export interface BracketCharacterWithTheme extends BracketCharacter {
|
||||
theme: FragmentType<typeof fragments.theme> | null;
|
||||
theme: FragmentType<typeof BRACKET_THEME_SUMMARY_CARD_THEME> | null;
|
||||
}
|
||||
|
||||
interface BracketThemeSummaryCardProps extends ComponentPropsWithoutRef<typeof StyledSummaryCardWrapper> {
|
||||
@@ -98,7 +96,7 @@ export function BracketThemeSummaryCard({
|
||||
votes,
|
||||
...props
|
||||
}: BracketThemeSummaryCardProps) {
|
||||
const theme = getFragmentData(fragments.theme, character.theme);
|
||||
const theme = getFragmentData(BRACKET_THEME_SUMMARY_CARD_THEME, character.theme);
|
||||
const { smallCover } = extractImages(theme?.anime.images.nodes ?? []);
|
||||
|
||||
let to;
|
||||
|
||||
@@ -11,36 +11,37 @@ import PlayerContext from "@/context/playerContext";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
import createVideoSlug, { getVideoSlugByWatchListItem } from "@/utils/createVideoSlug";
|
||||
|
||||
const fragments = {
|
||||
anime: graphql(`
|
||||
fragment VideoButtonAnime on Anime {
|
||||
slug
|
||||
}
|
||||
`),
|
||||
theme: graphql(`
|
||||
fragment VideoButtonTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment VideoButtonEntry on AnimeThemeEntry {
|
||||
...createVideoSlugEntry
|
||||
}
|
||||
`),
|
||||
video: graphql(`
|
||||
fragment VideoButtonVideo on Video {
|
||||
...createVideoSlugVideo
|
||||
...VideoTagsVideo
|
||||
id
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const VIDEO_BUTTON_ANIME = graphql(`
|
||||
fragment VideoButtonAnime on Anime {
|
||||
slug
|
||||
}
|
||||
`);
|
||||
|
||||
export const VIDEO_BUTTON_THEME = graphql(`
|
||||
fragment VideoButtonTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
}
|
||||
`);
|
||||
|
||||
export const VIDEO_BUTTON_ENTRY = graphql(`
|
||||
fragment VideoButtonEntry on AnimeThemeEntry {
|
||||
...createVideoSlugEntry
|
||||
}
|
||||
`);
|
||||
|
||||
export const VIDEO_BUTTON_VIDEO = graphql(`
|
||||
fragment VideoButtonVideo on Video {
|
||||
...createVideoSlugVideo
|
||||
...VideoTagsVideo
|
||||
id
|
||||
}
|
||||
`);
|
||||
|
||||
interface VideoButtonProps extends ComponentPropsWithoutRef<typeof Button> {
|
||||
anime: FragmentType<typeof fragments.anime>;
|
||||
theme: FragmentType<typeof fragments.theme>;
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
video: FragmentType<typeof fragments.video>;
|
||||
anime: FragmentType<typeof VIDEO_BUTTON_ANIME>;
|
||||
theme: FragmentType<typeof VIDEO_BUTTON_THEME>;
|
||||
entry: FragmentType<typeof VIDEO_BUTTON_ENTRY>;
|
||||
video: FragmentType<typeof VIDEO_BUTTON_VIDEO>;
|
||||
}
|
||||
|
||||
export function VideoButton({
|
||||
@@ -50,10 +51,10 @@ export function VideoButton({
|
||||
video: videoFragment,
|
||||
...props
|
||||
}: VideoButtonProps) {
|
||||
const anime = getFragmentData(fragments.anime, animeFragment);
|
||||
const theme = getFragmentData(fragments.theme, themeFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const anime = getFragmentData(VIDEO_BUTTON_ANIME, animeFragment);
|
||||
const theme = getFragmentData(VIDEO_BUTTON_THEME, themeFragment);
|
||||
const entry = getFragmentData(VIDEO_BUTTON_ENTRY, entryFragment);
|
||||
const video = getFragmentData(VIDEO_BUTTON_VIDEO, videoFragment);
|
||||
|
||||
const { currentWatchListItem } = useContext(PlayerContext);
|
||||
const videoSlug = createVideoSlug(theme, entry, video);
|
||||
|
||||
@@ -60,48 +60,47 @@ const StyledThemeGroupContainer = styled.div`
|
||||
margin-top: 8px;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
anime: graphql(`
|
||||
fragment AnimeSummaryCardAnime on Anime {
|
||||
slug
|
||||
name
|
||||
year
|
||||
season
|
||||
seasonLocalized
|
||||
mediaFormatLocalized
|
||||
animethemes {
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
export const ANIME_SUMMARY_CARD_ANIME = graphql(`
|
||||
fragment AnimeSummaryCardAnime on Anime {
|
||||
slug
|
||||
name
|
||||
year
|
||||
season
|
||||
seasonLocalized
|
||||
mediaFormatLocalized
|
||||
animethemes {
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
`),
|
||||
expandable: graphql(`
|
||||
fragment AnimeSummaryCardAnimeExpandable on Anime {
|
||||
animethemes {
|
||||
...ThemeTableTheme
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export const ANIME_SUMMARY_CARD_ANIME_EXPANDABLE = graphql(`
|
||||
fragment AnimeSummaryCardAnimeExpandable on Anime {
|
||||
animethemes {
|
||||
...ThemeTableTheme
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
interface AnimeSummaryCardProps {
|
||||
anime: FragmentType<typeof fragments.anime>;
|
||||
expandable?: FragmentType<typeof fragments.expandable>;
|
||||
anime: FragmentType<typeof ANIME_SUMMARY_CARD_ANIME>;
|
||||
expandable?: FragmentType<typeof ANIME_SUMMARY_CARD_ANIME_EXPANDABLE>;
|
||||
}
|
||||
|
||||
export function AnimeSummaryCard({ anime: animeFragment, expandable, ...props }: AnimeSummaryCardProps) {
|
||||
const anime = getFragmentData(fragments.anime, animeFragment);
|
||||
const anime = getFragmentData(ANIME_SUMMARY_CARD_ANIME, animeFragment);
|
||||
const [isExpanded, toggleExpanded] = useToggle();
|
||||
const { smallCover } = extractImages(anime.images.nodes);
|
||||
const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints.mobileMax})`);
|
||||
@@ -164,7 +163,7 @@ export function AnimeSummaryCard({ anime: animeFragment, expandable, ...props }:
|
||||
</SummaryCard>
|
||||
{expandable ? (
|
||||
<AnimeSummaryCardCollapse
|
||||
anime={getFragmentData(fragments.expandable, expandable)}
|
||||
anime={getFragmentData(ANIME_SUMMARY_CARD_ANIME_EXPANDABLE, expandable)}
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
) : null}
|
||||
@@ -173,7 +172,7 @@ export function AnimeSummaryCard({ anime: animeFragment, expandable, ...props }:
|
||||
}
|
||||
|
||||
interface AnimeSummaryCardCollapseProps {
|
||||
anime: ResultOf<typeof fragments.expandable>;
|
||||
anime: ResultOf<typeof ANIME_SUMMARY_CARD_ANIME_EXPANDABLE>;
|
||||
isExpanded: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,27 +2,25 @@ import { SummaryCard } from "@/components/card/SummaryCard";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
import extractImages from "@/utils/extractImages";
|
||||
|
||||
const fragments = {
|
||||
artist: graphql(`
|
||||
fragment ArtistSummaryCardArtist on Artist {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
export const ARTIST_SUMMARY_CARD_ARTIST = graphql(`
|
||||
fragment ArtistSummaryCardArtist on Artist {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
type ArtistSummaryCardProps = {
|
||||
artist: FragmentType<typeof fragments.artist>;
|
||||
artist: FragmentType<typeof ARTIST_SUMMARY_CARD_ARTIST>;
|
||||
as?: string | null;
|
||||
};
|
||||
|
||||
export function ArtistSummaryCard({ artist: artistFragment, as }: ArtistSummaryCardProps) {
|
||||
const artist = getFragmentData(fragments.artist, artistFragment);
|
||||
const artist = getFragmentData(ARTIST_SUMMARY_CARD_ARTIST, artistFragment);
|
||||
|
||||
const { smallCover } = extractImages(artist.images.nodes);
|
||||
|
||||
|
||||
@@ -28,27 +28,26 @@ const StyledOverlayButtons = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
playlist: graphql(`
|
||||
fragment PlaylistSummaryCardPlaylist on Playlist {
|
||||
id
|
||||
export const PLAYLIST_SUMMARY_CARD_PLAYLIST = graphql(`
|
||||
fragment PlaylistSummaryCardPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
visibilityLocalized
|
||||
tracksCount
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_SUMMARY_CARD_PLAYLIST_WITH_OWNER = graphql(`
|
||||
fragment PlaylistSummaryCardPlaylistWithOwner on Playlist {
|
||||
user {
|
||||
name
|
||||
visibilityLocalized
|
||||
tracksCount
|
||||
}
|
||||
`),
|
||||
playlistWithOwner: graphql(`
|
||||
fragment PlaylistSummaryCardPlaylistWithOwner on Playlist {
|
||||
user {
|
||||
name
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface PlaylistSummaryCardProps {
|
||||
playlist: FragmentType<typeof fragments.playlist>;
|
||||
playlistWithOwner?: FragmentType<typeof fragments.playlistWithOwner>;
|
||||
playlist: FragmentType<typeof PLAYLIST_SUMMARY_CARD_PLAYLIST>;
|
||||
playlistWithOwner?: FragmentType<typeof PLAYLIST_SUMMARY_CARD_PLAYLIST_WITH_OWNER>;
|
||||
menu?: ReactNode;
|
||||
}
|
||||
|
||||
@@ -59,8 +58,8 @@ export default function PlaylistSummaryCard({
|
||||
menu,
|
||||
...props
|
||||
}: PropsWithChildren<PlaylistSummaryCardProps>) {
|
||||
const playlist = getFragmentData(fragments.playlist, playlistFragment);
|
||||
const playlistWithOwner = getFragmentData(fragments.playlistWithOwner, playlistWithOwnerFragment);
|
||||
const playlist = getFragmentData(PLAYLIST_SUMMARY_CARD_PLAYLIST, playlistFragment);
|
||||
const playlistWithOwner = getFragmentData(PLAYLIST_SUMMARY_CARD_PLAYLIST_WITH_OWNER, playlistWithOwnerFragment);
|
||||
|
||||
const description = (
|
||||
<SummaryCard.Description>
|
||||
|
||||
@@ -7,26 +7,24 @@ import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated
|
||||
import extractBackgroundColor from "@/utils/extractBackgroundColor";
|
||||
import extractImages from "@/utils/extractImages";
|
||||
|
||||
const fragments = {
|
||||
studio: graphql(`
|
||||
fragment StudioSummaryCardStudio on Studio {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
export const STUDIO_SUMMARY_CARD_STUDIO = graphql(`
|
||||
fragment StudioSummaryCardStudio on Studio {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface StudioSummaryCardProps {
|
||||
studio: FragmentType<typeof fragments.studio>;
|
||||
studio: FragmentType<typeof STUDIO_SUMMARY_CARD_STUDIO>;
|
||||
}
|
||||
|
||||
export function StudioSummaryCard({ studio: studioFragment }: StudioSummaryCardProps) {
|
||||
const studio = getFragmentData(fragments.studio, studioFragment);
|
||||
const studio = getFragmentData(STUDIO_SUMMARY_CARD_STUDIO, studioFragment);
|
||||
|
||||
const [backgroundColor, setBackgroundColor] = useState<Property.Background>();
|
||||
|
||||
|
||||
@@ -42,48 +42,46 @@ const StyledVideoList = styled(Row)`
|
||||
}
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
theme: graphql(`
|
||||
fragment ThemeDetailCardTheme on AnimeTheme {
|
||||
...ThemeMenuTheme
|
||||
...VideoButtonTheme
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
...VideoButtonAnime
|
||||
slug
|
||||
name
|
||||
}
|
||||
song {
|
||||
...SongTitleSong
|
||||
...PerformancesSong
|
||||
}
|
||||
animethemeentries {
|
||||
...ThemeEntryTagsEntry
|
||||
...VideoButtonEntry
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
...VideoButtonVideo
|
||||
filename
|
||||
tags
|
||||
}
|
||||
export const THEME_DETAIL_CARD_THEME = graphql(`
|
||||
fragment ThemeDetailCardTheme on AnimeTheme {
|
||||
...ThemeMenuTheme
|
||||
...VideoButtonTheme
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
...VideoButtonAnime
|
||||
slug
|
||||
name
|
||||
}
|
||||
song {
|
||||
...SongTitleSong
|
||||
...PerformancesSong
|
||||
}
|
||||
animethemeentries {
|
||||
...ThemeEntryTagsEntry
|
||||
...VideoButtonEntry
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
...VideoButtonVideo
|
||||
filename
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface ThemeDetailCardProps {
|
||||
theme: FragmentType<typeof fragments.theme>;
|
||||
theme: FragmentType<typeof THEME_DETAIL_CARD_THEME>;
|
||||
}
|
||||
|
||||
export function ThemeDetailCard({ theme: themeFragment }: ThemeDetailCardProps) {
|
||||
const theme = getFragmentData(fragments.theme, themeFragment);
|
||||
const theme = getFragmentData(THEME_DETAIL_CARD_THEME, themeFragment);
|
||||
const { anime } = theme;
|
||||
|
||||
if (!anime) {
|
||||
|
||||
@@ -21,23 +21,21 @@ import type { PlaylistVisibility } from "@/graphql/generated/graphql";
|
||||
import { PLAYLIST_DETAIL_PAGE_PLAYLIST } from "@/pages/playlist/[playlistId]";
|
||||
import { PROFILE_PAGE } from "@/pages/profile";
|
||||
|
||||
const fragments = {
|
||||
playlist: graphql(`
|
||||
fragment PlaylistEditDialogPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
visibility
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const PLAYLIST_EDIT_DIALOG_PLAYLIST = graphql(`
|
||||
fragment PlaylistEditDialogPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
visibility
|
||||
}
|
||||
`);
|
||||
|
||||
interface PlaylistEditDialogProps {
|
||||
playlist: FragmentType<typeof fragments.playlist>;
|
||||
playlist: FragmentType<typeof PLAYLIST_EDIT_DIALOG_PLAYLIST>;
|
||||
trigger?: ReactNode;
|
||||
}
|
||||
|
||||
export function PlaylistEditDialog({ playlist: playlistFragment, trigger }: PlaylistEditDialogProps) {
|
||||
const playlist = getFragmentData(fragments.playlist, playlistFragment);
|
||||
const playlist = getFragmentData(PLAYLIST_EDIT_DIALOG_PLAYLIST, playlistFragment);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -71,7 +69,7 @@ const StyledForm = styled.form`
|
||||
`;
|
||||
|
||||
interface PlaylistEditFormProps {
|
||||
playlist: ResultOf<typeof fragments.playlist>;
|
||||
playlist: ResultOf<typeof PLAYLIST_EDIT_DIALOG_PLAYLIST>;
|
||||
onSuccess(): void;
|
||||
onCancel(): void;
|
||||
}
|
||||
|
||||
@@ -18,24 +18,22 @@ import { useToasts } from "@/context/toastContext";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
import { PROFILE_PAGE } from "@/pages/profile";
|
||||
|
||||
const fragments = {
|
||||
playlist: graphql(`
|
||||
fragment PlaylistRemoveDialogPlaylist on Playlist {
|
||||
...PlaylistSummaryCardPlaylist
|
||||
...PlaylistRemoveToastPlaylist
|
||||
id
|
||||
name
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const PLAYLIST_REMOVE_DIALOG_PLAYLIST = graphql(`
|
||||
fragment PlaylistRemoveDialogPlaylist on Playlist {
|
||||
...PlaylistSummaryCardPlaylist
|
||||
...PlaylistRemoveToastPlaylist
|
||||
id
|
||||
name
|
||||
}
|
||||
`);
|
||||
|
||||
interface PlaylistRemoveDialogProps {
|
||||
playlist: FragmentType<typeof fragments.playlist>;
|
||||
playlist: FragmentType<typeof PLAYLIST_REMOVE_DIALOG_PLAYLIST>;
|
||||
trigger?: ReactNode;
|
||||
}
|
||||
|
||||
export function PlaylistRemoveDialog({ playlist: playlistFragment, trigger }: PlaylistRemoveDialogProps) {
|
||||
const playlist = getFragmentData(fragments.playlist, playlistFragment);
|
||||
const playlist = getFragmentData(PLAYLIST_REMOVE_DIALOG_PLAYLIST, playlistFragment);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -65,7 +63,7 @@ export function PlaylistRemoveDialog({ playlist: playlistFragment, trigger }: Pl
|
||||
}
|
||||
|
||||
interface PlaylistRemoveFormProps {
|
||||
playlist: ResultOf<typeof fragments.playlist>;
|
||||
playlist: ResultOf<typeof PLAYLIST_REMOVE_DIALOG_PLAYLIST>;
|
||||
onSuccess(): void;
|
||||
onCancel(): void;
|
||||
}
|
||||
|
||||
@@ -25,26 +25,25 @@ import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated
|
||||
import { PLAYLIST_DETAIL_PAGE_PLAYLIST } from "@/pages/playlist/[playlistId]";
|
||||
import { PROFILE_PAGE } from "@/pages/profile";
|
||||
|
||||
const fragments = {
|
||||
video: graphql(`
|
||||
fragment PlaylistTrackAddDialogVideo on Video {
|
||||
...VideoSummaryCardVideo
|
||||
id
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment PlaylistTrackAddDialogEntry on AnimeThemeEntry {
|
||||
...VideoSummaryCardEntry
|
||||
...PlaylistTrackAddToastEntry
|
||||
...PlaylistTrackRemoveToastEntry
|
||||
id
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const PLAYLIST_TRACK_ADD_DIALOG_VIDEO = graphql(`
|
||||
fragment PlaylistTrackAddDialogVideo on Video {
|
||||
...VideoSummaryCardVideo
|
||||
id
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_TRACK_ADD_DIALOG_ENTRY = graphql(`
|
||||
fragment PlaylistTrackAddDialogEntry on AnimeThemeEntry {
|
||||
...VideoSummaryCardEntry
|
||||
...PlaylistTrackAddToastEntry
|
||||
...PlaylistTrackRemoveToastEntry
|
||||
id
|
||||
}
|
||||
`);
|
||||
|
||||
interface PlaylistTrackAddDialogProps {
|
||||
video: FragmentType<typeof fragments.video>;
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
video: FragmentType<typeof PLAYLIST_TRACK_ADD_DIALOG_VIDEO>;
|
||||
entry: FragmentType<typeof PLAYLIST_TRACK_ADD_DIALOG_ENTRY>;
|
||||
trigger?: ReactNode;
|
||||
}
|
||||
|
||||
@@ -53,8 +52,8 @@ export function PlaylistTrackAddDialog({
|
||||
entry: entryFragment,
|
||||
trigger,
|
||||
}: PlaylistTrackAddDialogProps) {
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const video = getFragmentData(PLAYLIST_TRACK_ADD_DIALOG_VIDEO, videoFragment);
|
||||
const entry = getFragmentData(PLAYLIST_TRACK_ADD_DIALOG_ENTRY, entryFragment);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
@@ -93,8 +92,8 @@ const PLAYLIST_TRACK_ADD_FORM_PLAYLIST = graphql(`
|
||||
`);
|
||||
|
||||
interface PlaylistTrackAddFormProps {
|
||||
video: ResultOf<typeof fragments.video>;
|
||||
entry: ResultOf<typeof fragments.entry>;
|
||||
video: ResultOf<typeof PLAYLIST_TRACK_ADD_DIALOG_VIDEO>;
|
||||
entry: ResultOf<typeof PLAYLIST_TRACK_ADD_DIALOG_ENTRY>;
|
||||
onCancel(): void;
|
||||
}
|
||||
|
||||
@@ -175,8 +174,8 @@ const PLAYLIST_TRACK_ADD_CARD_TRACK = graphql(`
|
||||
interface PlaylistTrackAddCardProps {
|
||||
playlist: FragmentType<typeof PLAYLIST_TRACK_ADD_CARD_PLAYLIST>;
|
||||
track: FragmentType<typeof PLAYLIST_TRACK_ADD_CARD_TRACK> | null;
|
||||
video: ResultOf<typeof fragments.video>;
|
||||
entry: ResultOf<typeof fragments.entry>;
|
||||
video: ResultOf<typeof PLAYLIST_TRACK_ADD_DIALOG_VIDEO>;
|
||||
entry: ResultOf<typeof PLAYLIST_TRACK_ADD_DIALOG_ENTRY>;
|
||||
}
|
||||
|
||||
function PlaylistTrackAddCard({
|
||||
|
||||
@@ -18,32 +18,32 @@ import { useToasts } from "@/context/toastContext";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
import { PLAYLIST_DETAIL_PAGE_PLAYLIST } from "@/pages/playlist/[playlistId]";
|
||||
|
||||
const fragments = {
|
||||
playlist: graphql(`
|
||||
fragment PlaylistTrackRemoveDialogPlaylist on Playlist {
|
||||
...PlaylistTrackRemoveToastPlaylist
|
||||
id
|
||||
name
|
||||
}
|
||||
`),
|
||||
video: graphql(`
|
||||
fragment PlaylistTrackRemoveDialogVideo on Video {
|
||||
...VideoSummaryCardVideo
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment PlaylistTrackRemoveDialogEntry on AnimeThemeEntry {
|
||||
...VideoSummaryCardEntry
|
||||
...PlaylistTrackRemoveToastEntry
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const PLAYLIST_TRACK_REMOVE_DIALOG_PLAYLIST = graphql(`
|
||||
fragment PlaylistTrackRemoveDialogPlaylist on Playlist {
|
||||
...PlaylistTrackRemoveToastPlaylist
|
||||
id
|
||||
name
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_TRACK_REMOVE_DIALOG_VIDEO = graphql(`
|
||||
fragment PlaylistTrackRemoveDialogVideo on Video {
|
||||
...VideoSummaryCardVideo
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_TRACK_REMOVE_DIALOG_ENTRY = graphql(`
|
||||
fragment PlaylistTrackRemoveDialogEntry on AnimeThemeEntry {
|
||||
...VideoSummaryCardEntry
|
||||
...PlaylistTrackRemoveToastEntry
|
||||
}
|
||||
`);
|
||||
|
||||
interface PlaylistTrackRemoveDialogProps {
|
||||
playlist: FragmentType<typeof fragments.playlist>;
|
||||
playlist: FragmentType<typeof PLAYLIST_TRACK_REMOVE_DIALOG_PLAYLIST>;
|
||||
trackId: string;
|
||||
video: FragmentType<typeof fragments.video>;
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
video: FragmentType<typeof PLAYLIST_TRACK_REMOVE_DIALOG_VIDEO>;
|
||||
entry: FragmentType<typeof PLAYLIST_TRACK_REMOVE_DIALOG_ENTRY>;
|
||||
trigger?: ReactNode;
|
||||
}
|
||||
|
||||
@@ -54,9 +54,9 @@ export function PlaylistTrackRemoveDialog({
|
||||
entry: entryFragment,
|
||||
trigger,
|
||||
}: PlaylistTrackRemoveDialogProps) {
|
||||
const playlist = getFragmentData(fragments.playlist, playlistFragment);
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const playlist = getFragmentData(PLAYLIST_TRACK_REMOVE_DIALOG_PLAYLIST, playlistFragment);
|
||||
const video = getFragmentData(PLAYLIST_TRACK_REMOVE_DIALOG_VIDEO, videoFragment);
|
||||
const entry = getFragmentData(PLAYLIST_TRACK_REMOVE_DIALOG_ENTRY, entryFragment);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -89,10 +89,10 @@ export function PlaylistTrackRemoveDialog({
|
||||
}
|
||||
|
||||
interface PlaylistTrackRemoveFormProps {
|
||||
playlist: ResultOf<typeof fragments.playlist>;
|
||||
playlist: ResultOf<typeof PLAYLIST_TRACK_REMOVE_DIALOG_PLAYLIST>;
|
||||
trackId: string;
|
||||
video: ResultOf<typeof fragments.video>;
|
||||
entry: ResultOf<typeof fragments.entry>;
|
||||
video: ResultOf<typeof PLAYLIST_TRACK_REMOVE_DIALOG_VIDEO>;
|
||||
entry: ResultOf<typeof PLAYLIST_TRACK_REMOVE_DIALOG_ENTRY>;
|
||||
onSuccess(): void;
|
||||
onCancel(): void;
|
||||
}
|
||||
|
||||
@@ -119,36 +119,35 @@ const StyledGrill = styled.img`
|
||||
|
||||
const Box = styled.div``;
|
||||
|
||||
const fragments = {
|
||||
entry: graphql(`
|
||||
fragment FeaturedThemeEntry on AnimeThemeEntry {
|
||||
...VideoSummaryCardEntry
|
||||
...createVideoSlugEntry
|
||||
animetheme {
|
||||
...createVideoSlugTheme
|
||||
anime {
|
||||
slug
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
export const FEATURED_THEME_ENTRY = graphql(`
|
||||
fragment FeaturedThemeEntry on AnimeThemeEntry {
|
||||
...VideoSummaryCardEntry
|
||||
...createVideoSlugEntry
|
||||
animetheme {
|
||||
...createVideoSlugTheme
|
||||
anime {
|
||||
slug
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
video: graphql(`
|
||||
fragment FeaturedThemeVideo on Video {
|
||||
...VideoSummaryCardVideo
|
||||
...createVideoSlugVideo
|
||||
basename
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export const FEATURED_THEME_VIDEO = graphql(`
|
||||
fragment FeaturedThemeVideo on Video {
|
||||
...VideoSummaryCardVideo
|
||||
...createVideoSlugVideo
|
||||
basename
|
||||
}
|
||||
`);
|
||||
|
||||
interface FeaturedThemeProps {
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
video: FragmentType<typeof fragments.video>;
|
||||
entry: FragmentType<typeof FEATURED_THEME_ENTRY>;
|
||||
video: FragmentType<typeof FEATURED_THEME_VIDEO>;
|
||||
hasGrill?: boolean;
|
||||
card?: ReactNode;
|
||||
onPlay?(): void;
|
||||
@@ -161,8 +160,8 @@ export function FeaturedTheme({
|
||||
card,
|
||||
onPlay,
|
||||
}: FeaturedThemeProps) {
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const entry = getFragmentData(FEATURED_THEME_ENTRY, entryFragment);
|
||||
const video = getFragmentData(FEATURED_THEME_VIDEO, videoFragment);
|
||||
|
||||
const [grill, setGrill] = useState<string | null>(null);
|
||||
const [featuredThemePreview] = useSetting(FeaturedThemePreview);
|
||||
@@ -196,8 +195,8 @@ export function FeaturedTheme({
|
||||
}
|
||||
|
||||
interface FeaturedThemeBackgroundProps {
|
||||
entry: ResultOf<typeof fragments.entry>;
|
||||
video: ResultOf<typeof fragments.video>;
|
||||
entry: ResultOf<typeof FEATURED_THEME_ENTRY>;
|
||||
video: ResultOf<typeof FEATURED_THEME_VIDEO>;
|
||||
onPlay?(): void;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,27 +8,25 @@ import { HorizontalScroll } from "@/components/utils/HorizontalScroll";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
import { either, themeGroupComparator, themeIndexComparator, themeTypeComparator } from "@/utils/comparators";
|
||||
|
||||
const fragments = {
|
||||
theme: graphql(`
|
||||
fragment AnimeThemeFilterTheme on AnimeTheme {
|
||||
...ThemeDetailCardTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
export const ANIME_THEME_FILTER_THEME = graphql(`
|
||||
fragment AnimeThemeFilterTheme on AnimeTheme {
|
||||
...ThemeDetailCardTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface AnimeThemeFilterProps {
|
||||
themes: Array<FragmentType<typeof fragments.theme>>;
|
||||
themes: Array<FragmentType<typeof ANIME_THEME_FILTER_THEME>>;
|
||||
}
|
||||
|
||||
function AnimeThemeFilterInternal({ themes: themesFragment }: AnimeThemeFilterProps) {
|
||||
const themes = getFragmentData(fragments.theme, themesFragment);
|
||||
const themes = getFragmentData(ANIME_THEME_FILTER_THEME, themesFragment);
|
||||
|
||||
const hasMultipleTypes = themes.some((theme) => theme.type === "OP") && themes.some((theme) => theme.type === "ED");
|
||||
const [filterType, setFilterType] = useState<string | null>(null);
|
||||
|
||||
@@ -2,22 +2,20 @@ import md5 from "md5";
|
||||
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
user: graphql(`
|
||||
fragment ProfileImageUser on Me {
|
||||
name
|
||||
email
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const PROFILE_IMAGE_USER = graphql(`
|
||||
fragment ProfileImageUser on Me {
|
||||
name
|
||||
email
|
||||
}
|
||||
`);
|
||||
|
||||
interface ProfileImageProps {
|
||||
user: FragmentType<typeof fragments.user>;
|
||||
user: FragmentType<typeof PROFILE_IMAGE_USER>;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
export function ProfileImage({ user: userFragment, size = 80, ...props }: ProfileImageProps) {
|
||||
const user = getFragmentData(fragments.user, userFragment);
|
||||
const user = getFragmentData(PROFILE_IMAGE_USER, userFragment);
|
||||
|
||||
const hash = md5(user.email.trim().toLowerCase());
|
||||
|
||||
|
||||
@@ -13,34 +13,32 @@ const StyledImage = styled(FullWidthImage)`
|
||||
background-size: contain;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
studio: graphql(`
|
||||
fragment StudioCoverImageStudio on Studio {
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
export const STUDIO_COVER_IMAGE_STUDIO = graphql(`
|
||||
fragment StudioCoverImageStudio on Studio {
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
anime {
|
||||
nodes {
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
anime {
|
||||
nodes {
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface StudioCoverImageProps extends ComponentPropsWithoutRef<typeof FullWidthImage> {
|
||||
studio: FragmentType<typeof fragments.studio>;
|
||||
studio: FragmentType<typeof STUDIO_COVER_IMAGE_STUDIO>;
|
||||
}
|
||||
|
||||
export function StudioCoverImage({ studio: studioFragment, ...props }: StudioCoverImageProps) {
|
||||
const studio = getFragmentData(fragments.studio, studioFragment);
|
||||
const studio = getFragmentData(STUDIO_COVER_IMAGE_STUDIO, studioFragment);
|
||||
const { largeCover } = extractImages(studio.images.nodes);
|
||||
|
||||
const [imageNotFound, setImageNotFound] = useState(!largeCover);
|
||||
|
||||
@@ -10,53 +10,51 @@ import { Text } from "@/components/text/Text";
|
||||
import PlayerContext from "@/context/playerContext";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
theme: graphql(`
|
||||
fragment ThemeMenuTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
export const THEME_MENU_THEME = graphql(`
|
||||
fragment ThemeMenuTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
song {
|
||||
...SongTitleWithArtistsSong
|
||||
}
|
||||
animethemeentries {
|
||||
...createVideoSlugEntry
|
||||
id
|
||||
videos {
|
||||
nodes {
|
||||
...createVideoSlugVideo
|
||||
id
|
||||
}
|
||||
song {
|
||||
...SongTitleWithArtistsSong
|
||||
}
|
||||
animethemeentries {
|
||||
...createVideoSlugEntry
|
||||
id
|
||||
videos {
|
||||
nodes {
|
||||
...createVideoSlugVideo
|
||||
id
|
||||
basename
|
||||
audio {
|
||||
basename
|
||||
audio {
|
||||
basename
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface ThemeMenuProps {
|
||||
theme: FragmentType<typeof fragments.theme>;
|
||||
theme: FragmentType<typeof THEME_MENU_THEME>;
|
||||
}
|
||||
|
||||
export function ThemeMenu({ theme: themeFragment }: ThemeMenuProps) {
|
||||
const theme = getFragmentData(fragments.theme, themeFragment);
|
||||
const theme = getFragmentData(THEME_MENU_THEME, themeFragment);
|
||||
|
||||
const { watchList, addWatchListItem, addWatchListItemNext } = useContext(PlayerContext);
|
||||
|
||||
|
||||
@@ -10,57 +10,56 @@ import { Text } from "@/components/text/Text";
|
||||
import PlayerContext from "@/context/playerContext";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
entry: graphql(`
|
||||
fragment VideoMenuEntry on AnimeThemeEntry {
|
||||
...createVideoSlugEntry
|
||||
...PlaylistTrackAddDialogEntry
|
||||
export const VIDEO_MENU_ENTRY = graphql(`
|
||||
fragment VideoMenuEntry on AnimeThemeEntry {
|
||||
...createVideoSlugEntry
|
||||
...PlaylistTrackAddDialogEntry
|
||||
id
|
||||
animetheme {
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
animetheme {
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
song {
|
||||
...SongTitleWithArtistsSong
|
||||
}
|
||||
}
|
||||
song {
|
||||
...SongTitleWithArtistsSong
|
||||
}
|
||||
}
|
||||
`),
|
||||
video: graphql(`
|
||||
fragment VideoMenuVideo on Video {
|
||||
...createVideoSlugVideo
|
||||
...PlaylistTrackAddDialogVideo
|
||||
id
|
||||
}
|
||||
`);
|
||||
|
||||
export const VIDEO_MENU_VIDEO = graphql(`
|
||||
fragment VideoMenuVideo on Video {
|
||||
...createVideoSlugVideo
|
||||
...PlaylistTrackAddDialogVideo
|
||||
id
|
||||
basename
|
||||
audio {
|
||||
basename
|
||||
audio {
|
||||
basename
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface VideoMenuProps {
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
video: FragmentType<typeof fragments.video>;
|
||||
entry: FragmentType<typeof VIDEO_MENU_ENTRY>;
|
||||
video: FragmentType<typeof VIDEO_MENU_VIDEO>;
|
||||
}
|
||||
|
||||
export function VideoMenu({ entry: entryFragment, video: videoFragment }: VideoMenuProps) {
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const entry = getFragmentData(VIDEO_MENU_ENTRY, entryFragment);
|
||||
const video = getFragmentData(VIDEO_MENU_VIDEO, videoFragment);
|
||||
|
||||
const { watchList, addWatchListItem, addWatchListItemNext } = useContext(PlayerContext);
|
||||
|
||||
|
||||
@@ -5,31 +5,30 @@ import { Switcher, SwitcherOption } from "@/components/switcher/Switcher";
|
||||
import { HorizontalScroll } from "@/components/utils/HorizontalScroll";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
year: graphql(`
|
||||
fragment SeasonNavigationYear on AnimeYear {
|
||||
year
|
||||
seasons {
|
||||
season
|
||||
seasonLocalized
|
||||
}
|
||||
}
|
||||
`),
|
||||
season: graphql(`
|
||||
fragment SeasonNavigationSeason on AnimeYearSeason {
|
||||
export const SEASON_NAVIGATION_YEAR = graphql(`
|
||||
fragment SeasonNavigationYear on AnimeYear {
|
||||
year
|
||||
seasons {
|
||||
season
|
||||
seasonLocalized
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export const SEASON_NAVIGATION_SEASON = graphql(`
|
||||
fragment SeasonNavigationSeason on AnimeYearSeason {
|
||||
season
|
||||
}
|
||||
`);
|
||||
|
||||
interface SeasonNavigationProps {
|
||||
year: FragmentType<typeof fragments.year>;
|
||||
season?: FragmentType<typeof fragments.season>;
|
||||
year: FragmentType<typeof SEASON_NAVIGATION_YEAR>;
|
||||
season?: FragmentType<typeof SEASON_NAVIGATION_SEASON>;
|
||||
}
|
||||
|
||||
export function SeasonNavigation({ year: yearFragment, season: seasonFragment }: SeasonNavigationProps) {
|
||||
const year = getFragmentData(fragments.year, yearFragment);
|
||||
const season = seasonFragment ? getFragmentData(fragments.season, seasonFragment) : undefined;
|
||||
const year = getFragmentData(SEASON_NAVIGATION_YEAR, yearFragment);
|
||||
const season = seasonFragment ? getFragmentData(SEASON_NAVIGATION_SEASON, seasonFragment) : undefined;
|
||||
|
||||
return (
|
||||
<Row style={{ "--justify-content": "center" }}>
|
||||
|
||||
@@ -22,31 +22,30 @@ const StyledYearNext = styled(StyledYear)`
|
||||
justify-content: flex-start;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
year: graphql(`
|
||||
fragment YearNavigationYear on AnimeYear {
|
||||
year
|
||||
seasons {
|
||||
season
|
||||
seasonLocalized
|
||||
}
|
||||
export const YEAR_NAVIGATION_YEAR = graphql(`
|
||||
fragment YearNavigationYear on AnimeYear {
|
||||
year
|
||||
seasons {
|
||||
season
|
||||
seasonLocalized
|
||||
}
|
||||
`),
|
||||
years: graphql(`
|
||||
fragment YearNavigationYears on AnimeYear {
|
||||
year
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export const YEAR_NAVIGATION_YEARS = graphql(`
|
||||
fragment YearNavigationYears on AnimeYear {
|
||||
year
|
||||
}
|
||||
`);
|
||||
|
||||
interface YearNavigationProps {
|
||||
year: FragmentType<typeof fragments.year>;
|
||||
years: Array<FragmentType<typeof fragments.years>>;
|
||||
year: FragmentType<typeof YEAR_NAVIGATION_YEAR>;
|
||||
years: Array<FragmentType<typeof YEAR_NAVIGATION_YEARS>>;
|
||||
}
|
||||
|
||||
export function YearNavigation({ year: yearFragment, years: yearsFragment }: YearNavigationProps) {
|
||||
const year = getFragmentData(fragments.year, yearFragment);
|
||||
const years = getFragmentData(fragments.years, yearsFragment);
|
||||
const year = getFragmentData(YEAR_NAVIGATION_YEAR, yearFragment);
|
||||
const years = getFragmentData(YEAR_NAVIGATION_YEARs, yearsFragment);
|
||||
|
||||
const previousYear = years.find((y) => y.year === year.year - 1)?.year ?? null;
|
||||
const nextYear = years.find((y) => y.year === year.year + 1)?.year ?? null;
|
||||
|
||||
@@ -11,42 +11,40 @@ import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated
|
||||
import { either, themeIndexComparator, themeTypeComparator } from "@/utils/comparators";
|
||||
import createVideoSlug from "@/utils/createVideoSlug";
|
||||
|
||||
const fragments = {
|
||||
theme: graphql(`
|
||||
fragment ThemeTableTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
anime {
|
||||
slug
|
||||
}
|
||||
animethemeentries {
|
||||
...createVideoSlugEntry
|
||||
...EpisodeTagEntry
|
||||
...ContentWarningTagsEntry
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
...createVideoSlugVideo
|
||||
...VideoTagsVideo
|
||||
}
|
||||
export const THEME_TABLE_THEME = graphql(`
|
||||
fragment ThemeTableTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
anime {
|
||||
slug
|
||||
}
|
||||
animethemeentries {
|
||||
...createVideoSlugEntry
|
||||
...EpisodeTagEntry
|
||||
...ContentWarningTagsEntry
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
...createVideoSlugVideo
|
||||
...VideoTagsVideo
|
||||
}
|
||||
}
|
||||
song {
|
||||
...SongTitleSong
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
song {
|
||||
...SongTitleSong
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export interface ThemeTableProps {
|
||||
themes: Array<FragmentType<typeof fragments.theme>>;
|
||||
themes: Array<FragmentType<typeof THEME_TABLE_THEME>>;
|
||||
onPlay?(initiatingThemeId: number, entryIndex?: number, videoIndex?: number): void;
|
||||
}
|
||||
|
||||
export function ThemeTable({ themes: themesFragment, onPlay }: ThemeTableProps) {
|
||||
const themes = getFragmentData(fragments.theme, themesFragment);
|
||||
const themes = getFragmentData(THEME_TABLE_THEME, themesFragment);
|
||||
|
||||
const rows = themes
|
||||
.filter(
|
||||
|
||||
@@ -4,21 +4,19 @@ import { Icon } from "@/components/icon/Icon";
|
||||
import { Tag } from "@/components/tag/Tag";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
entry: graphql(`
|
||||
fragment ContentWarningTagsEntry on AnimeThemeEntry {
|
||||
spoiler
|
||||
nsfw
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const CONTENT_WARNING_TAGS_ENTRY = graphql(`
|
||||
fragment ContentWarningTagsEntry on AnimeThemeEntry {
|
||||
spoiler
|
||||
nsfw
|
||||
}
|
||||
`);
|
||||
|
||||
interface ContentWarningTagsProps {
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
entry: FragmentType<typeof CONTENT_WARNING_TAGS_ENTRY>;
|
||||
}
|
||||
|
||||
export function ContentWarningTags({ entry: entryFragment }: ContentWarningTagsProps) {
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const entry = getFragmentData(CONTENT_WARNING_TAGS_ENTRY, entryFragment);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -3,20 +3,18 @@ import { faFilm } from "@fortawesome/free-solid-svg-icons";
|
||||
import { Tag } from "@/components/tag/Tag";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
entry: graphql(`
|
||||
fragment EpisodeTagEntry on AnimeThemeEntry {
|
||||
episodes
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const EPISODE_TAG_ENTRY = graphql(`
|
||||
fragment EpisodeTagEntry on AnimeThemeEntry {
|
||||
episodes
|
||||
}
|
||||
`);
|
||||
|
||||
interface EpisodeTagProps {
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
entry: FragmentType<typeof EPISODE_TAG_ENTRY>;
|
||||
}
|
||||
|
||||
export function EpisodeTag({ entry: entryFragment }: EpisodeTagProps) {
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const entry = getFragmentData(EPISODE_TAG_ENTRY, entryFragment);
|
||||
|
||||
return (
|
||||
<Tag icon={faFilm} title={entry.episodes ? `Used in episode ${entry.episodes}` : "Used in all episodes"}>
|
||||
|
||||
@@ -3,21 +3,19 @@ import { ContentWarningTags } from "@/components/tag/ContentWarningTags";
|
||||
import { EpisodeTag } from "@/components/tag/EpisodeTag";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
entry: graphql(`
|
||||
fragment ThemeEntryTagsEntry on AnimeThemeEntry {
|
||||
...EpisodeTagEntry
|
||||
...ContentWarningTagsEntry
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const THEME_ENTRY_TAGS_ENTRY = graphql(`
|
||||
fragment ThemeEntryTagsEntry on AnimeThemeEntry {
|
||||
...EpisodeTagEntry
|
||||
...ContentWarningTagsEntry
|
||||
}
|
||||
`);
|
||||
|
||||
interface ThemeEntryTagsProps {
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
entry: FragmentType<typeof THEME_ENTRY_TAGS_ENTRY>;
|
||||
}
|
||||
|
||||
export function ThemeEntryTags({ entry: entryFragment }: ThemeEntryTagsProps) {
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const entry = getFragmentData(THEME_ENTRY_TAGS_ENTRY, entryFragment);
|
||||
|
||||
return (
|
||||
<Row style={{ "--gap": "8px", "--align-items": "baseline" }}>
|
||||
|
||||
@@ -11,26 +11,24 @@ const StyledVideoTags = styled(Row)`
|
||||
gap: 8px;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
video: graphql(`
|
||||
fragment VideoTagsVideo on Video {
|
||||
resolution
|
||||
nc
|
||||
subbed
|
||||
lyrics
|
||||
uncen
|
||||
source
|
||||
overlap
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const VIDEO_TAGS_VIDEO = graphql(`
|
||||
fragment VideoTagsVideo on Video {
|
||||
resolution
|
||||
nc
|
||||
subbed
|
||||
lyrics
|
||||
uncen
|
||||
source
|
||||
overlap
|
||||
}
|
||||
`);
|
||||
|
||||
interface VideoTagsProps {
|
||||
video: FragmentType<typeof fragments.video>;
|
||||
video: FragmentType<typeof VIDEO_TAGS_VIDEO>;
|
||||
}
|
||||
|
||||
export function VideoTags(props: VideoTagsProps) {
|
||||
const video = getFragmentData(fragments.video, props.video);
|
||||
const video = getFragmentData(VIDEO_TAGS_VIDEO, props.video);
|
||||
|
||||
return (
|
||||
<StyledVideoTags>
|
||||
|
||||
@@ -2,21 +2,19 @@ import { Text } from "@/components/text/Text";
|
||||
import { Toast } from "@/components/toast/Toast";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
playlist: graphql(`
|
||||
fragment PlaylistRemoveToastPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const PLAYLIST_REMOVE_TOAST_PLAYLIST = graphql(`
|
||||
fragment PlaylistRemoveToastPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
}
|
||||
`);
|
||||
|
||||
interface PlaylistRemoveToastProps {
|
||||
playlist: FragmentType<typeof fragments.playlist>;
|
||||
playlist: FragmentType<typeof PLAYLIST_REMOVE_TOAST_PLAYLIST>;
|
||||
}
|
||||
|
||||
export function PlaylistRemoveToast({ playlist: playlistFragment }: PlaylistRemoveToastProps) {
|
||||
const playlist = getFragmentData(fragments.playlist, playlistFragment);
|
||||
const playlist = getFragmentData(PLAYLIST_REMOVE_TOAST_PLAYLIST, playlistFragment);
|
||||
|
||||
return (
|
||||
<Toast>
|
||||
|
||||
@@ -6,35 +6,34 @@ import { Toast } from "@/components/toast/Toast";
|
||||
import { SongTitle } from "@/components/utils/SongTitle";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
playlist: graphql(`
|
||||
fragment PlaylistTrackAddToastPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment PlaylistTrackAddToastEntry on AnimeThemeEntry {
|
||||
animetheme {
|
||||
song {
|
||||
...SongTitleSong
|
||||
}
|
||||
export const PLAYLIST_TRACK_ADD_TOAST_PLAYLIST = graphql(`
|
||||
fragment PlaylistTrackAddToastPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_TRACK_ADD_TOAST_ENTRY = graphql(`
|
||||
fragment PlaylistTrackAddToastEntry on AnimeThemeEntry {
|
||||
animetheme {
|
||||
song {
|
||||
...SongTitleSong
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface PlaylistTrackAddToastProps {
|
||||
playlist: FragmentType<typeof fragments.playlist>;
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
playlist: FragmentType<typeof PLAYLIST_TRACK_ADD_TOAST_PLAYLIST>;
|
||||
entry: FragmentType<typeof PLAYLIST_TRACK_ADD_TOAST_ENTRY>;
|
||||
}
|
||||
|
||||
export function PlaylistTrackAddToast({
|
||||
playlist: playlistFragment,
|
||||
entry: entryFragment,
|
||||
}: PlaylistTrackAddToastProps) {
|
||||
const playlist = getFragmentData(fragments.playlist, playlistFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const playlist = getFragmentData(PLAYLIST_TRACK_ADD_TOAST_PLAYLIST, playlistFragment);
|
||||
const entry = getFragmentData(PLAYLIST_TRACK_ADD_TOAST_ENTRY, entryFragment);
|
||||
|
||||
return (
|
||||
<Toast as={Link} href={`/playlist/${playlist.id}`} $hoverable>
|
||||
|
||||
@@ -6,35 +6,34 @@ import { Toast } from "@/components/toast/Toast";
|
||||
import { SongTitle } from "@/components/utils/SongTitle";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
playlist: graphql(`
|
||||
fragment PlaylistTrackRemoveToastPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment PlaylistTrackRemoveToastEntry on AnimeThemeEntry {
|
||||
animetheme {
|
||||
song {
|
||||
...SongTitleSong
|
||||
}
|
||||
export const PLAYLIST_TRACK_REMOVE_TOAST_PLAYLIST = graphql(`
|
||||
fragment PlaylistTrackRemoveToastPlaylist on Playlist {
|
||||
id
|
||||
name
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_TRACK_REMOVE_TOAST_ENTRY = graphql(`
|
||||
fragment PlaylistTrackRemoveToastEntry on AnimeThemeEntry {
|
||||
animetheme {
|
||||
song {
|
||||
...SongTitleSong
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface PlaylistTrackRemoveToastProps {
|
||||
playlist: FragmentType<typeof fragments.playlist>;
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
playlist: FragmentType<typeof PLAYLIST_TRACK_REMOVE_TOAST_PLAYLIST>;
|
||||
entry: FragmentType<typeof PLAYLIST_TRACK_REMOVE_TOAST_ENTRY>;
|
||||
}
|
||||
|
||||
export function PlaylistTrackRemoveToast({
|
||||
playlist: playlistFragment,
|
||||
entry: entryFragment,
|
||||
}: PlaylistTrackRemoveToastProps) {
|
||||
const playlist = getFragmentData(fragments.playlist, playlistFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const playlist = getFragmentData(PLAYLIST_TRACK_REMOVE_TOAST_PLAYLIST, playlistFragment);
|
||||
const entry = getFragmentData(PLAYLIST_TRACK_REMOVE_TOAST_ENTRY, entryFragment);
|
||||
|
||||
return (
|
||||
<Toast as={Link} href={`/playlist/${playlist.id}`} $hoverable>
|
||||
|
||||
@@ -21,38 +21,37 @@ const StyledArtistLink = styled(Text).attrs({ as: "a", link: true })`
|
||||
font-size: 1rem;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
song: graphql(`
|
||||
fragment PerformancesSong on Song {
|
||||
performances {
|
||||
alias
|
||||
as
|
||||
artist {
|
||||
__typename
|
||||
... on Artist {
|
||||
export const PERFORMANCES_SONG = graphql(`
|
||||
fragment PerformancesSong on Song {
|
||||
performances {
|
||||
alias
|
||||
as
|
||||
artist {
|
||||
__typename
|
||||
... on Artist {
|
||||
slug
|
||||
name
|
||||
}
|
||||
... on Membership {
|
||||
group {
|
||||
slug
|
||||
name
|
||||
}
|
||||
... on Membership {
|
||||
group {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
artist: graphql(`
|
||||
fragment PerformancesArtist on Artist {
|
||||
slug
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export const PERFORMANCES_ARTIST = graphql(`
|
||||
fragment PerformancesArtist on Artist {
|
||||
slug
|
||||
}
|
||||
`);
|
||||
|
||||
export interface PerformancesProps {
|
||||
song: FragmentType<typeof fragments.song> | null;
|
||||
artist?: FragmentType<typeof fragments.artist>;
|
||||
song: FragmentType<typeof PERFORMANCES_SONG> | null;
|
||||
artist?: FragmentType<typeof PERFORMANCES_ARTIST>;
|
||||
maxPerformances?: number | null;
|
||||
expandable?: boolean;
|
||||
}
|
||||
@@ -82,8 +81,8 @@ export function Performances({
|
||||
maxPerformances = 3,
|
||||
expandable = false,
|
||||
}: PerformancesProps) {
|
||||
const song = getFragmentData(fragments.song, songFragment);
|
||||
const artist = getFragmentData(fragments.artist, artistFragment);
|
||||
const song = getFragmentData(PERFORMANCES_SONG, songFragment);
|
||||
const artist = getFragmentData(PERFORMANCES_ARTIST, artistFragment);
|
||||
const [expandPerformances, setExpandPerformances] = useState(false);
|
||||
|
||||
if (!song?.performances.length) {
|
||||
|
||||
@@ -4,21 +4,19 @@ import Link from "next/link";
|
||||
import { Text } from "@/components/text/Text";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
song: graphql(`
|
||||
fragment SongTitleSong on Song {
|
||||
title
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const SONG_TITLE_SONG = graphql(`
|
||||
fragment SongTitleSong on Song {
|
||||
title
|
||||
}
|
||||
`);
|
||||
|
||||
export interface SongTitleProps extends ComponentPropsWithoutRef<typeof Text> {
|
||||
song: FragmentType<typeof fragments.song> | null;
|
||||
song: FragmentType<typeof SONG_TITLE_SONG> | null;
|
||||
href?: ComponentPropsWithoutRef<typeof Link>["href"];
|
||||
}
|
||||
|
||||
export function SongTitle({ song: songFragment, href, ...props }: SongTitleProps) {
|
||||
const song = getFragmentData(fragments.song, songFragment);
|
||||
const song = getFragmentData(SONG_TITLE_SONG, songFragment);
|
||||
const songTitle = song?.title || "T.B.A.";
|
||||
|
||||
if (href) {
|
||||
|
||||
@@ -3,24 +3,23 @@ import { Performances } from "@/components/utils/Performances";
|
||||
import { SongTitle } from "@/components/utils/SongTitle";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
song: graphql(`
|
||||
fragment SongTitleWithArtistsSong on Song {
|
||||
...SongTitleSong
|
||||
...PerformancesSong
|
||||
}
|
||||
`),
|
||||
artist: graphql(`
|
||||
fragment SongTitleWithArtistsArtist on Artist {
|
||||
...PerformancesArtist
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const SONG_TITLE_WITH_ARTISTS_SONG = graphql(`
|
||||
fragment SongTitleWithArtistsSong on Song {
|
||||
...SongTitleSong
|
||||
...PerformancesSong
|
||||
}
|
||||
`);
|
||||
|
||||
export const SONG_TITLE_WITH_ARTISTS_ARTIST = graphql(`
|
||||
fragment SongTitleWithArtistsArtist on Artist {
|
||||
...PerformancesArtist
|
||||
}
|
||||
`);
|
||||
|
||||
interface SongTitleWithArtistsProps {
|
||||
song: FragmentType<typeof fragments.song> | null;
|
||||
song: FragmentType<typeof SONG_TITLE_WITH_ARTISTS_SONG> | null;
|
||||
songTitleLinkTo?: string;
|
||||
artist?: FragmentType<typeof fragments.artist>;
|
||||
artist?: FragmentType<typeof SONG_TITLE_WITH_ARTISTS_ARTIST>;
|
||||
onPlay?: () => void;
|
||||
}
|
||||
|
||||
@@ -31,8 +30,8 @@ export function SongTitleWithArtists({
|
||||
artist: artistFragment,
|
||||
onPlay,
|
||||
}: SongTitleWithArtistsProps) {
|
||||
const song = getFragmentData(fragments.song, songFragment);
|
||||
const artist = getFragmentData(fragments.artist, artistFragment);
|
||||
const song = getFragmentData(SONG_TITLE_WITH_ARTISTS_SONG, songFragment);
|
||||
const artist = getFragmentData(SONG_TITLE_WITH_ARTISTS_ARTIST, artistFragment);
|
||||
|
||||
return (
|
||||
<Text onClick={onPlay}>
|
||||
|
||||
@@ -28,39 +28,38 @@ import createVideoSlug from "@/utils/createVideoSlug";
|
||||
import extractImages from "@/utils/extractImages";
|
||||
import { AudioMode, GlobalVolume, Muted } from "@/utils/settings";
|
||||
|
||||
const fragments = {
|
||||
video: graphql(`
|
||||
fragment VideoPlayerVideo on Video {
|
||||
...VideoPlayerBarVideo
|
||||
...createVideoSlugVideo
|
||||
export const VIDEO_PLAYER_VIDEO = graphql(`
|
||||
fragment VideoPlayerVideo on Video {
|
||||
...VideoPlayerBarVideo
|
||||
...createVideoSlugVideo
|
||||
basename
|
||||
audio {
|
||||
basename
|
||||
audio {
|
||||
basename
|
||||
}
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment VideoPlayerEntry on AnimeThemeEntry {
|
||||
...VideoPlayerBarEntry
|
||||
...createVideoSlugEntry
|
||||
animetheme {
|
||||
...createVideoSlugTheme
|
||||
anime {
|
||||
slug
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const VIDEO_PLAYER_ENTRY = graphql(`
|
||||
fragment VideoPlayerEntry on AnimeThemeEntry {
|
||||
...VideoPlayerBarEntry
|
||||
...createVideoSlugEntry
|
||||
animetheme {
|
||||
...createVideoSlugTheme
|
||||
anime {
|
||||
slug
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface VideoPlayerContextValue {
|
||||
video: ResultOf<typeof fragments.video>;
|
||||
entry: ResultOf<typeof fragments.entry>;
|
||||
video: ResultOf<typeof VIDEO_PLAYER_VIDEO>;
|
||||
entry: ResultOf<typeof VIDEO_PLAYER_ENTRY>;
|
||||
background: boolean;
|
||||
videoPagePath: string;
|
||||
playerRef: RefObject<HTMLVideoElement | HTMLAudioElement | null>;
|
||||
@@ -89,8 +88,8 @@ type VideoPlayerProps = {
|
||||
|
||||
export function VideoPlayer({ watchListItem, background, children, overlay, ...props }: VideoPlayerProps) {
|
||||
const { video: videoFragment, entry: entryFragment } = watchListItem;
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const video = getFragmentData(VIDEO_PLAYER_VIDEO, videoFragment);
|
||||
const entry = getFragmentData(VIDEO_PLAYER_ENTRY, entryFragment);
|
||||
const theme = entry.animetheme;
|
||||
const anime = theme.anime;
|
||||
|
||||
@@ -131,8 +130,8 @@ export function VideoPlayer({ watchListItem, background, children, overlay, ...p
|
||||
const playbackAreaMouseRelaxProps = useMouseRelax();
|
||||
|
||||
const previousWatchListItem = getRelativeWatchListItem(-1);
|
||||
const previousVideo = getFragmentData(fragments.video, previousWatchListItem?.video);
|
||||
const previousEntry = getFragmentData(fragments.entry, previousWatchListItem?.entry);
|
||||
const previousVideo = getFragmentData(VIDEO_PLAYER_VIDEO, previousWatchListItem?.video);
|
||||
const previousEntry = getFragmentData(VIDEO_PLAYER_ENTRY, previousWatchListItem?.entry);
|
||||
const previousTheme = previousEntry?.animetheme;
|
||||
const previousAnime = previousTheme?.anime;
|
||||
|
||||
@@ -154,8 +153,8 @@ export function VideoPlayer({ watchListItem, background, children, overlay, ...p
|
||||
);
|
||||
|
||||
const nextWatchListItem = getRelativeWatchListItem(1);
|
||||
const nextVideo = getFragmentData(fragments.video, nextWatchListItem?.video);
|
||||
const nextEntry = getFragmentData(fragments.entry, nextWatchListItem?.entry);
|
||||
const nextVideo = getFragmentData(VIDEO_PLAYER_VIDEO, nextWatchListItem?.video);
|
||||
const nextEntry = getFragmentData(VIDEO_PLAYER_ENTRY, nextWatchListItem?.entry);
|
||||
const nextTheme = nextEntry?.animetheme;
|
||||
const nextAnime = nextTheme?.anime;
|
||||
|
||||
|
||||
@@ -86,37 +86,36 @@ const StyledVolumeControl = styled(VolumeControl)`
|
||||
margin-right: auto;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
video: graphql(`
|
||||
fragment VideoPlayerBarVideo on Video {
|
||||
__typename
|
||||
# ...PlaylistTrackAddDialogVideo
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment VideoPlayerBarEntry on AnimeThemeEntry {
|
||||
# ...PlaylistTrackAddDialogEntry
|
||||
animetheme {
|
||||
type
|
||||
sequence
|
||||
song {
|
||||
...SongTitleSong
|
||||
...PerformancesSong
|
||||
performances {
|
||||
__typename
|
||||
}
|
||||
}
|
||||
group {
|
||||
name
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
export const VIDEO_PLAYER_BAR_VIDEO = graphql(`
|
||||
fragment VideoPlayerBarVideo on Video {
|
||||
__typename
|
||||
# ...PlaylistTrackAddDialogVideo
|
||||
}
|
||||
`);
|
||||
|
||||
export const VIDEO_PLAYER_BAR_ENTRY = graphql(`
|
||||
fragment VideoPlayerBarEntry on AnimeThemeEntry {
|
||||
# ...PlaylistTrackAddDialogEntry
|
||||
animetheme {
|
||||
type
|
||||
sequence
|
||||
song {
|
||||
...SongTitleSong
|
||||
...PerformancesSong
|
||||
performances {
|
||||
__typename
|
||||
}
|
||||
}
|
||||
group {
|
||||
name
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export function VideoPlayerBar() {
|
||||
const context = useContext(VideoPlayerContext);
|
||||
@@ -140,8 +139,8 @@ export function VideoPlayerBar() {
|
||||
audioUrl,
|
||||
} = context;
|
||||
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const video = getFragmentData(VIDEO_PLAYER_BAR_VIDEO, videoFragment);
|
||||
const entry = getFragmentData(VIDEO_PLAYER_BAR_ENTRY, entryFragment);
|
||||
const theme = entry.animetheme;
|
||||
const anime = theme.anime;
|
||||
|
||||
|
||||
@@ -16,22 +16,20 @@ const StyledCodeBlock = styled.pre`
|
||||
}
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
video: graphql(`
|
||||
fragment VideoScriptVideo on Video {
|
||||
videoscript {
|
||||
link
|
||||
}
|
||||
export const VIDEO_SCRIPT_VIDEO = graphql(`
|
||||
fragment VideoScriptVideo on Video {
|
||||
videoscript {
|
||||
link
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface Props {
|
||||
video: FragmentType<typeof fragments.video>;
|
||||
video: FragmentType<typeof VIDEO_SCRIPT_VIDEO>;
|
||||
}
|
||||
|
||||
export default function VideoScript({ video: videoFragment }: Props) {
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const video = getFragmentData(VIDEO_SCRIPT_VIDEO, videoFragment);
|
||||
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
const [videoScript, setVideoScript] = useState<string>();
|
||||
|
||||
+140
-170
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -45,14 +45,12 @@ const ArrowLink = styled(Link)`
|
||||
gap: 8px;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
page: graphql(`
|
||||
fragment DocumentPagePage on Page {
|
||||
name
|
||||
createdAt
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const DOCUMENT_PAGE_PAGE = graphql(`
|
||||
fragment DocumentPagePage on Page {
|
||||
name
|
||||
createdAt
|
||||
}
|
||||
`);
|
||||
|
||||
const propsQuery = graphql(`
|
||||
query DocumentPage($pageSlug: String!) {
|
||||
@@ -74,7 +72,7 @@ const pathsQuery = graphql(`
|
||||
`);
|
||||
|
||||
export interface DocumentPageProps extends SharedPageProps {
|
||||
page: FragmentType<typeof fragments.page>;
|
||||
page: FragmentType<typeof DOCUMENT_PAGE_PAGE>;
|
||||
source: MDXRemoteSerializeResult;
|
||||
headings: Heading[];
|
||||
}
|
||||
@@ -84,7 +82,7 @@ interface DocumentPageParams extends ParsedUrlQuery {
|
||||
}
|
||||
|
||||
export default function DocumentPage({ page: pageFragment, source, headings }: DocumentPageProps) {
|
||||
const page = getFragmentData(fragments.page, pageFragment);
|
||||
const page = getFragmentData(DOCUMENT_PAGE_PAGE, pageFragment);
|
||||
const author = typeof source.frontmatter?.author === "string" ? source.frontmatter.author : undefined;
|
||||
|
||||
return (
|
||||
|
||||
@@ -31,97 +31,95 @@ import fetchStaticPaths from "@/utils/fetchStaticPaths";
|
||||
import type { SharedPageProps } from "@/utils/getSharedPageProps";
|
||||
import getSharedPageProps from "@/utils/getSharedPageProps";
|
||||
|
||||
const fragments = {
|
||||
anime: graphql(`
|
||||
fragment VideoPageAnime on Anime {
|
||||
...AnimeSummaryCardAnime
|
||||
name
|
||||
slug
|
||||
year
|
||||
season
|
||||
animethemes {
|
||||
...ThemeSummaryCardTheme
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
song {
|
||||
title
|
||||
performances {
|
||||
artist {
|
||||
...ArtistSummaryCardArtist
|
||||
}
|
||||
as
|
||||
export const VIDEO_PAGE_ANIME = graphql(`
|
||||
fragment VideoPageAnime on Anime {
|
||||
...AnimeSummaryCardAnime
|
||||
name
|
||||
slug
|
||||
year
|
||||
season
|
||||
animethemes {
|
||||
...ThemeSummaryCardTheme
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
song {
|
||||
title
|
||||
performances {
|
||||
artist {
|
||||
...ArtistSummaryCardArtist
|
||||
}
|
||||
as
|
||||
}
|
||||
group {
|
||||
slug
|
||||
}
|
||||
animethemeentries {
|
||||
...VideoPlayerEntry
|
||||
...createVideoSlugEntry
|
||||
id
|
||||
episodes
|
||||
nsfw
|
||||
spoiler
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
...VideoPlayerVideo
|
||||
...VideoScriptVideo
|
||||
...createVideoSlugVideo
|
||||
id
|
||||
basename
|
||||
filename
|
||||
lyrics
|
||||
nc
|
||||
overlap
|
||||
resolution
|
||||
source
|
||||
subbed
|
||||
uncen
|
||||
tags
|
||||
animethemeentries {
|
||||
nodes {
|
||||
animetheme {
|
||||
...ThemeSummaryCardTheme
|
||||
anime {
|
||||
slug
|
||||
}
|
||||
}
|
||||
group {
|
||||
slug
|
||||
}
|
||||
animethemeentries {
|
||||
...VideoPlayerEntry
|
||||
...createVideoSlugEntry
|
||||
id
|
||||
episodes
|
||||
nsfw
|
||||
spoiler
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
...VideoPlayerVideo
|
||||
...VideoScriptVideo
|
||||
...createVideoSlugVideo
|
||||
id
|
||||
basename
|
||||
filename
|
||||
lyrics
|
||||
nc
|
||||
overlap
|
||||
resolution
|
||||
source
|
||||
subbed
|
||||
uncen
|
||||
tags
|
||||
animethemeentries {
|
||||
nodes {
|
||||
animetheme {
|
||||
...ThemeSummaryCardTheme
|
||||
anime {
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
tracks {
|
||||
playlist {
|
||||
...PlaylistSummaryCardPlaylist
|
||||
...PlaylistSummaryCardPlaylistWithOwner
|
||||
id
|
||||
}
|
||||
}
|
||||
tracks {
|
||||
playlist {
|
||||
...PlaylistSummaryCardPlaylist
|
||||
...PlaylistSummaryCardPlaylistWithOwner
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
series {
|
||||
nodes {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
studios {
|
||||
nodes {
|
||||
...StudioSummaryCardStudio
|
||||
slug
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
series {
|
||||
nodes {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
studios {
|
||||
nodes {
|
||||
...StudioSummaryCardStudio
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const propsQuery = graphql(`
|
||||
query VideoPage($animeSlug: String!) {
|
||||
@@ -153,12 +151,12 @@ const pathsQuery = graphql(`
|
||||
}
|
||||
`);
|
||||
|
||||
export function getAnimeFromVideoPageFragment(fragment: FragmentType<typeof fragments.anime>) {
|
||||
return getFragmentData(fragments.anime, fragment);
|
||||
export function getAnimeFromVideoPageFragment(fragment: FragmentType<typeof VIDEO_PAGE_ANIME>) {
|
||||
return getFragmentData(VIDEO_PAGE_ANIME, fragment);
|
||||
}
|
||||
|
||||
export interface VideoPageProps extends SharedPageProps {
|
||||
anime: FragmentType<typeof fragments.anime>;
|
||||
anime: FragmentType<typeof VIDEO_PAGE_ANIME>;
|
||||
themeIndex: number;
|
||||
entryIndex: number;
|
||||
videoIndex: number;
|
||||
@@ -440,7 +438,7 @@ export default function VideoPage({
|
||||
);
|
||||
}
|
||||
|
||||
const buildTimeCache: Map<string, FragmentType<typeof fragments.anime>> = new Map();
|
||||
const buildTimeCache: Map<string, FragmentType<typeof VIDEO_PAGE_ANIME>> = new Map();
|
||||
|
||||
export const getStaticProps: GetStaticProps<VideoPageProps, VideoPageParams> = async ({ params }) => {
|
||||
const client = createApolloClient();
|
||||
@@ -462,7 +460,7 @@ export const getStaticProps: GetStaticProps<VideoPageProps, VideoPageParams> = a
|
||||
};
|
||||
}
|
||||
|
||||
const anime = getFragmentData(fragments.anime, animeFragment);
|
||||
const anime = getFragmentData(VIDEO_PAGE_ANIME, animeFragment);
|
||||
|
||||
if (anime) {
|
||||
for (const [themeIndex, theme] of anime.animethemes.entries()) {
|
||||
|
||||
@@ -34,52 +34,50 @@ const StyledList = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
anime: graphql(`
|
||||
fragment AnimeDetailPageAnime on Anime {
|
||||
slug
|
||||
name
|
||||
season
|
||||
seasonLocalized
|
||||
year
|
||||
synopsis
|
||||
mediaFormatLocalized
|
||||
animesynonyms {
|
||||
text
|
||||
}
|
||||
series {
|
||||
nodes {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
studios {
|
||||
nodes {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
resources {
|
||||
edges {
|
||||
node {
|
||||
site
|
||||
siteLocalized
|
||||
link
|
||||
}
|
||||
as
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
animethemes {
|
||||
...AnimeThemeFilterTheme
|
||||
export const ANIME_DETAIL_PAGE_ANIME = graphql(`
|
||||
fragment AnimeDetailPageAnime on Anime {
|
||||
slug
|
||||
name
|
||||
season
|
||||
seasonLocalized
|
||||
year
|
||||
synopsis
|
||||
mediaFormatLocalized
|
||||
animesynonyms {
|
||||
text
|
||||
}
|
||||
series {
|
||||
nodes {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
studios {
|
||||
nodes {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
resources {
|
||||
edges {
|
||||
node {
|
||||
site
|
||||
siteLocalized
|
||||
link
|
||||
}
|
||||
as
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
animethemes {
|
||||
...AnimeThemeFilterTheme
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const propsQuery = graphql(`
|
||||
query AnimeDetailPage($animeSlug: String!) {
|
||||
@@ -101,7 +99,7 @@ const pathsQuery = graphql(`
|
||||
`);
|
||||
|
||||
interface AnimeDetailPageProps extends SharedPageProps {
|
||||
anime: FragmentType<typeof fragments.anime>;
|
||||
anime: FragmentType<typeof ANIME_DETAIL_PAGE_ANIME>;
|
||||
synopsisMarkdownSource: MDXRemoteSerializeResult | null;
|
||||
}
|
||||
|
||||
@@ -110,7 +108,7 @@ interface AnimeDetailPageParams extends ParsedUrlQuery {
|
||||
}
|
||||
|
||||
export default function AnimeDetailPage({ anime: animeFragment, synopsisMarkdownSource }: AnimeDetailPageProps) {
|
||||
const anime = getFragmentData(fragments.anime, animeFragment);
|
||||
const anime = getFragmentData(ANIME_DETAIL_PAGE_ANIME, animeFragment);
|
||||
|
||||
const [collapseSynopsis, setCollapseSynopsis] = useState(true);
|
||||
const { smallCover, largeCover } = extractImages(anime.images.nodes);
|
||||
@@ -210,7 +208,7 @@ export default function AnimeDetailPage({ anime: animeFragment, synopsisMarkdown
|
||||
);
|
||||
}
|
||||
|
||||
const buildTimeCache: Map<string, FragmentType<typeof fragments.anime>> = new Map();
|
||||
const buildTimeCache: Map<string, FragmentType<typeof ANIME_DETAIL_PAGE_ANIME>> = new Map();
|
||||
|
||||
export const getStaticProps: GetStaticProps<AnimeDetailPageProps, AnimeDetailPageParams> = async ({ params }) => {
|
||||
const client = createApolloClient();
|
||||
@@ -232,7 +230,7 @@ export const getStaticProps: GetStaticProps<AnimeDetailPageProps, AnimeDetailPag
|
||||
};
|
||||
}
|
||||
|
||||
const anime = getFragmentData(fragments.anime, animeFragment);
|
||||
const anime = getFragmentData(ANIME_DETAIL_PAGE_ANIME, animeFragment);
|
||||
|
||||
return {
|
||||
props: {
|
||||
|
||||
@@ -58,12 +58,71 @@ const StyledHeader = styled.div`
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
artist: graphql(`
|
||||
fragment ArtistDetailPageArtist on Artist {
|
||||
...ThemeSummaryCardArtist
|
||||
slug
|
||||
name
|
||||
export const ARTIST_DETAIL_PAGE_ARTIST = graphql(`
|
||||
fragment ArtistDetailPageArtist on Artist {
|
||||
...ThemeSummaryCardArtist
|
||||
slug
|
||||
name
|
||||
performances {
|
||||
alias
|
||||
as
|
||||
song {
|
||||
id
|
||||
title
|
||||
performances {
|
||||
artist {
|
||||
__typename
|
||||
... on Artist {
|
||||
slug
|
||||
name
|
||||
}
|
||||
... on Membership {
|
||||
group {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
alias
|
||||
as
|
||||
}
|
||||
animethemes {
|
||||
...ThemeSummaryCardTheme
|
||||
...ThemeSummaryCardThemeExpandable
|
||||
id
|
||||
type
|
||||
sequence
|
||||
animethemeentries {
|
||||
videos {
|
||||
nodes {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
year
|
||||
season
|
||||
}
|
||||
song {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memberships {
|
||||
alias
|
||||
as
|
||||
group {
|
||||
...ThemeSummaryCardArtist
|
||||
slug
|
||||
name
|
||||
}
|
||||
performances {
|
||||
alias
|
||||
as
|
||||
@@ -116,168 +175,107 @@ const fragments = {
|
||||
}
|
||||
}
|
||||
}
|
||||
memberships {
|
||||
}
|
||||
groupships {
|
||||
alias
|
||||
as
|
||||
member {
|
||||
slug
|
||||
name
|
||||
}
|
||||
performances {
|
||||
alias
|
||||
as
|
||||
group {
|
||||
...ThemeSummaryCardArtist
|
||||
slug
|
||||
name
|
||||
}
|
||||
performances {
|
||||
alias
|
||||
as
|
||||
song {
|
||||
id
|
||||
title
|
||||
performances {
|
||||
artist {
|
||||
__typename
|
||||
... on Artist {
|
||||
song {
|
||||
id
|
||||
title
|
||||
performances {
|
||||
artist {
|
||||
__typename
|
||||
... on Artist {
|
||||
slug
|
||||
name
|
||||
}
|
||||
... on Membership {
|
||||
group {
|
||||
slug
|
||||
name
|
||||
}
|
||||
... on Membership {
|
||||
group {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
alias
|
||||
as
|
||||
}
|
||||
animethemes {
|
||||
...ThemeSummaryCardTheme
|
||||
...ThemeSummaryCardThemeExpandable
|
||||
id
|
||||
type
|
||||
sequence
|
||||
animethemeentries {
|
||||
videos {
|
||||
nodes {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
year
|
||||
season
|
||||
}
|
||||
song {
|
||||
title
|
||||
}
|
||||
}
|
||||
alias
|
||||
as
|
||||
}
|
||||
}
|
||||
}
|
||||
groupships {
|
||||
alias
|
||||
as
|
||||
member {
|
||||
slug
|
||||
name
|
||||
}
|
||||
performances {
|
||||
alias
|
||||
as
|
||||
song {
|
||||
animethemes {
|
||||
...ThemeSummaryCardTheme
|
||||
...ThemeSummaryCardThemeExpandable
|
||||
id
|
||||
title
|
||||
performances {
|
||||
artist {
|
||||
__typename
|
||||
... on Artist {
|
||||
slug
|
||||
name
|
||||
type
|
||||
sequence
|
||||
animethemeentries {
|
||||
videos {
|
||||
nodes {
|
||||
id
|
||||
}
|
||||
... on Membership {
|
||||
group {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
alias
|
||||
as
|
||||
}
|
||||
animethemes {
|
||||
...ThemeSummaryCardTheme
|
||||
...ThemeSummaryCardThemeExpandable
|
||||
id
|
||||
type
|
||||
sequence
|
||||
animethemeentries {
|
||||
videos {
|
||||
nodes {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
year
|
||||
season
|
||||
}
|
||||
song {
|
||||
title
|
||||
}
|
||||
}
|
||||
group {
|
||||
name
|
||||
slug
|
||||
}
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
year
|
||||
season
|
||||
}
|
||||
song {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
members {
|
||||
edges {
|
||||
alias
|
||||
as
|
||||
notes
|
||||
node {
|
||||
...ArtistSummaryCardArtist
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
groups {
|
||||
edges {
|
||||
alias
|
||||
as
|
||||
notes
|
||||
node {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
images {
|
||||
edges {
|
||||
...extractMultipleImagesImageArtistEdge
|
||||
}
|
||||
}
|
||||
resources {
|
||||
edges {
|
||||
node {
|
||||
link
|
||||
site
|
||||
siteLocalized
|
||||
}
|
||||
as
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
members {
|
||||
edges {
|
||||
alias
|
||||
as
|
||||
notes
|
||||
node {
|
||||
...ArtistSummaryCardArtist
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
groups {
|
||||
edges {
|
||||
alias
|
||||
as
|
||||
notes
|
||||
node {
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
images {
|
||||
edges {
|
||||
...extractMultipleImagesImageArtistEdge
|
||||
}
|
||||
}
|
||||
resources {
|
||||
edges {
|
||||
node {
|
||||
link
|
||||
site
|
||||
siteLocalized
|
||||
}
|
||||
as
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const propsQuery = graphql(`
|
||||
query ArtistDetailPage($artistSlug: String!) {
|
||||
@@ -301,8 +299,8 @@ const pathsQuery = graphql(`
|
||||
`);
|
||||
|
||||
type Performance =
|
||||
| ResultOf<typeof fragments.artist>["performances"][number]
|
||||
| ResultOf<typeof fragments.artist>["groupships"][number]["performances"][number];
|
||||
| ResultOf<typeof ARTIST_DETAIL_PAGE_ARTIST>["performances"][number]
|
||||
| ResultOf<typeof ARTIST_DETAIL_PAGE_ARTIST>["groupships"][number]["performances"][number];
|
||||
|
||||
function getPerformanceFilter(key: string | null): (performance: Performance) => boolean {
|
||||
switch (key) {
|
||||
@@ -316,7 +314,7 @@ function getPerformanceFilter(key: string | null): (performance: Performance) =>
|
||||
}
|
||||
|
||||
interface ArtistDetailPageProps {
|
||||
artist: FragmentType<typeof fragments.artist>;
|
||||
artist: FragmentType<typeof ARTIST_DETAIL_PAGE_ARTIST>;
|
||||
informationMarkdownSource: MDXRemoteSerializeResult | null;
|
||||
}
|
||||
|
||||
@@ -325,7 +323,7 @@ interface ArtistDetailPageParams extends ParsedUrlQuery {
|
||||
}
|
||||
|
||||
export default function ArtistDetailPage({ artist: artistFragment, informationMarkdownSource }: ArtistDetailPageProps) {
|
||||
const artist = getFragmentData(fragments.artist, artistFragment);
|
||||
const artist = getFragmentData(ARTIST_DETAIL_PAGE_ARTIST, artistFragment);
|
||||
const images = extractMultipleImages(artist.images.edges);
|
||||
const [collapseInformation, setCollapseInformation] = useState(true);
|
||||
|
||||
@@ -624,7 +622,9 @@ export default function ArtistDetailPage({ artist: artistFragment, informationMa
|
||||
|
||||
interface ArtistThemesProps {
|
||||
themes: Performance["song"]["animethemes"];
|
||||
artist: ResultOf<typeof fragments.artist> | ResultOf<typeof fragments.artist>["memberships"][number]["group"];
|
||||
artist:
|
||||
| ResultOf<typeof ARTIST_DETAIL_PAGE_ARTIST>
|
||||
| ResultOf<typeof ARTIST_DETAIL_PAGE_ARTIST>["memberships"][number]["group"];
|
||||
}
|
||||
|
||||
const ArtistThemes = memo(function ArtistThemes({ themes, artist }: ArtistThemesProps) {
|
||||
@@ -661,7 +661,8 @@ const ArtistThemes = memo(function ArtistThemes({ themes, artist }: ArtistThemes
|
||||
return <>{themeCards}</>;
|
||||
});
|
||||
|
||||
const buildTimeCache: Map<string, FragmentType<typeof fragments.artist> & { information: string | null }> = new Map();
|
||||
const buildTimeCache: Map<string, FragmentType<typeof ARTIST_DETAIL_PAGE_ARTIST> & { information: string | null }> =
|
||||
new Map();
|
||||
|
||||
export const getStaticProps: GetStaticProps<ArtistDetailPageProps, ArtistDetailPageParams> = async ({ params }) => {
|
||||
const client = createApolloClient();
|
||||
|
||||
@@ -54,41 +54,40 @@ const StyledNomineeGrid = styled.div<{ style: { "--columns": number; "--rows": n
|
||||
}
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
theme: graphql(`
|
||||
fragment AnimeAwardsPageTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
song {
|
||||
...SongTitleWithArtistsSong
|
||||
}
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment AnimeAwardPageEntry on AnimeThemeEntry {
|
||||
...createVideoSlugEntry
|
||||
version
|
||||
videos {
|
||||
export const ANIME_AWARDS_PAGE_THEME = graphql(`
|
||||
fragment AnimeAwardsPageTheme on AnimeTheme {
|
||||
...createVideoSlugTheme
|
||||
id
|
||||
type
|
||||
sequence
|
||||
anime {
|
||||
slug
|
||||
name
|
||||
images {
|
||||
nodes {
|
||||
...createVideoSlugVideo
|
||||
basename
|
||||
tags
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
song {
|
||||
...SongTitleWithArtistsSong
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const ANIME_AWARD_PAGE_ENTRY = graphql(`
|
||||
fragment AnimeAwardPageEntry on AnimeThemeEntry {
|
||||
...createVideoSlugEntry
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
...createVideoSlugVideo
|
||||
basename
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
interface Nominee {
|
||||
id: number;
|
||||
@@ -101,8 +100,8 @@ interface HasVotes {
|
||||
}
|
||||
|
||||
interface HasTheme {
|
||||
theme: FragmentType<typeof fragments.theme>;
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
theme: FragmentType<typeof ANIME_AWARDS_PAGE_THEME>;
|
||||
entry: FragmentType<typeof ANIME_AWARD_PAGE_ENTRY>;
|
||||
}
|
||||
|
||||
type Award = AwardUnvoted | AwardVoted;
|
||||
@@ -171,8 +170,8 @@ function AwardSectionUnvoted({ award }: AwardSectionUnvotedProps) {
|
||||
const [typeFilter, setTypeFilter] = useState<string | null>(null);
|
||||
|
||||
const sortFn: Comparator<HasTheme> = (a, b) => {
|
||||
const nameA = getFragmentData(fragments.theme, a.theme)?.anime?.name;
|
||||
const nameB = getFragmentData(fragments.theme, b.theme)?.anime?.name;
|
||||
const nameA = getFragmentData(ANIME_AWARDS_PAGE_THEME, a.theme)?.anime?.name;
|
||||
const nameB = getFragmentData(ANIME_AWARDS_PAGE_THEME, b.theme)?.anime?.name;
|
||||
|
||||
return (nameA && nameB && nameA.localeCompare(nameB)) || 0;
|
||||
};
|
||||
@@ -295,8 +294,8 @@ const StyledRank = styled(Text)`
|
||||
`;
|
||||
|
||||
interface AwardThemeSummaryCardProps extends ComponentPropsWithoutRef<typeof StyledSummaryCardWrapper> {
|
||||
theme: FragmentType<typeof fragments.theme>;
|
||||
entry: FragmentType<typeof fragments.entry>;
|
||||
theme: FragmentType<typeof ANIME_AWARDS_PAGE_THEME>;
|
||||
entry: FragmentType<typeof ANIME_AWARD_PAGE_ENTRY>;
|
||||
rank?: number;
|
||||
votes?: number | null;
|
||||
}
|
||||
@@ -308,8 +307,8 @@ function AwardThemeSummaryCard({
|
||||
votes,
|
||||
...props
|
||||
}: AwardThemeSummaryCardProps) {
|
||||
const theme = getFragmentData(fragments.theme, themeFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const theme = getFragmentData(ANIME_AWARDS_PAGE_THEME, themeFragment);
|
||||
const entry = getFragmentData(ANIME_AWARD_PAGE_ENTRY, entryFragment);
|
||||
|
||||
if (!theme?.anime) {
|
||||
return null;
|
||||
|
||||
+17
-18
@@ -65,31 +65,30 @@ const Grid = styled.div<{ $columns: number }>`
|
||||
}
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
featuredTheme: graphql(`
|
||||
fragment HomePageFeaturedTheme on FeaturedTheme {
|
||||
animethemeentry {
|
||||
...FeaturedThemeEntry
|
||||
}
|
||||
video {
|
||||
...FeaturedThemeVideo
|
||||
}
|
||||
export const HOME_PAGE_FEATURED_THEME = graphql(`
|
||||
fragment HomePageFeaturedTheme on FeaturedTheme {
|
||||
animethemeentry {
|
||||
...FeaturedThemeEntry
|
||||
}
|
||||
`),
|
||||
announcement: graphql(`
|
||||
fragment HomePageAnnouncement on Announcement {
|
||||
content
|
||||
video {
|
||||
...FeaturedThemeVideo
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export const HOME_PAGE_ANNOUNCEMENT = graphql(`
|
||||
fragment HomePageAnnouncement on Announcement {
|
||||
content
|
||||
}
|
||||
`);
|
||||
|
||||
interface HomePageProps {
|
||||
featuredTheme: FragmentType<typeof fragments.featuredTheme> | null;
|
||||
featuredTheme: FragmentType<typeof HOME_PAGE_FEATURED_THEME> | null;
|
||||
announcementSources: MDXRemoteSerializeResult[];
|
||||
}
|
||||
|
||||
export default function HomePage({ featuredTheme: featuredThemeFragment, announcementSources }: HomePageProps) {
|
||||
const featuredTheme = getFragmentData(fragments.featuredTheme, featuredThemeFragment);
|
||||
const featuredTheme = getFragmentData(HOME_PAGE_FEATURED_THEME, featuredThemeFragment);
|
||||
|
||||
const { me } = useAuth();
|
||||
const { currentYear, currentSeason } = useCurrentSeason();
|
||||
@@ -259,7 +258,7 @@ export const getStaticProps: GetStaticProps<HomePageProps> = async () => {
|
||||
`),
|
||||
});
|
||||
|
||||
const announcements = getFragmentData(fragments.announcement, data.announcementPagination.data);
|
||||
const announcements = getFragmentData(HOME_PAGE_ANNOUNCEMENT, data.announcementPagination.data);
|
||||
|
||||
return {
|
||||
props: {
|
||||
|
||||
@@ -128,7 +128,7 @@ const comparators = {
|
||||
[ANIME_NEW_OLD]: sortTransformed(getComparator(ANIME_NEW_OLD), (track) => track.animethemeentry.animetheme?.anime),
|
||||
[RANK_ASC]: (a, b) => a.rank - b.rank,
|
||||
[RANK_DESC]: (a, b) => a.rank - b.rank,
|
||||
} satisfies Record<string, Comparator<ResultOf<typeof fragments.track> & { rank: number }>>;
|
||||
} satisfies Record<string, Comparator<ResultOf<typeof PLAYLIST_DETAIL_PAGE_TRACK> & { rank: number }>>;
|
||||
|
||||
type LinkedList<T> = Array<
|
||||
{
|
||||
@@ -163,60 +163,60 @@ function sortLinkedList<T>(list: LinkedList<T>) {
|
||||
return sortedList;
|
||||
}
|
||||
|
||||
const fragments = {
|
||||
playlist: graphql(`
|
||||
fragment PlaylistDetailPagePlaylist on Playlist {
|
||||
...PlaylistEditDialogPlaylist
|
||||
...PlaylistTrackRemoveDialogPlaylist
|
||||
id
|
||||
export const PLAYLIST_DETAIL_PAGE_PLAYLIST = graphql(`
|
||||
fragment PlaylistDetailPagePlaylist on Playlist {
|
||||
...PlaylistEditDialogPlaylist
|
||||
...PlaylistTrackRemoveDialogPlaylist
|
||||
id
|
||||
name
|
||||
description
|
||||
visibility
|
||||
tracksCount
|
||||
user {
|
||||
name
|
||||
description
|
||||
visibility
|
||||
tracksCount
|
||||
user {
|
||||
name
|
||||
}
|
||||
}
|
||||
`),
|
||||
track: graphql(`
|
||||
fragment PlaylistDetailPageTrack on PlaylistTrack {
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_DETAIL_PAGE_TRACK = graphql(`
|
||||
fragment PlaylistDetailPageTrack on PlaylistTrack {
|
||||
id
|
||||
video {
|
||||
...VideoSummaryCardVideo
|
||||
...FeaturedThemeVideo
|
||||
...PlaylistTrackAddDialogVideo
|
||||
...PlaylistTrackRemoveDialogVideo
|
||||
id
|
||||
video {
|
||||
...VideoSummaryCardVideo
|
||||
...FeaturedThemeVideo
|
||||
...PlaylistTrackAddDialogVideo
|
||||
...PlaylistTrackRemoveDialogVideo
|
||||
id
|
||||
}
|
||||
animethemeentry {
|
||||
...VideoSummaryCardEntry
|
||||
...FeaturedThemeEntry
|
||||
...PlaylistTrackAddDialogEntry
|
||||
...PlaylistTrackRemoveDialogEntry
|
||||
animetheme {
|
||||
anime {
|
||||
name
|
||||
year
|
||||
season
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
animethemeentry {
|
||||
...VideoSummaryCardEntry
|
||||
...FeaturedThemeEntry
|
||||
...PlaylistTrackAddDialogEntry
|
||||
...PlaylistTrackRemoveDialogEntry
|
||||
animetheme {
|
||||
anime {
|
||||
name
|
||||
year
|
||||
season
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
song {
|
||||
title
|
||||
}
|
||||
}
|
||||
song {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
me: graphql(`
|
||||
fragment PlaylistDetailPageMe on Me {
|
||||
name
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_DETAIL_PAGE_ME = graphql(`
|
||||
fragment PlaylistDetailPageMe on Me {
|
||||
name
|
||||
}
|
||||
`);
|
||||
|
||||
export const PLAYLIST_DETAIL_PAGE_PLAYLIST = graphql(`
|
||||
query PlaylistDetailPagePlaylist($playlistId: String!) {
|
||||
@@ -244,9 +244,9 @@ const meQuery = graphql(`
|
||||
`);
|
||||
|
||||
interface PlaylistDetailPageProps extends SharedPageProps {
|
||||
playlist: FragmentType<typeof fragments.playlist>;
|
||||
tracks: Array<FragmentType<typeof fragments.track>>;
|
||||
me: FragmentType<typeof fragments.me> | null;
|
||||
playlist: FragmentType<typeof PLAYLIST_DETAIL_PAGE_PLAYLIST>;
|
||||
tracks: Array<FragmentType<typeof PLAYLIST_DETAIL_PAGE_TRACK>>;
|
||||
me: FragmentType<typeof PLAYLIST_DETAIL_PAGE_ME> | null;
|
||||
}
|
||||
|
||||
interface PlaylistDetailPageParams extends ParsedUrlQuery {
|
||||
@@ -258,7 +258,7 @@ export default function PlaylistDetailPage({
|
||||
tracks: tracksFragment,
|
||||
me: meFragment,
|
||||
}: PlaylistDetailPageProps) {
|
||||
const initialPlaylist = getFragmentData(fragments.playlist, playlistFragment);
|
||||
const initialPlaylist = getFragmentData(PLAYLIST_DETAIL_PAGE_PLAYLIST, playlistFragment);
|
||||
|
||||
const { setWatchList, setWatchListFactory, setCurrentWatchListItem } = useContext(PlayerContext);
|
||||
const router = useRouter();
|
||||
@@ -268,9 +268,11 @@ export default function PlaylistDetailPage({
|
||||
});
|
||||
const { data: meData } = useQuery(meQuery);
|
||||
|
||||
const playlist = getFragmentData(fragments.playlist, playlistData?.playlist ?? playlistFragment);
|
||||
const tracks = sortLinkedList(getFragmentData(fragments.track, playlistData?.playlist.tracks ?? tracksFragment));
|
||||
const me = getFragmentData(fragments.me, meData?.me ?? meFragment);
|
||||
const playlist = getFragmentData(PLAYLIST_DETAIL_PAGE_PLAYLIST, playlistData?.playlist ?? playlistFragment);
|
||||
const tracks = sortLinkedList(
|
||||
getFragmentData(PLAYLIST_DETAIL_PAGE_TRACK, playlistData?.playlist.tracks ?? tracksFragment),
|
||||
);
|
||||
const me = getFragmentData(PLAYLIST_DETAIL_PAGE_ME, meData?.me ?? meFragment);
|
||||
|
||||
if (!playlist) {
|
||||
location.reload();
|
||||
@@ -465,7 +467,7 @@ export default function PlaylistDetailPage({
|
||||
}
|
||||
|
||||
interface DescriptionProps {
|
||||
playlist: ResultOf<typeof fragments.playlist>;
|
||||
playlist: ResultOf<typeof PLAYLIST_DETAIL_PAGE_PLAYLIST>;
|
||||
description: string;
|
||||
setDescription: (newValue: string) => void;
|
||||
isEditable: boolean;
|
||||
@@ -566,14 +568,14 @@ function Description({ playlist, description, setDescription, isEditable, setEdi
|
||||
}
|
||||
|
||||
interface PlaylistTrackListProps {
|
||||
playlist: ResultOf<typeof fragments.playlist>;
|
||||
tracks: Array<ResultOf<typeof fragments.track> & { rank: number }>;
|
||||
playlist: ResultOf<typeof PLAYLIST_DETAIL_PAGE_PLAYLIST>;
|
||||
tracks: Array<ResultOf<typeof PLAYLIST_DETAIL_PAGE_TRACK> & { rank: number }>;
|
||||
isReorderable: boolean;
|
||||
isOwner: boolean;
|
||||
isRanking: boolean;
|
||||
playAll: (index: number) => void;
|
||||
updateTrackOrderRemote: (trackId: string) => void;
|
||||
updateTrackOrder: (tracks: Array<ResultOf<typeof fragments.track> & { rank: number }>) => void;
|
||||
updateTrackOrder: (tracks: Array<ResultOf<typeof PLAYLIST_DETAIL_PAGE_TRACK> & { rank: number }>) => void;
|
||||
}
|
||||
|
||||
const PlaylistTrackList = memo(function PlaylistTrackList({
|
||||
@@ -632,8 +634,8 @@ const StyledDragHandle = styled(Icon)`
|
||||
`;
|
||||
|
||||
interface PlaylistTrackProps {
|
||||
playlist: ResultOf<typeof fragments.playlist>;
|
||||
track: ResultOf<typeof fragments.track> & { rank: number };
|
||||
playlist: ResultOf<typeof PLAYLIST_DETAIL_PAGE_PLAYLIST>;
|
||||
track: ResultOf<typeof PLAYLIST_DETAIL_PAGE_TRACK> & { rank: number };
|
||||
isOwner: boolean;
|
||||
isRanking: boolean;
|
||||
isDraggable?: boolean;
|
||||
|
||||
+22
-24
@@ -135,30 +135,28 @@ const StyledRoleBadge = styled.span<{ $color: string }>`
|
||||
letter-spacing: 1px;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
me: graphql(`
|
||||
fragment ProfilePageMe on Me {
|
||||
...ProfileImageUser
|
||||
name
|
||||
email
|
||||
emailVerifiedAt
|
||||
createdAt
|
||||
roles {
|
||||
nodes {
|
||||
name
|
||||
color
|
||||
priority
|
||||
default
|
||||
}
|
||||
}
|
||||
playlists(sort: [CREATED_AT_DESC]) {
|
||||
...PlaylistSummaryCardPlaylist
|
||||
...PlaylistRemoveDialogPlaylist
|
||||
id
|
||||
export const PROFILE_PAGE_ME = graphql(`
|
||||
fragment ProfilePageMe on Me {
|
||||
...ProfileImageUser
|
||||
name
|
||||
email
|
||||
emailVerifiedAt
|
||||
createdAt
|
||||
roles {
|
||||
nodes {
|
||||
name
|
||||
color
|
||||
priority
|
||||
default
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
playlists(sort: [CREATED_AT_DESC]) {
|
||||
...PlaylistSummaryCardPlaylist
|
||||
...PlaylistRemoveDialogPlaylist
|
||||
id
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const PROFILE_PAGE = graphql(`
|
||||
query ProfilePage {
|
||||
@@ -169,13 +167,13 @@ export const PROFILE_PAGE = graphql(`
|
||||
`);
|
||||
|
||||
interface ProfilePageProps extends SharedPageProps {
|
||||
me: FragmentType<typeof fragments.me> | null;
|
||||
me: FragmentType<typeof PROFILE_PAGE_ME> | null;
|
||||
}
|
||||
|
||||
export default function ProfilePage({ me: meFragment }: ProfilePageProps) {
|
||||
const { data } = useQuery(PROFILE_PAGE);
|
||||
|
||||
const me = getFragmentData(fragments.me, data?.me ?? meFragment);
|
||||
const me = getFragmentData(PROFILE_PAGE_ME, data?.me ?? meFragment);
|
||||
|
||||
const { history, clearHistory } = useWatchHistory();
|
||||
|
||||
|
||||
@@ -31,41 +31,39 @@ const StyledDesktopOnly = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
series: graphql(`
|
||||
fragment SeriesDetailPageSeries on Series {
|
||||
slug
|
||||
name
|
||||
anime {
|
||||
nodes {
|
||||
...AnimeSummaryCardAnime
|
||||
...AnimeSummaryCardAnimeExpandable
|
||||
name
|
||||
slug
|
||||
year
|
||||
season
|
||||
animethemes {
|
||||
type
|
||||
sequence
|
||||
animethemeentries {
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
tags
|
||||
}
|
||||
export const SERIES_DETAIL_PAGE_SERIES = graphql(`
|
||||
fragment SeriesDetailPageSeries on Series {
|
||||
slug
|
||||
name
|
||||
anime {
|
||||
nodes {
|
||||
...AnimeSummaryCardAnime
|
||||
...AnimeSummaryCardAnimeExpandable
|
||||
name
|
||||
slug
|
||||
year
|
||||
season
|
||||
animethemes {
|
||||
type
|
||||
sequence
|
||||
animethemeentries {
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
const propsQuery = graphql(`
|
||||
query SeriesDetailPage($seriesSlug: String!) {
|
||||
@@ -87,7 +85,7 @@ const pathsQuery = graphql(`
|
||||
`);
|
||||
|
||||
interface SeriesDetailPageProps {
|
||||
series: FragmentType<typeof fragments.series>;
|
||||
series: FragmentType<typeof SERIES_DETAIL_PAGE_SERIES>;
|
||||
}
|
||||
|
||||
interface SeriesDetailPageParams extends ParsedUrlQuery {
|
||||
@@ -95,7 +93,7 @@ interface SeriesDetailPageParams extends ParsedUrlQuery {
|
||||
}
|
||||
|
||||
export default function SeriesDetailPage({ series: seriesFragment }: SeriesDetailPageProps) {
|
||||
const series = getFragmentData(fragments.series, seriesFragment);
|
||||
const series = getFragmentData(SERIES_DETAIL_PAGE_SERIES, seriesFragment);
|
||||
const anime = series.anime.nodes;
|
||||
|
||||
const [showFilter, toggleShowFilter] = useToggle();
|
||||
@@ -141,7 +139,7 @@ export default function SeriesDetailPage({ series: seriesFragment }: SeriesDetai
|
||||
}
|
||||
|
||||
interface SeriesAnimeProps {
|
||||
anime: ResultOf<typeof fragments.series>["anime"]["nodes"];
|
||||
anime: ResultOf<typeof SERIES_DETAIL_PAGE_SERIES>["anime"]["nodes"];
|
||||
}
|
||||
|
||||
const SeriesAnime = memo(function SeriesAnime({ anime }: SeriesAnimeProps) {
|
||||
@@ -150,7 +148,7 @@ const SeriesAnime = memo(function SeriesAnime({ anime }: SeriesAnimeProps) {
|
||||
return <>{animeCards}</>;
|
||||
});
|
||||
|
||||
const buildTimeCache: Map<string, FragmentType<typeof fragments.series>> = new Map();
|
||||
const buildTimeCache: Map<string, FragmentType<typeof SERIES_DETAIL_PAGE_SERIES>> = new Map();
|
||||
|
||||
export const getStaticProps: GetStaticProps<SeriesDetailPageProps, SeriesDetailPageParams> = async ({ params }) => {
|
||||
const client = createApolloClient();
|
||||
|
||||
@@ -40,58 +40,56 @@ const StyledList = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const fragments = {
|
||||
studio: graphql(`
|
||||
fragment StudioDetailPageStudio on Studio {
|
||||
...StudioCoverImageStudio
|
||||
slug
|
||||
name
|
||||
anime {
|
||||
nodes {
|
||||
...AnimeSummaryCardAnime
|
||||
...AnimeSummaryCardAnimeExpandable
|
||||
name
|
||||
slug
|
||||
year
|
||||
season
|
||||
animethemes {
|
||||
type
|
||||
sequence
|
||||
animethemeentries {
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
tags
|
||||
}
|
||||
export const STUDIO_DETAIL_PAGE_STUDIO = graphql(`
|
||||
fragment StudioDetailPageStudio on Studio {
|
||||
...StudioCoverImageStudio
|
||||
slug
|
||||
name
|
||||
anime {
|
||||
nodes {
|
||||
...AnimeSummaryCardAnime
|
||||
...AnimeSummaryCardAnimeExpandable
|
||||
name
|
||||
slug
|
||||
year
|
||||
season
|
||||
animethemes {
|
||||
type
|
||||
sequence
|
||||
animethemeentries {
|
||||
version
|
||||
videos {
|
||||
nodes {
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
facet
|
||||
link
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resources {
|
||||
edges {
|
||||
as
|
||||
node {
|
||||
images {
|
||||
nodes {
|
||||
facet
|
||||
link
|
||||
site
|
||||
siteLocalized
|
||||
}
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
resources {
|
||||
edges {
|
||||
as
|
||||
node {
|
||||
link
|
||||
site
|
||||
siteLocalized
|
||||
}
|
||||
}
|
||||
}
|
||||
images {
|
||||
nodes {
|
||||
...extractImagesImage
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const propsQuery = graphql(`
|
||||
query StudioDetailPage($studioSlug: String!) {
|
||||
@@ -113,7 +111,7 @@ const pathsQuery = graphql(`
|
||||
`);
|
||||
|
||||
interface StudioDetailPageProps {
|
||||
studio: FragmentType<typeof fragments.studio>;
|
||||
studio: FragmentType<typeof STUDIO_DETAIL_PAGE_STUDIO>;
|
||||
}
|
||||
|
||||
interface StudioDetailPageParams extends ParsedUrlQuery {
|
||||
@@ -121,7 +119,7 @@ interface StudioDetailPageParams extends ParsedUrlQuery {
|
||||
}
|
||||
|
||||
export default function StudioDetailPage({ studio: studioFragment }: StudioDetailPageProps) {
|
||||
const studio = getFragmentData(fragments.studio, studioFragment);
|
||||
const studio = getFragmentData(STUDIO_DETAIL_PAGE_STUDIO, studioFragment);
|
||||
const anime = studio.anime.nodes;
|
||||
const { largeCover } = extractImages(studio.images.nodes);
|
||||
|
||||
@@ -186,7 +184,7 @@ export default function StudioDetailPage({ studio: studioFragment }: StudioDetai
|
||||
}
|
||||
|
||||
interface StudioAnimeProps {
|
||||
anime: ResultOf<typeof fragments.studio>["anime"]["nodes"];
|
||||
anime: ResultOf<typeof STUDIO_DETAIL_PAGE_STUDIO>["anime"]["nodes"];
|
||||
}
|
||||
|
||||
const StudioAnime = memo(function StudioAnime({ anime }: StudioAnimeProps) {
|
||||
@@ -195,7 +193,7 @@ const StudioAnime = memo(function StudioAnime({ anime }: StudioAnimeProps) {
|
||||
return <>{animeCards}</>;
|
||||
});
|
||||
|
||||
const buildTimeCache: Map<string, FragmentType<typeof fragments.studio>> = new Map();
|
||||
const buildTimeCache: Map<string, FragmentType<typeof STUDIO_DETAIL_PAGE_STUDIO>> = new Map();
|
||||
|
||||
export const getStaticProps: GetStaticProps<StudioDetailPageProps, StudioDetailPageParams> = async ({ params }) => {
|
||||
const client = createApolloClient();
|
||||
|
||||
@@ -15,29 +15,28 @@ import fetchStaticPaths from "@/utils/fetchStaticPaths";
|
||||
import type { SharedPageProps } from "@/utils/getSharedPageProps";
|
||||
import getSharedPageProps from "@/utils/getSharedPageProps";
|
||||
|
||||
const fragments = {
|
||||
year: graphql(`
|
||||
fragment SeasonDetailPageYear on AnimeYear {
|
||||
...SeasonNavigationYear
|
||||
year
|
||||
}
|
||||
`),
|
||||
season: graphql(`
|
||||
fragment SeasonDetailPageSeason on AnimeYearSeason {
|
||||
...SeasonNavigationSeason
|
||||
season
|
||||
seasonLocalized
|
||||
anime {
|
||||
data {
|
||||
...AnimeSummaryCardAnime
|
||||
...AnimeSummaryCardAnimeExpandable
|
||||
slug
|
||||
name
|
||||
}
|
||||
export const SEASON_DETAIL_PAGE_YEAR = graphql(`
|
||||
fragment SeasonDetailPageYear on AnimeYear {
|
||||
...SeasonNavigationYear
|
||||
year
|
||||
}
|
||||
`);
|
||||
|
||||
export const SEASON_DETAIL_PAGE_SEASON = graphql(`
|
||||
fragment SeasonDetailPageSeason on AnimeYearSeason {
|
||||
...SeasonNavigationSeason
|
||||
season
|
||||
seasonLocalized
|
||||
anime {
|
||||
data {
|
||||
...AnimeSummaryCardAnime
|
||||
...AnimeSummaryCardAnimeExpandable
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
const pathsQuery = graphql(`
|
||||
query SeasonDetailPageAll {
|
||||
@@ -72,8 +71,8 @@ const propsQuery = graphql(`
|
||||
|
||||
export interface SeasonDetailPageProps extends SharedPageProps {
|
||||
isYearOrSeasonPage: true;
|
||||
year: FragmentType<typeof fragments.year>;
|
||||
season: FragmentType<typeof fragments.season>;
|
||||
year: FragmentType<typeof SEASON_DETAIL_PAGE_YEAR>;
|
||||
season: FragmentType<typeof SEASON_DETAIL_PAGE_SEASON>;
|
||||
years: ResultOf<typeof propsQuery>["animeyears"];
|
||||
}
|
||||
|
||||
@@ -83,8 +82,8 @@ interface SeasonDetailPageParams extends ParsedUrlQuery {
|
||||
}
|
||||
|
||||
export default function SeasonDetailPage({ year: yearFragment, season: seasonFragment }: SeasonDetailPageProps) {
|
||||
const year = getFragmentData(fragments.year, yearFragment);
|
||||
const season = getFragmentData(fragments.season, seasonFragment);
|
||||
const year = getFragmentData(SEASON_DETAIL_PAGE_YEAR, yearFragment);
|
||||
const season = getFragmentData(SEASON_DETAIL_PAGE_SEASON, seasonFragment);
|
||||
const animeList = season.anime.data.filter((anime) => anime.name).sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
return (
|
||||
|
||||
@@ -70,24 +70,22 @@ export default function YearDetailPage({ year }: YearDetailPageProps) {
|
||||
);
|
||||
}
|
||||
|
||||
const fragments = {
|
||||
anime: graphql(`
|
||||
fragment SeasonPreviewAnime on Anime {
|
||||
...AnimeSummaryCardAnime
|
||||
...AnimeSummaryCardAnimeExpandable
|
||||
slug
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const SEASON_PREVIEW_ANIME = graphql(`
|
||||
fragment SeasonPreviewAnime on Anime {
|
||||
...AnimeSummaryCardAnime
|
||||
...AnimeSummaryCardAnimeExpandable
|
||||
slug
|
||||
}
|
||||
`);
|
||||
|
||||
interface SeasonPreviewProps {
|
||||
season: string;
|
||||
year: number;
|
||||
animes: Array<FragmentType<typeof fragments.anime>>;
|
||||
animes: Array<FragmentType<typeof SEASON_PREVIEW_ANIME>>;
|
||||
}
|
||||
|
||||
function SeasonPreview({ season, year, animes: animesFragment }: SeasonPreviewProps) {
|
||||
const animes = getFragmentData(fragments.anime, animesFragment);
|
||||
const animes = getFragmentData(SEASON_PREVIEW_ANIME, animesFragment);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -2,27 +2,27 @@ import type { WatchListItem } from "@/context/playerContext";
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
import { getAnimeFromVideoPageFragment, type VideoPageProps } from "@/pages/anime/[animeSlug]/[videoSlug]";
|
||||
|
||||
const fragments = {
|
||||
theme: graphql(`
|
||||
fragment createVideoSlugTheme on AnimeTheme {
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
slug
|
||||
}
|
||||
export const CREATE_VIDEO_SLUG_THEME = graphql(`
|
||||
fragment createVideoSlugTheme on AnimeTheme {
|
||||
type
|
||||
sequence
|
||||
group {
|
||||
slug
|
||||
}
|
||||
`),
|
||||
entry: graphql(`
|
||||
fragment createVideoSlugEntry on AnimeThemeEntry {
|
||||
version
|
||||
}
|
||||
`),
|
||||
video: graphql(`
|
||||
fragment createVideoSlugVideo on Video {
|
||||
tags
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
export const CREATE_VIDEO_SLUG_ENTRY = graphql(`
|
||||
fragment createVideoSlugEntry on AnimeThemeEntry {
|
||||
version
|
||||
}
|
||||
`);
|
||||
|
||||
export const CREATE_VIDEO_SLUG_VIDEO = graphql(`
|
||||
fragment createVideoSlugVideo on Video {
|
||||
tags
|
||||
}
|
||||
`);
|
||||
|
||||
/**
|
||||
* Slug format is:
|
||||
@@ -30,13 +30,13 @@ const fragments = {
|
||||
* `<OP|ED><#>[v#][-<Group>][-<Tags>]`
|
||||
*/
|
||||
const createVideoSlug = (
|
||||
themeFragment: FragmentType<typeof fragments.theme>,
|
||||
entryFragment: FragmentType<typeof fragments.entry>,
|
||||
videoFragment: FragmentType<typeof fragments.video>,
|
||||
themeFragment: FragmentType<typeof CREATE_VIDEO_SLUG_THEME>,
|
||||
entryFragment: FragmentType<typeof CREATE_VIDEO_SLUG_ENTRY>,
|
||||
videoFragment: FragmentType<typeof CREATE_VIDEO_SLUG_VIDEO>,
|
||||
) => {
|
||||
const theme = getFragmentData(fragments.theme, themeFragment);
|
||||
const entry = getFragmentData(fragments.entry, entryFragment);
|
||||
const video = getFragmentData(fragments.video, videoFragment);
|
||||
const theme = getFragmentData(CREATE_VIDEO_SLUG_THEME, themeFragment);
|
||||
const entry = getFragmentData(CREATE_VIDEO_SLUG_ENTRY, entryFragment);
|
||||
const video = getFragmentData(CREATE_VIDEO_SLUG_VIDEO, videoFragment);
|
||||
|
||||
let slug = theme.type + (theme.sequence || 1);
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
image: graphql(`
|
||||
fragment extractImagesImage on Image {
|
||||
link
|
||||
facet
|
||||
}
|
||||
`),
|
||||
};
|
||||
export const EXTRACT_IMAGES_IMAGE = graphql(`
|
||||
fragment extractImagesImage on Image {
|
||||
link
|
||||
facet
|
||||
}
|
||||
`);
|
||||
|
||||
interface ExtractImagesResult {
|
||||
smallCover?: string;
|
||||
@@ -15,9 +13,9 @@ interface ExtractImagesResult {
|
||||
}
|
||||
|
||||
export default function extractImages(
|
||||
imageFragments: Array<FragmentType<typeof fragments.image>> | null,
|
||||
imageFragments: Array<FragmentType<typeof EXTRACT_IMAGES_IMAGE>> | null,
|
||||
): ExtractImagesResult {
|
||||
const images = imageFragments ? getFragmentData(fragments.image, imageFragments) : [];
|
||||
const images = imageFragments ? getFragmentData(EXTRACT_IMAGES_IMAGE, imageFragments) : [];
|
||||
const extractedImages: ExtractImagesResult = {};
|
||||
|
||||
for (const image of images) {
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import { type FragmentType, getFragmentData, graphql } from "@/graphql/generated";
|
||||
|
||||
const fragments = {
|
||||
imageEdge: graphql(`
|
||||
fragment extractMultipleImagesImageArtistEdge on ArtistImageEdge {
|
||||
depth
|
||||
node {
|
||||
link
|
||||
facet
|
||||
}
|
||||
export const EXTRACT_MULTIPLE_IMAGES_IMAGE_ARTIST_EDGE = graphql(`
|
||||
fragment extractMultipleImagesImageArtistEdge on ArtistImageEdge {
|
||||
depth
|
||||
node {
|
||||
link
|
||||
facet
|
||||
}
|
||||
`),
|
||||
};
|
||||
}
|
||||
`);
|
||||
|
||||
interface ExtractMultipleImagesResult {
|
||||
link: string;
|
||||
@@ -19,9 +17,11 @@ interface ExtractMultipleImagesResult {
|
||||
}
|
||||
|
||||
export default function extractMultipleImages(
|
||||
imageEdgeFragments: Array<FragmentType<typeof fragments.imageEdge>> | null,
|
||||
imageEdgeFragments: Array<FragmentType<typeof EXTRACT_MULTIPLE_IMAGES_IMAGE_ARTIST_EDGE>> | null,
|
||||
): Array<ExtractMultipleImagesResult> {
|
||||
const imageEdges = imageEdgeFragments ? getFragmentData(fragments.imageEdge, imageEdgeFragments) : [];
|
||||
const imageEdges = imageEdgeFragments
|
||||
? getFragmentData(EXTRACT_MULTIPLE_IMAGES_IMAGE_ARTIST_EDGE, imageEdgeFragments)
|
||||
: [];
|
||||
|
||||
if (imageEdges?.length > 0) {
|
||||
const largeCovers = imageEdges.filter((edge) => edge.node.facet === "LARGE_COVER");
|
||||
|
||||
Reference in New Issue
Block a user