Refac APIClient to return data, error and status as object

This commit is contained in:
MerlinScheurer
2025-03-20 20:30:08 +01:00
parent 52083e6fb7
commit edcede5de6
67 changed files with 660 additions and 544 deletions

View File

@@ -1,7 +1,9 @@
import { Fragment } from 'react';
import StatsInfoBoxItem from './StatsInfoBoxItem';
import formatNumbers from '../functions/formatNumbers';
import { ChannelStatsType, PlaylistStatsType, DownloadStatsType } from '../pages/SettingsDashboard';
import { ChannelStatsType } from '../api/loader/loadStatsChannel';
import { PlaylistStatsType } from '../api/loader/loadStatsPlaylist';
import { DownloadStatsType } from '../api/loader/loadStatsDownload';
type ApplicationStatsProps = {
channelStats?: ChannelStatsType;

View File

@@ -2,7 +2,7 @@ import humanFileSize from '../functions/humanFileSize';
import formatNumbers from '../functions/formatNumbers';
import { Link } from 'react-router-dom';
import Routes from '../configuration/routes/RouteList';
import { BiggestChannelsStatsType } from '../pages/SettingsDashboard';
import { BiggestChannelsStatsType } from '../api/loader/loadStatsBiggestChannels';
type BiggestChannelsStatsProps = {
biggestChannelsStatsByCount?: BiggestChannelsStatsType;

View File

@@ -1,7 +1,7 @@
import humanFileSize from '../functions/humanFileSize';
import formatDate from '../functions/formatDates';
import formatNumbers from '../functions/formatNumbers';
import { DownloadHistoryStatsType } from '../pages/SettingsDashboard';
import { DownloadHistoryStatsType } from '../api/loader/loadStatsDownloadHistory';
type DownloadHistoryStatsProps = {
downloadHistoryStats?: DownloadHistoryStatsType;

View File

@@ -1,7 +1,6 @@
import { useEffect, useRef, useState } from 'react';
import { VideoResponseType } from '../pages/Video';
import VideoPlayer from './VideoPlayer';
import loadVideoById from '../api/loader/loadVideoById';
import loadVideoById, { VideoResponseType } from '../api/loader/loadVideoById';
import iconClose from '/img/icon-close.svg';
import iconEye from '/img/icon-eye.svg';
import iconThumb from '/img/icon-thumb.svg';
@@ -13,6 +12,7 @@ import { Link, useSearchParams } from 'react-router-dom';
import Routes from '../configuration/routes/RouteList';
import loadPlaylistById from '../api/loader/loadPlaylistById';
import { useAppSettingsStore } from '../stores/AppSettingsStore';
import { ApiResponseType } from '../functions/APIClient';
type Playlist = {
id: string;
@@ -32,9 +32,11 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => {
const [refresh, setRefresh] = useState(true);
const [videoResponse, setVideoResponse] = useState<VideoResponseType>();
const [videoResponse, setVideoResponse] = useState<ApiResponseType<VideoResponseType>>();
const [playlists, setPlaylists] = useState<PlaylistList>();
const { data: videoResponseData } = videoResponse ?? {};
useEffect(() => {
(async () => {
if (!videoId) {
@@ -43,27 +45,31 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => {
inlinePlayerRef.current?.scrollIntoView();
if (refresh || videoId !== videoResponse?.youtube_id) {
if (refresh || videoId !== videoResponseData?.youtube_id) {
const videoResponse = await loadVideoById(videoId);
const playlistIds = videoResponse.playlist;
const { data: videoResponseData } = videoResponse ?? {};
const playlistIds = videoResponseData?.playlist || [];
if (playlistIds !== undefined) {
const playlists = await Promise.all(
playlistIds.map(async playlistid => {
const playlistResponse = await loadPlaylistById(playlistid);
return playlistResponse;
const { data: playlistResponseData } = playlistResponse ?? {};
return playlistResponseData;
}),
);
const playlistsFiltered = playlists
.filter(playlist => {
return playlist.playlist_subscribed;
return playlist?.playlist_subscribed;
})
.map(playlist => {
return {
id: playlist.playlist_id,
name: playlist.playlist_name,
id: playlist?.playlist_id || '',
name: playlist?.playlist_name || '',
};
});
@@ -77,11 +83,11 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [videoId, refresh]);
if (videoResponse === undefined || videoId === null) {
if (videoResponseData === undefined || videoId === null) {
return <div ref={inlinePlayerRef} className="player-wrapper" />;
}
const video = videoResponse;
const video = videoResponseData;
const name = video.title;
const channelId = video.channel.channel_id;
const channelName = video.channel.channel_name;
@@ -99,7 +105,7 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => {
<div ref={inlinePlayerRef} className="player-wrapper">
<div className="video-player">
<VideoPlayer
video={videoResponse}
video={videoResponseData}
sponsorBlock={sponsorblock}
embed={true}
autoplay={true}

View File

@@ -22,7 +22,11 @@ const Filterbar = ({ hideToggleText, viewStyleName, showSort = true }: Filterbar
const handleUserConfigUpdate = async (config: Partial<UserConfigType>) => {
const updatedUserConfig = await updateUserConfig(config);
setUserConfig(updatedUserConfig);
const { data: updatedUserConfigData } = updatedUserConfig;
if (updatedUserConfigData) {
setUserConfig(updatedUserConfigData);
}
};
return (

View File

@@ -46,7 +46,12 @@ async function castVideoProgress(
currentProgress: currentTime,
});
if (videoProgressResponse.watched && video.player.watched !== videoProgressResponse.watched) {
const { data: videoProgressResponseData } = videoProgressResponse ?? {};
if (
videoProgressResponseData?.watched &&
video.player.watched !== videoProgressResponseData.watched
) {
onWatchStateChanged?.(true);
}
}

View File

@@ -1,20 +1,11 @@
import { Fragment, useEffect, useState } from 'react';
import loadNotifications, { NotificationPages } from '../api/loader/loadNotifications';
import loadNotifications, {
NotificationPages,
NotificationResponseType,
} from '../api/loader/loadNotifications';
import iconStop from '/img/icon-stop.svg';
import stopTaskByName from '../api/actions/stopTaskByName';
type NotificationType = {
title: string;
group: string;
api_stop: boolean;
level: string;
id: string;
command: boolean | string;
messages: string[];
progress: number;
};
type NotificationResponseType = NotificationType[];
import { ApiResponseType } from '../functions/APIClient';
type NotificationsProps = {
pageName: NotificationPages;
@@ -29,13 +20,17 @@ const Notifications = ({
update,
setShouldRefresh,
}: NotificationsProps) => {
const [notificationResponse, setNotificationResponse] = useState<NotificationResponseType>([]);
const [notificationResponse, setNotificationResponse] =
useState<ApiResponseType<NotificationResponseType>>();
const { data: notificationResponseData } = notificationResponse ?? {};
useEffect(() => {
const intervalId = setInterval(async () => {
const notifications = await loadNotifications(pageName, includeReindex);
const { data: notificationsData } = notifications ?? {};
if (notifications.length === 0) {
if (notificationsData?.length === 0) {
setNotificationResponse(notifications);
clearInterval(intervalId);
setShouldRefresh?.(true);
@@ -52,13 +47,13 @@ const Notifications = ({
};
}, [pageName, update, setShouldRefresh, includeReindex]);
if (notificationResponse.length === 0) {
if (notificationResponseData?.length === 0) {
return [];
}
return (
<>
{notificationResponse.map(notification => (
{notificationResponseData?.map(notification => (
<div
id={notification.id}
className={`notification ${notification.level}`}

View File

@@ -2,7 +2,7 @@ import { Fragment } from 'react';
import humanFileSize from '../functions/humanFileSize';
import StatsInfoBoxItem from './StatsInfoBoxItem';
import formatNumbers from '../functions/formatNumbers';
import { VideoStatsType } from '../pages/SettingsDashboard';
import { VideoStatsType } from '../api/loader/loadStatsVideo';
type OverviewStatsProps = {
videoStats?: VideoStatsType;

View File

@@ -1,5 +1,5 @@
import updateVideoProgressById from '../api/actions/updateVideoProgressById';
import { SponsorBlockSegmentType, SponsorBlockType, VideoResponseType } from '../pages/Video';
import { SponsorBlockSegmentType, SponsorBlockType } from '../pages/Video';
import {
Dispatch,
Fragment,
@@ -13,6 +13,7 @@ import formatTime from '../functions/formatTime';
import { useSearchParams } from 'react-router-dom';
import getApiUrl from '../configuration/getApiUrl';
import { useKeyPress } from '../functions/useKeypressHook';
import { VideoResponseType } from '../api/loader/loadVideoById';
const VIDEO_PLAYBACK_SPEEDS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3];
@@ -95,7 +96,9 @@ const handleTimeUpdate =
currentProgress: currentTime,
});
if (videoProgressResponse.watched && watched !== videoProgressResponse.watched) {
const { data: videoProgressResponseData } = videoProgressResponse ?? {};
if (videoProgressResponseData?.watched && watched !== videoProgressResponseData.watched) {
onWatchStateChanged?.(true);
}
}
@@ -185,7 +188,9 @@ const VideoPlayer = ({
currentProgress: currentTime,
});
if (videoProgressResponse.watched && watched !== videoProgressResponse.watched) {
const { data: videoProgressResponseData } = videoProgressResponse;
if (videoProgressResponseData?.watched && watched !== videoProgressResponseData.watched) {
onWatchStateChanged?.(true);
}

View File

@@ -2,7 +2,7 @@ import { Fragment } from 'react';
import humanFileSize from '../functions/humanFileSize';
import StatsInfoBoxItem from './StatsInfoBoxItem';
import formatNumbers from '../functions/formatNumbers';
import { VideoStatsType } from '../pages/SettingsDashboard';
import { VideoStatsType } from '../api/loader/loadStatsVideo';
type VideoTypeStatsProps = {
videoStats?: VideoStatsType;

View File

@@ -1,7 +1,7 @@
import { Fragment } from 'react';
import StatsInfoBoxItem from './StatsInfoBoxItem';
import formatNumbers from '../functions/formatNumbers';
import { WatchProgressStatsType } from '../pages/SettingsDashboard';
import { WatchProgressStatsType } from '../api/loader/loadStatsWatchProgress';
const formatProgress = (progress: number) => {
return (Number(progress) * 100).toFixed(2) ?? '0';