|
@@ -16,7 +16,7 @@ import {
|
|
|
VideoOrderByInput,
|
|
|
useSearchLazyQuery,
|
|
|
} from '@/api/queries'
|
|
|
-import { LimitedWidthContainer, VideoTile, ViewWrapper } from '@/components'
|
|
|
+import { LimitedWidthContainer, VideoTile, ViewErrorFallback, ViewWrapper } from '@/components'
|
|
|
import { absoluteRoutes } from '@/config/routes'
|
|
|
import { SORT_OPTIONS } from '@/config/sorting'
|
|
|
import { AssetType, useAsset, useDialog, usePersonalDataStore } from '@/providers'
|
|
@@ -59,7 +59,9 @@ export const ChannelView: React.FC = () => {
|
|
|
const [openUnfollowDialog, closeUnfollowDialog] = useDialog()
|
|
|
const { id } = useParams()
|
|
|
const [searchParams, setSearchParams] = useSearchParams()
|
|
|
- const { channel, loading, error } = useChannel(id)
|
|
|
+ const { channel, loading, error } = useChannel(id, {
|
|
|
+ onError: (error) => Logger.captureError('Failed to fetch channel', 'ChannelView', error, { channel: { id } }),
|
|
|
+ })
|
|
|
const {
|
|
|
searchVideos,
|
|
|
loadingSearch,
|
|
@@ -71,7 +73,13 @@ export const ChannelView: React.FC = () => {
|
|
|
search,
|
|
|
errorSearch,
|
|
|
searchQuery,
|
|
|
- } = useSearchVideos({ id })
|
|
|
+ } = useSearchVideos({
|
|
|
+ id,
|
|
|
+ onError: (error) =>
|
|
|
+ Logger.captureError('Failed to search channel videos', 'ChannelView', error, {
|
|
|
+ search: { channelId: id, query: searchQuery },
|
|
|
+ }),
|
|
|
+ })
|
|
|
const { followChannel } = useFollowChannel()
|
|
|
const { unfollowChannel } = useUnfollowChannel()
|
|
|
const followedChannels = usePersonalDataStore((state) => state.followedChannels)
|
|
@@ -106,9 +114,14 @@ export const ChannelView: React.FC = () => {
|
|
|
mediaAvailability_eq: AssetAvailability.Accepted,
|
|
|
},
|
|
|
},
|
|
|
- { notifyOnNetworkStatusChange: true }
|
|
|
+ {
|
|
|
+ notifyOnNetworkStatusChange: true,
|
|
|
+ onError: (error) => Logger.captureError('Failed to fetch videos', 'ChannelView', error, { channel: { id } }),
|
|
|
+ }
|
|
|
)
|
|
|
- const { videoCount: videosLastMonth } = useChannelVideoCount(id, DATE_ONE_MONTH_PAST)
|
|
|
+ const { videoCount: videosLastMonth } = useChannelVideoCount(id, DATE_ONE_MONTH_PAST, {
|
|
|
+ onError: (error) => Logger.captureError('Failed to fetch videos', 'ChannelView', error, { channel: { id } }),
|
|
|
+ })
|
|
|
useEffect(() => {
|
|
|
const isFollowing = followedChannels.some((channel) => channel.id === id)
|
|
|
setFollowing(isFollowing)
|
|
@@ -156,16 +169,9 @@ export const ChannelView: React.FC = () => {
|
|
|
setFollowing(true)
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- Logger.warn('Failed to update Channel following', { error })
|
|
|
+ Logger.captureError('Failed to update channel following', 'ChannelView', error, { channel: { id } })
|
|
|
}
|
|
|
}
|
|
|
- if (videosError) {
|
|
|
- throw videosError
|
|
|
- } else if (error) {
|
|
|
- throw error
|
|
|
- } else if (errorSearch) {
|
|
|
- throw errorSearch
|
|
|
- }
|
|
|
|
|
|
const handleSetCurrentTab = async (tab: number) => {
|
|
|
if (TABS[tab] === 'Videos' && isSearching) {
|
|
@@ -259,6 +265,10 @@ export const ChannelView: React.FC = () => {
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
}, [])
|
|
|
|
|
|
+ if (videosError || error || errorSearch) {
|
|
|
+ return <ViewErrorFallback />
|
|
|
+ }
|
|
|
+
|
|
|
if (!loading && !channel) {
|
|
|
return (
|
|
|
<NotFoundChannelContainer>
|
|
@@ -273,6 +283,7 @@ export const ChannelView: React.FC = () => {
|
|
|
</NotFoundChannelContainer>
|
|
|
)
|
|
|
}
|
|
|
+
|
|
|
return (
|
|
|
<ViewWrapper>
|
|
|
<ChannelCover assetUrl={coverPhotoUrl} />
|
|
@@ -354,12 +365,15 @@ const getVideosFromSearch = (loading: boolean, data: SearchQuery['search'] | und
|
|
|
}
|
|
|
type UseSearchVideosParams = {
|
|
|
id: string
|
|
|
+ onError: (error: unknown) => void
|
|
|
}
|
|
|
-const useSearchVideos = ({ id }: UseSearchVideosParams) => {
|
|
|
+const useSearchVideos = ({ id, onError }: UseSearchVideosParams) => {
|
|
|
const [isSearchInputOpen, setIsSearchingInputOpen] = useState(false)
|
|
|
const [isSearching, setIsSearching] = useState(false)
|
|
|
const [searchQuery, setSearchQuery] = useState('')
|
|
|
- const [searchVideo, { loading: loadingSearch, data: searchData, error: errorSearch }] = useSearchLazyQuery()
|
|
|
+ const [searchVideo, { loading: loadingSearch, data: searchData, error: errorSearch }] = useSearchLazyQuery({
|
|
|
+ onError,
|
|
|
+ })
|
|
|
const searchInputRef = useRef<HTMLInputElement>(null)
|
|
|
const search = useCallback(
|
|
|
(searchQuery: string) => {
|