Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [18.x]
node-version: [20.x]
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion src/main/tipc/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import FFmpeg from '@main/lib/ffmpeg'
import { getFilePathFromProtocolURL } from '@main/lib/protocols'
import { coverSubtitleToAss } from '@main/lib/utils'
import { showFileSelectionDialog } from '@main/modules/showDialog'
import { calculateFileHashByBuffer } from '@renderer/lib/calc-file-hash'
import { calculateFileHashByBuffer } from '@renderer/lib/file'
import { dialog } from 'electron'
import naturalCompare from 'string-natural-compare'

Expand Down
47 changes: 43 additions & 4 deletions src/main/tipc/utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,52 @@
import path from 'node:path'

import { getFilePathFromProtocolURL } from '@main/lib/protocols'
import { coverSubtitleToAss } from '@main/lib/utils'

import { t } from './_instance'

type Actions =
| 'cover-path-from-protocol'
| 'get-file-name-from-path'
| 'url-to-base64'
| 'cover-subtitle-to-ass'

// type FileAction<T extends Actions> = T extends 'cover-subtitle-to-ass'

export const utilsRoute = {
getFilePathFromProtocolURL: t.procedure.input<{ path: string }>().action(async ({ input }) => {
return getFilePathFromProtocolURL(input.path)
}),
coverSubtitleToAss: t.procedure.input<{ path: string }>().action(async ({ input }) => {
fileAction: t.procedure
.input<{
action: Actions
url: string
}>()
.action(async ({ input }) => {
const { url, action } = input

switch (action) {
case 'cover-path-from-protocol': {
return getFilePathFromProtocolURL(url)
}
case 'get-file-name-from-path': {
return path.basename(url)
}
case 'url-to-base64': {
try {
const response = await fetch(url)
const arrayBuffer = await response.arrayBuffer()
const buffer = Buffer.from(arrayBuffer)
const base64 = buffer.toString('base64')
return `data:${response.headers.get('content-type')};base64,${base64}`
} catch (error) {
console.error('Error converting image to base64:', error)
return
}
}
default: {
throw new Error(`Unsupported action: ${action}`)
}
}
}),
coverSubtitleToAss: t.procedure.input<{ path: string }>().action(({ input }) => {
return coverSubtitleToAss(input.path)
}),
}
2 changes: 1 addition & 1 deletion src/renderer/src/atoms/settings/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ const createAppDefaultSettings = () => {
export const appSettingAtom = createSettingATom('app', createAppDefaultSettings)

export const useAppSettings = () => useAtom(appSettingAtom)
export const useAppSettingsValue = () => useAtomValue(appSettingAtom)
export const useAppSettingsValue = () => useAtomValue(appSettingAtom)
42 changes: 30 additions & 12 deletions src/renderer/src/components/common/ErrorView.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,48 @@
import { tipcClient } from '@renderer/lib/client'
import { RouteName } from '@renderer/router'
import * as Sentry from '@sentry/react'
import { useEffect } from 'react'
import { useRouteError } from 'react-router'
import { useLocation, useNavigate, useRouteError } from 'react-router'

import { Button } from '../ui/button'

export default function ErrorView() {
const error = useRouteError() as { statusText: string; message: string }
const location = useLocation()
const navigate = useNavigate()
console.error(error)

useEffect(() => {
Sentry.captureException(error)
}, [error])
return (
<div className="flex h-screen flex-col items-center justify-center gap-5">
<div className="flex h-screen flex-col items-center justify-center gap-6">
<p className="text-xl">糟糕发生错误了😭</p>
<p className="text-lg">
错误信息: <i>{error?.statusText ?? error?.message}</i>
</p>
<Button
onClick={() => {
tipcClient?.windowAction({ action: 'restart' })
}}
>
重新加载页面
</Button>
<div className="space-y-4 text-lg">
<p>
错误信息: <i>{error?.statusText ?? error?.message}</i>
</p>
<p>
当前路由: <i>{location.pathname}</i>
</p>
</div>
<div className='space-x-4'>
<Button
onClick={() => {
navigate(RouteName.PLAYER)
}}
>
返回首页
</Button>

<Button
onClick={() => {
tipcClient?.windowAction({ action: 'restart' })
}}
>
重新加载页面
</Button>
</div>
</div>
)
}
25 changes: 0 additions & 25 deletions src/renderer/src/components/layout/root/RouterLayout.tsx

This file was deleted.

28 changes: 28 additions & 0 deletions src/renderer/src/components/layout/root/TitleBarLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { cn } from '@renderer/lib/utils'
import { useCurrentRoute } from '@renderer/router'
import type { FC, PropsWithChildren, ReactNode } from 'react'

interface TitleBarLayoutProps extends PropsWithChildren {
FunctionArea?: ReactNode
title?: ReactNode
}

export const TitleBarLayout: FC<TitleBarLayoutProps> = ({ children, FunctionArea, title }) => {
const currentRoute = useCurrentRoute()

return (
<div className={cn('relative flex h-full flex-col pt-1')}>
<section className="flex h-14 items-center justify-between overflow-hidden border-b px-4 dark:border-zinc-600">
<div>
{title ?? (
<h3 className="select-none align-middle text-lg font-medium">
{currentRoute?.meta?.title}
</h3>
)}
</div>
{FunctionArea}
</section>
{children}
</div>
)
}
4 changes: 2 additions & 2 deletions src/renderer/src/components/layout/sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const Sidebar = () => {
</p>
</Show>
</Link>
<ButtonWithIcon icon="icon-[mingcute--settings-3-line]" onClick={() => showModal()} />
<ButtonWithIcon icon="icon-[mingcute--settings-3-line]" className='hover:bg-base-300' onClick={() => showModal()} />
</div>
<nav className="mt-5 flex select-none flex-col gap-2">
{siderbarRoutes.map((route) => (
Expand Down Expand Up @@ -64,7 +64,7 @@ const NavLinkItem: FC<SidebarRouteObject> = ({ path, meta }) => {
<NavLink
draggable={false}
to={path}
className={cn(pathname === path && 'rounded-md bg-base-300')}
className={cn(pathname.includes(path) && 'rounded-md bg-base-300')}
>
<p className="flex cursor-default items-center gap-1.5 p-2">
<i className={cn(icon, 'text-xl')} />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useToast } from '@renderer/components/ui/toast'
import { db } from '@renderer/database/db'
import type { DB_Bangumi } from '@renderer/database/schemas/bangumi'
import type { DB_History } from '@renderer/database/schemas/history'
import { RouteName } from '@renderer/router'
import { useQuery } from '@tanstack/react-query'
import type { FC, PropsWithChildren } from 'react'
import { createContext, use } from 'react'
import { useNavigate, useParams } from 'react-router'

interface AnimeDataContextType {
bangumiData: DB_Bangumi
episodeData: DB_History[]
}

const AnimeDataContext = createContext<AnimeDataContextType | null>(null)

export const HistoryAnimeDataProvider: FC<PropsWithChildren> = ({ children }) => {
const { animeId } = useParams()
const { toast } = useToast()
const navigate = useNavigate()
const { isLoading, data } = useQuery({
queryKey: [RouteName.HISTORY, animeId],
queryFn: async () => {
if (!animeId) {
return
}
const bangumiData = await db.bangumi.get(+animeId)
const episodeData = await db.history.where({ animeId: +animeId }).toArray()
if (!bangumiData) {
return
}
return {
bangumiData,
episodeData,
}
},
})
if (isLoading) {
return null
}
if (!data) {
toast({
title: '错误',
description: '未找到该番剧',
})
navigate(RouteName.HISTORY)
return null
}
return <AnimeDataContext value={data}>{children}</AnimeDataContext>
}

export const useHistoryAnimeData = () => {

Check warning on line 53 in src/renderer/src/components/modules/history/HistoryAnimeDataProvider.tsx

View workflow job for this annotation

GitHub Actions / Lint and Typecheck (20.x)

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
const context = use(AnimeDataContext)
if (!context) {
throw new Error('useHistoryAnimeData must be used within a HistoryAnimeDataProvider')
}
return context
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export const HistoryDetailsContent = ()=>{
// const { bangumiData,episodeData } = useHistoryAnimeData()
return <div>
{/* <img src={episodeData[0].thumbnail} className="size-full"/> */}
</div>
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
listenerClear()
}
}
}, [initializePlayerEvent])

Check warning on line 35 in src/renderer/src/components/modules/player/initialize/Event.tsx

View workflow job for this annotation

GitHub Actions / Lint and Typecheck (20.x)

React Hook useEffect has missing dependencies: 'grabFrame', 'initializePlayerListener', and 'player'. Either include them or remove the dependency array
return null
}

Expand Down Expand Up @@ -155,7 +155,7 @@
})

player.on(Events.PLAYNEXT, async (url: string) => {
const path = await tipcClient?.getFilePathFromProtocolURL({ path: url })
const path = await tipcClient?.fileAction({ action: 'cover-path-from-protocol', url })
if (!path) {
return
}
Expand All @@ -175,7 +175,7 @@
}
return player.destroy()
})
}, [hash, player])

Check warning on line 178 in src/renderer/src/components/modules/player/initialize/Event.tsx

View workflow job for this annotation

GitHub Actions / Lint and Typecheck (20.x)

React Hook useCallback has missing dependencies: 'enableAutomaticEpisodeSwitching', 'grabFrame', 'importAnimeViaIPC', and 'resetVideo'. Either include them or remove the dependency array

const grabFrame = useCallback(
async (time?: string) => {
Expand Down
Loading
Loading