diff --git a/@types/messageHandler.d.ts b/@types/messageHandler.d.ts index bcca4b2..904b96a 100644 --- a/@types/messageHandler.d.ts +++ b/@types/messageHandler.d.ts @@ -12,7 +12,8 @@ export interface MessageHandler { listEpisodes: (id: string) => Promise, downloadItem: (data) => void, isDownloading: () => boolean, - writeToClipboard: (text: string) => void + writeToClipboard: (text: string) => void, + openFolder: (path: string[]) => void } export type QueueItem = { diff --git a/TODO.md b/TODO.md index e323db0..0dc9c9a 100644 --- a/TODO.md +++ b/TODO.md @@ -9,4 +9,5 @@ - [ ] Add help information (version, contributor, documentation...) - [ ] App Icon with electron-forge make - [x] ContextMenu -- [x] Better episode listing with selectio via left mouse button \ No newline at end of file +- [x] Better episode listing with selectio via left mouse button +- [x] Use Child for Context Menu \ No newline at end of file diff --git a/gui/electron/src/index.ts b/gui/electron/src/index.ts index fdc0926..fcb0a05 100644 --- a/gui/electron/src/index.ts +++ b/gui/electron/src/index.ts @@ -14,7 +14,7 @@ if (require('electron-squirrel-startup')) { app.quit(); } -const isWindows = __dirname.indexOf('\\') !== -1; +export const isWindows = __dirname.indexOf('\\') !== -1; let mainWindow: BrowserWindow|undefined = undefined; export { mainWindow }; diff --git a/gui/electron/src/menu.ts b/gui/electron/src/menu.ts index 6bbc5ea..39070f5 100644 --- a/gui/electron/src/menu.ts +++ b/gui/electron/src/menu.ts @@ -37,6 +37,9 @@ const template: (MenuItemConstructorOptions | MenuItem)[] = [ click: () => { shell.openPath(path.join(__dirname, 'logs')) } + }, + { + role: 'forceReload' } ] }, diff --git a/gui/electron/src/messageHandler.ts b/gui/electron/src/messageHandler.ts index 7c15c8d..193bf86 100644 --- a/gui/electron/src/messageHandler.ts +++ b/gui/electron/src/messageHandler.ts @@ -23,5 +23,6 @@ export default (window: BrowserWindow) => { ipcMain.handle('listEpisodes', async (_, data) => handler?.listEpisodes(data)); ipcMain.handle('downloadItem', async (_, data) => handler?.downloadItem(data)); ipcMain.handle('writeToClipboard', async (_, data) => handler?.writeToClipboard(data)); + ipcMain.handle('openFolder', async (_, data) => handler?.openFolder(data)); ipcMain.on('isDownloading', (ev) => ev.returnValue = handler?.isDownloading()); }; diff --git a/gui/electron/src/serviceHandler/base.ts b/gui/electron/src/serviceHandler/base.ts index 7f4b799..e9e0b0e 100644 --- a/gui/electron/src/serviceHandler/base.ts +++ b/gui/electron/src/serviceHandler/base.ts @@ -1,6 +1,7 @@ -import { BrowserWindow, clipboard, dialog } from "electron"; -import { DownloadInfo, ExtendedProgress, ProgressData } from "../../../../@types/messageHandler"; +import { BrowserWindow, clipboard, dialog, shell } from "electron"; +import { DownloadInfo, ProgressData } from "../../../../@types/messageHandler"; import { RandomEvent, RandomEvents } from "../../../../@types/randomEvents"; +import { isWindows } from ".."; export default class Base { @@ -54,4 +55,12 @@ export default class Base { return true; } + async openFolder(subPath: string[]) { + const sep = isWindows ? '\\' : '/'; + + const p = __dirname.split(sep).slice(0, -4); // gui/electron/src/serviceHandler + p.push(...subPath); + shell.openPath(p.join(sep)); + } + } \ No newline at end of file diff --git a/gui/react/package.json b/gui/react/package.json index dd9dfa6..8e2504c 100644 --- a/gui/react/package.json +++ b/gui/react/package.json @@ -1,5 +1,5 @@ { - "name": "reacttt", + "name": "react", "version": "0.1.0", "private": true, "dependencies": { diff --git a/gui/react/src/components/MainFrame/DownloadSelector/DownloadSelector.tsx b/gui/react/src/components/MainFrame/DownloadSelector/DownloadSelector.tsx index 4fb6a1e..d71f12d 100644 --- a/gui/react/src/components/MainFrame/DownloadSelector/DownloadSelector.tsx +++ b/gui/react/src/components/MainFrame/DownloadSelector/DownloadSelector.tsx @@ -5,6 +5,7 @@ import MultiSelect from "../../reusable/MultiSelect"; import { messageChannelContext } from "../../../provider/MessageChannel"; import LoadingButton from '@mui/lab/LoadingButton'; import { useSnackbar } from "notistack"; +import { Folder } from "@mui/icons-material"; const DownloadSelector: React.FC = () => { const messageHandler = React.useContext(messageChannelContext); @@ -21,7 +22,6 @@ const DownloadSelector: React.FC = () => { const q = messageHandler?.handleDefault('q'); const fileName = messageHandler?.handleDefault('fileName'); const result = await Promise.all([dubLang, q, fileName]); - console.log(result); dispatch({ type: 'downloadOptions', payload: { @@ -123,6 +123,7 @@ const DownloadSelector: React.FC = () => { List episodes Add to Queue + }; diff --git a/gui/react/src/components/MainFrame/Listing/EpisodeListing.tsx b/gui/react/src/components/MainFrame/Listing/EpisodeListing.tsx index 24a08b8..1078bee 100644 --- a/gui/react/src/components/MainFrame/Listing/EpisodeListing.tsx +++ b/gui/react/src/components/MainFrame/Listing/EpisodeListing.tsx @@ -3,12 +3,16 @@ import { ExpandMore } from '@mui/icons-material' import React from "react"; import useStore from "../../../hooks/useStore"; import { Episode } from "../../../../../../@types/messageHandler"; +import ContextMenu from "../../reusable/ContextMenu"; +import { messageChannelContext } from "../../../provider/MessageChannel"; const EpisodeListing: React.FC = () => { const [store, dispatch] = useStore(); const [season, setSeason] = React.useState<'all'|string>('all'); + const messageHandler = React.useContext(messageChannelContext); + const seasons = React.useMemo(() => { const s: string[] = []; for (const {season} of store.episodeListing) { @@ -58,9 +62,10 @@ const EpisodeListing: React.FC = () => { {store.episodeListing.filter((a) => season === 'all' ? true : a.season === season).map((item, index, { length }) => { + const ref = React.createRef(); const e = isNaN(parseInt(item.e)) ? item.e : parseInt(item.e); const isSelected = selected.includes(e.toString()); - return { + messageHandler?.writeToClipboard(item.name) }, + { text: 'Copy description', onClick: () => messageHandler?.writeToClipboard(item.description) }, + { text: 'Copy image URL', onClick: () => messageHandler?.writeToClipboard(item.img) }, + "divider", + { text: 'Copy everything', onClick: () => messageHandler?.writeToClipboard(JSON.stringify(item, null, 2)) }, + ]} /> {index < length - 1 && } })} diff --git a/gui/react/src/components/reusable/ContextMenu.tsx b/gui/react/src/components/reusable/ContextMenu.tsx index a1438a1..d9252a5 100644 --- a/gui/react/src/components/reusable/ContextMenu.tsx +++ b/gui/react/src/components/reusable/ContextMenu.tsx @@ -44,7 +44,7 @@ function ContextMenu(props: ContextMenuProps) { }; }, [ props.popupItem ]) - return show ? + return show ? {props.options.map((item, i) => { return item === 'divider' ? : diff --git a/gui/react/src/provider/MessageChannel.tsx b/gui/react/src/provider/MessageChannel.tsx index 671bda7..513eb0e 100644 --- a/gui/react/src/provider/MessageChannel.tsx +++ b/gui/react/src/provider/MessageChannel.tsx @@ -79,7 +79,8 @@ const MessageChannelProvider: React.FC = ({ children }) => { randomEvents: randomEventHandler, downloadItem: (data) => ipcRenderer.invoke('downloadItem', data), isDownloading: () => ipcRenderer.sendSync('isDownloading'), - writeToClipboard: async (data) => await ipcRenderer.invoke('writeToClipboard', data) + writeToClipboard: async (data) => await ipcRenderer.invoke('writeToClipboard', data), + openFolder: async (data) => await ipcRenderer.invoke('openFolder', data) } return