diff --git a/.idea/workspace.xml b/.idea/workspace.xml index dca2541..27386d7 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,11 +4,33 @@ - - + + + + + + + + + + + + + + + + + + + + + - + + + + @@ -25,7 +47,7 @@ - + @@ -108,6 +130,20 @@ "number": 73 }, "lastSeen": 1743265865001 + }, + { + "id": { + "id": "PR_kwDOMJIfts6Qp5nI", + "number": 72 + }, + "lastSeen": 1743338472110 + }, + { + "id": { + "id": "PR_kwDOMJIfts6QsjlS", + "number": 76 + }, + "lastSeen": 1743352150953 } ] }]]> @@ -139,56 +175,56 @@ - { - "keyToString": { - "ASKED_ADD_EXTERNAL_FILES": "true", - "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", - "Docker.Dockerfile build.executor": "Run", - "Docker.Dockerfile.executor": "Run", - "Playwright.Create transparent PNG.should make png color transparent.executor": "Run", - "Playwright.JoinText Component.executor": "Run", - "Playwright.JoinText Component.should merge text pieces with specified join character.executor": "Run", - "RunOnceActivity.OpenProjectViewOnStart": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.git.unshallow": "true", - "Vitest.compute function (1).executor": "Run", - "Vitest.compute function.executor": "Run", - "Vitest.mergeText.executor": "Run", - "Vitest.mergeText.should merge lines and preserve blank lines when deleteBlankLines is false.executor": "Run", - "Vitest.mergeText.should merge lines, preserve blank lines and trailing spaces when both deleteBlankLines and deleteTrailingSpaces are false.executor": "Run", - "Vitest.parsePageRanges.executor": "Run", - "Vitest.removeDuplicateLines function.executor": "Run", - "Vitest.removeDuplicateLines function.newlines option.executor": "Run", - "Vitest.removeDuplicateLines function.newlines option.should filter newlines when newlines is set to filter.executor": "Run", - "Vitest.replaceText function (regexp mode).should return the original text when passed an invalid regexp.executor": "Run", - "Vitest.replaceText function.executor": "Run", - "Vitest.timeBetweenDates.executor": "Run", - "git-widget-placeholder": "main", - "ignore.virus.scanning.warn.message": "true", - "kotlin-language-version-configured": "true", - "last_opened_file_path": "C:/Users/Ibrahima/IdeaProjects/omni-tools/src/components/input", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "npm.build.executor": "Run", - "npm.dev.executor": "Run", - "npm.lint.executor": "Run", - "npm.prebuild.executor": "Run", - "npm.script:create:tool.executor": "Run", - "npm.test.executor": "Run", - "npm.test:e2e.executor": "Run", - "npm.test:e2e:run.executor": "Run", - "prettierjs.PrettierConfiguration.Package": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\prettier", - "project.structure.last.edited": "Problems", - "project.structure.proportion": "0.0", - "project.structure.side.proportion": "0.2", - "settings.editor.selected.configurable": "refactai_advanced_settings", - "ts.external.directory.path": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib", - "vue.rearranger.settings.migration": "true" + +}]]> @@ -200,21 +236,21 @@ + + - - + - - + @@ -293,11 +329,11 @@ - - + + @@ -384,30 +420,7 @@ - - - - 1740614012237 - - - - 1740614012237 - - - - 1740614185980 - - - - 1740614185980 - - - - 1740614957672 - - - - 1740614957672 + @@ -777,7 +790,31 @@ 1743106796406 - + + + 1743349732644 + + + + 1743349732644 + + + + 1743355099396 + + + + 1743355099396 + + + + 1743355166425 + + + + 1743355166426 + + @@ -824,9 +861,6 @@ - - - @@ -849,7 +883,10 @@ - + + + + diff --git a/@types/theme.d.ts b/@types/theme.d.ts new file mode 100644 index 0000000..6738d79 --- /dev/null +++ b/@types/theme.d.ts @@ -0,0 +1,9 @@ +import '@mui/material/styles'; + +declare module '@mui/material/styles' { + interface TypeBackground { + hover?: string; + lightSecondary?: string; + darkSecondary?: string; + } +} diff --git a/public/assets/background-dark.png b/public/assets/background-dark.png new file mode 100644 index 0000000..5b8d1ca Binary files /dev/null and b/public/assets/background-dark.png differ diff --git a/src/components/App.tsx b/src/components/App.tsx index be12fe1..65c3304 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,14 +1,14 @@ import { BrowserRouter, useRoutes } from 'react-router-dom'; import routesConfig from '../config/routesConfig'; import Navbar from './Navbar'; -import { Suspense } from 'react'; +import { Suspense, useMemo, useState } from 'react'; import Loading from './Loading'; -import { ThemeProvider } from '@mui/material'; -import theme from '../config/muiConfig'; +import { CssBaseline, ThemeProvider } from '@mui/material'; import { CustomSnackBarProvider } from '../contexts/CustomSnackBarContext'; import { SnackbarProvider } from 'notistack'; import { tools } from '../tools'; import './index.css'; +import { darkTheme, lightTheme } from '../config/muiConfig'; const AppRoutes = () => { const updatedRoutesConfig = [...routesConfig]; @@ -19,21 +19,29 @@ const AppRoutes = () => { }; function App() { + const [darkMode, setDarkMode] = useState(() => { + return localStorage.getItem('theme') === 'dark'; + }); + const theme = useMemo(() => (darkMode ? darkTheme : lightTheme), [darkMode]); + return ( + - + { + setDarkMode((prevState) => !prevState); + localStorage.setItem('theme', darkMode ? 'light' : 'dark'); + }} + /> }> diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx index 6406b45..58e9e19 100644 --- a/src/components/Hero.tsx +++ b/src/components/Hero.tsx @@ -1,4 +1,4 @@ -import { Autocomplete, Box, Stack, TextField } from '@mui/material'; +import { Autocomplete, Box, Stack, TextField, useTheme } from '@mui/material'; import Typography from '@mui/material/Typography'; import SearchIcon from '@mui/icons-material/Search'; import Grid from '@mui/material/Grid'; @@ -25,6 +25,7 @@ const exampleTools: { label: string; url: string }[] = [ ]; export default function Hero() { const [inputValue, setInputValue] = useState(''); + const theme = useTheme(); const [filteredTools, setFilteredTools] = useState( _.shuffle(tools) ); @@ -78,7 +79,7 @@ export default function Hero() { endAdornment: , sx: { borderRadius: 4, - backgroundColor: 'white' + backgroundColor: 'background.paper' } }} onChange={(event) => handleInputChange(event, event.target.value)} @@ -125,11 +126,13 @@ export default function Hero() { borderWidth: 1, padding: 1, borderRadius: 3, - borderColor: 'grey', + borderColor: theme.palette.mode === 'dark' ? '#363b41' : 'grey', borderStyle: 'solid', - backgroundColor: 'white', + backgroundColor: 'background.paper', cursor: 'pointer', - '&:hover': { backgroundColor: '#FAFAFD' } + '&:hover': { + backgroundColor: 'background.hover' + } }} > {tool.label} diff --git a/src/components/Navbar/index.tsx b/src/components/Navbar/index.tsx index 83285a9..f148df5 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/Navbar/index.tsx @@ -17,8 +17,13 @@ import { import useMediaQuery from '@mui/material/useMediaQuery'; import { useTheme } from '@mui/material/styles'; import { Icon } from '@iconify/react'; +import DarkModeIcon from '@mui/icons-material/DarkMode'; -const Navbar: React.FC = () => { +interface NavbarProps { + onSwitchTheme: () => void; +} + +const Navbar: React.FC = ({ onSwitchTheme }) => { const navigate = useNavigate(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); @@ -30,7 +35,9 @@ const Navbar: React.FC = () => { // { label: 'Features', path: '/features' } // { label: 'About Us', path: '/about-us' } ]; + const buttons: ReactNode[] = [ + , window.open('https://discord.gg/SDbbn3hT4b', '_blank')} style={{ cursor: 'pointer' }} @@ -81,9 +88,10 @@ const Navbar: React.FC = () => { return ( scrollToElement('tool')} @@ -43,6 +43,7 @@ function ToolLinks() { scrollToElement('examples')} > See Examples diff --git a/src/components/ToolLayout.tsx b/src/components/ToolLayout.tsx index 90569b0..fb7caef 100644 --- a/src/components/ToolLayout.tsx +++ b/src/components/ToolLayout.tsx @@ -38,7 +38,7 @@ export default function ToolLayout({ display={'flex'} flexDirection={'column'} alignItems={'center'} - sx={{ backgroundColor: '#F5F5FA' }} + sx={{ backgroundColor: 'background.default' }} > {`${title} - Omni Tools`} diff --git a/src/components/allTools/ToolCard.tsx b/src/components/allTools/ToolCard.tsx index c4047c8..462bf39 100644 --- a/src/components/allTools/ToolCard.tsx +++ b/src/components/allTools/ToolCard.tsx @@ -1,4 +1,12 @@ -import { Box, Card, CardContent, Link, Stack, Typography } from '@mui/material'; +import { + Box, + Card, + CardContent, + Link, + Stack, + Typography, + useTheme +} from '@mui/material'; import { ToolCardProps } from './AllTools'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import { useNavigate } from 'react-router-dom'; @@ -10,6 +18,7 @@ export default function ToolCard({ link, icon }: ToolCardProps) { + const theme = useTheme(); const navigate = useNavigate(); return ( ({ changeInputResult(sampleText, sampleOptions); }} sx={{ - bgcolor: theme.palette.background.default, + bgcolor: 'background.lightSecondary', height: '100%', overflow: 'hidden', borderRadius: 2, transition: 'background-color 0.3s ease', cursor: 'pointer', '&:hover': { - boxShadow: '12px 9px 11px 2px #b8b9be, -6px -6px 12px #fff' + boxShadow: `12px 9px 11px 2px ${ + theme.palette.mode === 'dark' ? theme.palette.grey[900] : '#b8b9be' + }, -6px -6px 12px ${theme.palette.mode === 'dark' ? 'black' : '#fff'}` } }} > diff --git a/src/components/input/BaseFileInput.tsx b/src/components/input/BaseFileInput.tsx index 66c1241..232dc5c 100644 --- a/src/components/input/BaseFileInput.tsx +++ b/src/components/input/BaseFileInput.tsx @@ -94,7 +94,7 @@ export default function BaseFileInput({ border: preview ? 0 : 1, borderRadius: 2, boxShadow: '5', - bgcolor: 'white', + bgcolor: 'background.paper', position: 'relative' }} > @@ -106,7 +106,8 @@ export default function BaseFileInput({ display: 'flex', alignItems: 'center', justifyContent: 'center', - backgroundImage: `url(${greyPattern})`, + backgroundImage: + theme.palette.mode === 'dark' ? null : `url(${greyPattern})`, position: 'relative', overflow: 'hidden' }} @@ -126,7 +127,13 @@ export default function BaseFileInput({ cursor: 'pointer' }} > - + Click here to select a {type} from your device, press Ctrl+V to use a {type} from your clipboard, drag and drop a file from desktop diff --git a/src/components/input/ToolFileInput.tsx b/src/components/input/ToolFileInput.tsx deleted file mode 100644 index ed80889..0000000 --- a/src/components/input/ToolFileInput.tsx +++ /dev/null @@ -1,377 +0,0 @@ -import { Box, useTheme } from '@mui/material'; -import Typography from '@mui/material/Typography'; -import React, { useContext, useEffect, useRef, useState } from 'react'; -import ReactCrop, { Crop, PixelCrop } from 'react-image-crop'; -import 'react-image-crop/dist/ReactCrop.css'; -import InputHeader from '../InputHeader'; -import InputFooter from './InputFooter'; -import { CustomSnackBarContext } from '../../contexts/CustomSnackBarContext'; -import greyPattern from '@assets/grey-pattern.png'; -import { globalInputHeight } from '../../config/uiConfig'; -import Slider from 'rc-slider'; -import 'rc-slider/assets/index.css'; - -interface ToolFileInputProps { - value: File | null; - onChange: (file: File) => void; - accept: string[]; - title?: string; - showCropOverlay?: boolean; - cropShape?: 'rectangular' | 'circular'; - cropPosition?: { x: number; y: number }; - cropSize?: { width: number; height: number }; - onCropChange?: ( - position: { x: number; y: number }, - size: { width: number; height: number } - ) => void; - type?: 'image' | 'video' | 'audio'; - // Video specific props - showTrimControls?: boolean; - onTrimChange?: (trimStart: number, trimEnd: number) => void; - trimStart?: number; - trimEnd?: number; -} - -export default function ToolFileInput({ - value, - onChange, - accept, - title = 'File', - showCropOverlay = false, - cropShape = 'rectangular', - cropPosition = { x: 0, y: 0 }, - cropSize = { width: 100, height: 100 }, - onCropChange, - type = 'image', - showTrimControls = false, - onTrimChange, - trimStart = 0, - trimEnd = 100 -}: ToolFileInputProps) { - const [preview, setPreview] = useState(null); - const theme = useTheme(); - const { showSnackBar } = useContext(CustomSnackBarContext); - const fileInputRef = useRef(null); - const imageRef = useRef(null); - const videoRef = useRef(null); - const [imgWidth, setImgWidth] = useState(0); - const [imgHeight, setImgHeight] = useState(0); - const [videoDuration, setVideoDuration] = useState(0); - - // Convert position and size to crop format used by ReactCrop - const [crop, setCrop] = useState({ - unit: 'px', - x: 0, - y: 0, - width: 0, - height: 0 - }); - - const RATIO = imageRef.current ? imgWidth / imageRef.current.width : 1; - - useEffect(() => { - if (imgWidth && imgHeight) { - setCrop({ - unit: 'px', - x: cropPosition.x / RATIO, - y: cropPosition.y / RATIO, - width: cropSize.width / RATIO, - height: cropSize.height / RATIO - }); - } - }, [cropPosition, cropSize, imgWidth, imgHeight]); - - const handleCopy = () => { - if (value) { - const blob = new Blob([value], { type: value.type }); - const clipboardItem = new ClipboardItem({ [value.type]: blob }); - - navigator.clipboard - .write([clipboardItem]) - .then(() => showSnackBar('File copied', 'success')) - .catch((err) => { - showSnackBar('Failed to copy: ' + err, 'error'); - }); - } - }; - - useEffect(() => { - if (value) { - const objectUrl = URL.createObjectURL(value); - setPreview(objectUrl); - - // Clean up memory when the component is unmounted or the file changes - return () => URL.revokeObjectURL(objectUrl); - } else { - setPreview(null); - setImgWidth(0); - setImgHeight(0); - } - }, [value]); - - const handleFileChange = (event: React.ChangeEvent) => { - const file = event.target.files?.[0]; - if (file) onChange(file); - }; - - const handleImportClick = () => { - fileInputRef.current?.click(); - }; - - // Handle image load to set dimensions - const onImageLoad = (e: React.SyntheticEvent) => { - const { naturalWidth: width, naturalHeight: height } = e.currentTarget; - setImgWidth(width); - setImgHeight(height); - - // Initialize crop with a centered default crop if needed - if (!crop.width && !crop.height && onCropChange) { - const initialCrop: Crop = { - unit: 'px', - x: Math.floor(width / 4), - y: Math.floor(height / 4), - width: Math.floor(width / 2), - height: Math.floor(height / 2) - }; - - setCrop(initialCrop); - - // Notify parent component of initial crop - onCropChange( - { x: initialCrop.x, y: initialCrop.y }, - { width: initialCrop.width, height: initialCrop.height } - ); - } - }; - - // Handle video load to set duration - const onVideoLoad = (e: React.SyntheticEvent) => { - const duration = e.currentTarget.duration; - setVideoDuration(duration); - - // Initialize trim with full duration if needed - if (onTrimChange && trimStart === 0 && trimEnd === 100) { - onTrimChange(0, duration); - } - }; - - const handleCropChange = (newCrop: Crop) => { - setCrop(newCrop); - }; - - const handleCropComplete = (crop: PixelCrop) => { - if (onCropChange) { - onCropChange( - { x: Math.round(crop.x * RATIO), y: Math.round(crop.y * RATIO) }, - { - width: Math.round(crop.width * RATIO), - height: Math.round(crop.height * RATIO) - } - ); - } - }; - - const handleTrimChange = (start: number, end: number) => { - if (onTrimChange) { - onTrimChange(start, end); - } - }; - - useEffect(() => { - const handlePaste = (event: ClipboardEvent) => { - const clipboardItems = event.clipboardData?.items ?? []; - const item = clipboardItems[0]; - if ( - item && - (item.type.includes('image') || item.type.includes('video')) - ) { - const file = item.getAsFile(); - if (file) onChange(file); - } - }; - window.addEventListener('paste', handlePaste); - - return () => { - window.removeEventListener('paste', handlePaste); - }; - }, [onChange]); - - // Format seconds to MM:SS format - const formatTime = (seconds: number) => { - const minutes = Math.floor(seconds / 60); - const remainingSeconds = Math.floor(seconds % 60); - return `${minutes.toString().padStart(2, '0')}:${remainingSeconds - .toString() - .padStart(2, '0')}`; - }; - - return ( - - - - {preview ? ( - - {type === 'image' && - (showCropOverlay ? ( - - - - ) : ( - - ))} - {type === 'video' && ( - - - - {showTrimControls && videoDuration > 0 && ( - - - - Start: {formatTime(trimStart || 0)} - - - End: {formatTime(trimEnd || videoDuration)} - - - - - { - if (Array.isArray(values)) { - handleTrimChange(values[0], values[1]); - } - }} - allowCross={false} - pushable={0.1} // Minimum distance between handles - /> - - - - )} - - )} - {type === 'audio' && ( - - )} - - ) : ( - - - Click here to select a {type} from your device, press Ctrl+V to - use a {type} from your clipboard, drag and drop a file from - desktop - - - )} - - - - - ); -} diff --git a/src/components/input/ToolTextInput.tsx b/src/components/input/ToolTextInput.tsx index 319c942..e5741f6 100644 --- a/src/components/input/ToolTextInput.tsx +++ b/src/components/input/ToolTextInput.tsx @@ -52,7 +52,7 @@ export default function ToolTextInput({ rows={10} sx={{ '&.MuiTextField-root': { - backgroundColor: 'white' + backgroundColor: 'background.paper' } }} inputProps={{ diff --git a/src/components/options/ColorSelector.tsx b/src/components/options/ColorSelector.tsx index 5ff89cc..a89ea1d 100644 --- a/src/components/options/ColorSelector.tsx +++ b/src/components/options/ColorSelector.tsx @@ -30,7 +30,7 @@ const ColorSelector: React.FC = ({ onOwnChange(event.target.value)} {...props} diff --git a/src/components/options/ToolOptions.tsx b/src/components/options/ToolOptions.tsx index a4a381d..15a1844 100644 --- a/src/components/options/ToolOptions.tsx +++ b/src/components/options/ToolOptions.tsx @@ -36,7 +36,7 @@ export default function ToolOptions({ mb: 2, borderRadius: 2, padding: 2, - backgroundColor: theme.palette.background.default, + backgroundColor: 'background.lightSecondary', boxShadow: '2' }} mt={2} diff --git a/src/components/result/ToolFileResult.tsx b/src/components/result/ToolFileResult.tsx index d34eea3..7b07578 100644 --- a/src/components/result/ToolFileResult.tsx +++ b/src/components/result/ToolFileResult.tsx @@ -1,4 +1,4 @@ -import { Box, CircularProgress, Typography } from '@mui/material'; +import { Box, CircularProgress, Typography, useTheme } from '@mui/material'; import React, { useContext } from 'react'; import InputHeader from '../InputHeader'; import greyPattern from '@assets/grey-pattern.png'; @@ -21,6 +21,7 @@ export default function ToolFileResult({ }) { const [preview, setPreview] = React.useState(null); const { showSnackBar } = useContext(CustomSnackBarContext); + const theme = useTheme(); React.useEffect(() => { if (value) { @@ -87,7 +88,7 @@ export default function ToolFileResult({ border: preview ? 0 : 1, borderRadius: 2, boxShadow: '5', - bgcolor: 'white' + bgcolor: 'background.paper' }} > {loading ? ( @@ -114,7 +115,8 @@ export default function ToolFileResult({ display: 'flex', alignItems: 'center', justifyContent: 'center', - backgroundImage: `url(${greyPattern})` + backgroundImage: + theme.palette.mode === 'dark' ? null : `url(${greyPattern})` }} > {fileType === 'image' && ( diff --git a/src/components/result/ToolTextResult.tsx b/src/components/result/ToolTextResult.tsx index 46b0efc..cefa482 100644 --- a/src/components/result/ToolTextResult.tsx +++ b/src/components/result/ToolTextResult.tsx @@ -52,7 +52,7 @@ export default function ToolTextResult({ multiline sx={{ '&.MuiTextField-root': { - backgroundColor: 'white' + backgroundColor: 'background.paper' } }} rows={10} diff --git a/src/config/muiConfig.ts b/src/config/muiConfig.ts index 118efef..28a4abb 100644 --- a/src/config/muiConfig.ts +++ b/src/config/muiConfig.ts @@ -1,13 +1,50 @@ -import { createTheme } from '@mui/material'; +import { createTheme, ThemeOptions } from '@mui/material'; -const theme = createTheme({ +const sharedThemeOptions: ThemeOptions = { typography: { button: { textTransform: 'none' } }, - palette: { background: { default: '#ebf5ff' } }, zIndex: { snackbar: 100000 } +}; +export const lightTheme = createTheme({ + ...sharedThemeOptions, + palette: { + background: { + default: '#F5F5FA', + hover: '#FAFAFD', + lightSecondary: '#EBF5FF', + darkSecondary: '#5581b5' + } + }, + components: { + MuiButton: { + styleOverrides: { + contained: { color: '#ffffff', backgroundColor: '#1976d2' } + } + } + } }); -export default theme; +export const darkTheme = createTheme({ + ...sharedThemeOptions, + palette: { + mode: 'dark', + background: { + default: '#1C1F20', + paper: '#181a1b', + hover: '#1a1c1d', + lightSecondary: '#1E2021', + darkSecondary: '#3C5F8A' + }, + text: { primary: '#ffffff' } + }, + components: { + MuiButton: { + styleOverrides: { + contained: { color: '#ffffff', backgroundColor: '#145ea8' } + } + } + } +}); diff --git a/src/pages/home/Categories.tsx b/src/pages/home/Categories.tsx index afd9664..12ee949 100644 --- a/src/pages/home/Categories.tsx +++ b/src/pages/home/Categories.tsx @@ -1,6 +1,6 @@ import { getToolsByCategory } from '@tools/index'; import Grid from '@mui/material/Grid'; -import { Box, Card, CardContent, Stack } from '@mui/material'; +import { Box, Card, CardContent, Stack, useTheme } from '@mui/material'; import { Link, useNavigate } from 'react-router-dom'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; @@ -19,6 +19,7 @@ const SingleCategory = function ({ index: number; }) { const navigate = useNavigate(); + const theme = useTheme(); const [hovered, setHovered] = useState(false); const toggleHover = () => setHovered((prevState) => !prevState); return ( @@ -32,7 +33,7 @@ const SingleCategory = function ({ @@ -52,7 +53,11 @@ const SingleCategory = function ({ color={categoriesColors[index % categoriesColors.length]} /> {category.title} @@ -70,7 +75,7 @@ const SingleCategory = function ({ navigate(category.example.path)} variant={'outlined'} diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index b54e460..4443975 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -1,16 +1,23 @@ -import { Box } from '@mui/material'; +import { Box, useTheme } from '@mui/material'; import Hero from 'components/Hero'; import Categories from './Categories'; export default function Home() { + const theme = useTheme(); return ( + navigate('/' + tool.path)} @@ -77,7 +79,12 @@ export default function Home() { color={categoriesColors[index % categoriesColors.length]} /> - + {tool.name} diff --git a/src/pages/tools/pdf/split-pdf/index.tsx b/src/pages/tools/pdf/split-pdf/index.tsx index 2682949..c38c3bc 100644 --- a/src/pages/tools/pdf/split-pdf/index.tsx +++ b/src/pages/tools/pdf/split-pdf/index.tsx @@ -1,6 +1,5 @@ import { Box, Typography } from '@mui/material'; -import React, { useEffect, useRef, useState } from 'react'; -import ToolFileInput from '@components/input/ToolFileInput'; +import React, { useEffect, useState } from 'react'; import ToolFileResult from '@components/result/ToolFileResult'; import TextFieldWithDesc from '@components/options/TextFieldWithDesc'; import ToolContent from '@components/ToolContent'; @@ -8,7 +7,6 @@ import { ToolComponentProps } from '@tools/defineTool'; import { parsePageRanges, splitPdf } from './service'; import { CardExampleType } from '@components/examples/ToolExamples'; import { PDFDocument } from 'pdf-lib'; -import { FormikProps } from 'formik'; import ToolPdfInput from '@components/input/ToolPdfInput'; type InitialValuesType = { diff --git a/src/pages/tools/video/compress/service.ts b/src/pages/tools/video/compress/service.ts index 2850dbd..4c10d28 100644 --- a/src/pages/tools/video/compress/service.ts +++ b/src/pages/tools/video/compress/service.ts @@ -15,7 +15,6 @@ export async function compressVideo( input: File, options: CompressVideoOptions ): Promise { - console.log('Compressing video...', options); if (!ffmpeg.loaded) { await ffmpeg.load({ wasmURL: diff --git a/src/pages/tools/video/gif/change-speed/index.tsx b/src/pages/tools/video/gif/change-speed/index.tsx index a4c2e58..bf10e9d 100644 --- a/src/pages/tools/video/gif/change-speed/index.tsx +++ b/src/pages/tools/video/gif/change-speed/index.tsx @@ -1,7 +1,6 @@ import { Box } from '@mui/material'; import React, { useState } from 'react'; import * as Yup from 'yup'; -import ToolFileInput from '@components/input/ToolFileInput'; import ToolFileResult from '@components/result/ToolFileResult'; import TextFieldWithDesc from 'components/options/TextFieldWithDesc'; import Typography from '@mui/material/Typography'; @@ -9,6 +8,8 @@ import { FrameOptions, GifReader, GifWriter } from 'omggif'; import { gifBinaryToFile } from '@utils/gif'; import ToolContent from '@components/ToolContent'; import { ToolComponentProps } from '@tools/defineTool'; +import ToolVideoInput from '@components/input/ToolVideoInput'; +import ToolImageInput from '@components/input/ToolImageInput'; const initialValues = { newSpeed: 200 @@ -108,7 +109,7 @@ export default function ChangeSpeed({ title }: ToolComponentProps) { title={title} input={input} inputComponent={ -