mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-20 14:39:34 +02:00
213
.idea/workspace.xml
generated
213
.idea/workspace.xml
generated
@@ -4,11 +4,33 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="refactor: time between dates">
|
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="chore: compress video icon">
|
||||||
<change afterPath="$PROJECT_DIR$/src/components/BackButton.tsx" afterDir="false" />
|
<change afterPath="$PROJECT_DIR$/@types/theme.d.ts" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/public/assets/background-dark.png" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/App.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/App.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/Hero.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/Hero.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/Navbar/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/Navbar/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/ToolHeader.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/ToolHeader.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/ToolLayout.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/ToolLayout.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/allTools/ToolCard.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/allTools/ToolCard.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/examples/ExampleCard.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/examples/ExampleCard.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/input/BaseFileInput.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/input/BaseFileInput.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/input/ToolFileInput.tsx" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/input/ToolTextInput.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/input/ToolTextInput.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/options/ColorSelector.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/options/ColorSelector.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/options/TextFieldWithDesc.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/options/TextFieldWithDesc.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/options/ToolOptions.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/options/ToolOptions.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/result/ToolFileResult.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/result/ToolFileResult.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/result/ToolTextResult.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/result/ToolTextResult.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/config/muiConfig.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/config/muiConfig.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/home/Categories.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/home/Categories.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/home/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/home/index.tsx" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/pages/tools-by-category/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools-by-category/index.tsx" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/pages/tools-by-category/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools-by-category/index.tsx" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/pages/tools/video/rotate/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/video/rotate/index.tsx" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/pages/tools/pdf/split-pdf/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/pdf/split-pdf/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/tools/video/compress/service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/video/compress/service.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/tools/video/gif/change-speed/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/video/gif/change-speed/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/tsconfig.json" beforeDir="false" afterPath="$PROJECT_DIR$/tsconfig.json" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -25,7 +47,7 @@
|
|||||||
<option name="PUSH_AUTO_UPDATE" value="true" />
|
<option name="PUSH_AUTO_UPDATE" value="true" />
|
||||||
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||||
<map>
|
<map>
|
||||||
<entry key="$PROJECT_DIR$" value="fork/lfsjesus/feature/rotate-video" />
|
<entry key="$PROJECT_DIR$" value="main" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
@@ -108,6 +130,20 @@
|
|||||||
"number": 73
|
"number": 73
|
||||||
},
|
},
|
||||||
"lastSeen": 1743265865001
|
"lastSeen": 1743265865001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": {
|
||||||
|
"id": "PR_kwDOMJIfts6Qp5nI",
|
||||||
|
"number": 72
|
||||||
|
},
|
||||||
|
"lastSeen": 1743338472110
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": {
|
||||||
|
"id": "PR_kwDOMJIfts6QsjlS",
|
||||||
|
"number": 76
|
||||||
|
},
|
||||||
|
"lastSeen": 1743352150953
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]]></component>
|
}]]></component>
|
||||||
@@ -139,56 +175,56 @@
|
|||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">{
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"ASKED_ADD_EXTERNAL_FILES": "true",
|
"ASKED_ADD_EXTERNAL_FILES": "true",
|
||||||
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
"Docker.Dockerfile build.executor": "Run",
|
"Docker.Dockerfile build.executor": "Run",
|
||||||
"Docker.Dockerfile.executor": "Run",
|
"Docker.Dockerfile.executor": "Run",
|
||||||
"Playwright.Create transparent PNG.should make png color transparent.executor": "Run",
|
"Playwright.Create transparent PNG.should make png color transparent.executor": "Run",
|
||||||
"Playwright.JoinText Component.executor": "Run",
|
"Playwright.JoinText Component.executor": "Run",
|
||||||
"Playwright.JoinText Component.should merge text pieces with specified join character.executor": "Run",
|
"Playwright.JoinText Component.should merge text pieces with specified join character.executor": "Run",
|
||||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"RunOnceActivity.git.unshallow": "true",
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
"Vitest.compute function (1).executor": "Run",
|
"Vitest.compute function (1).executor": "Run",
|
||||||
"Vitest.compute function.executor": "Run",
|
"Vitest.compute function.executor": "Run",
|
||||||
"Vitest.mergeText.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 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.mergeText.should merge lines, preserve blank lines and trailing spaces when both deleteBlankLines and deleteTrailingSpaces are false.executor": "Run",
|
||||||
"Vitest.parsePageRanges.executor": "Run",
|
"Vitest.parsePageRanges.executor": "Run",
|
||||||
"Vitest.removeDuplicateLines function.executor": "Run",
|
"Vitest.removeDuplicateLines function.executor": "Run",
|
||||||
"Vitest.removeDuplicateLines function.newlines option.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.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 (regexp mode).should return the original text when passed an invalid regexp.executor": "Run",
|
||||||
"Vitest.replaceText function.executor": "Run",
|
"Vitest.replaceText function.executor": "Run",
|
||||||
"Vitest.timeBetweenDates.executor": "Run",
|
"Vitest.timeBetweenDates.executor": "Run",
|
||||||
"git-widget-placeholder": "main",
|
"git-widget-placeholder": "dark-mode",
|
||||||
"ignore.virus.scanning.warn.message": "true",
|
"ignore.virus.scanning.warn.message": "true",
|
||||||
"kotlin-language-version-configured": "true",
|
"kotlin-language-version-configured": "true",
|
||||||
"last_opened_file_path": "C:/Users/Ibrahima/IdeaProjects/omni-tools/src/components/input",
|
"last_opened_file_path": "C:/Users/Ibrahima/IdeaProjects/omni-tools/@types",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
"npm.build.executor": "Run",
|
"npm.build.executor": "Run",
|
||||||
"npm.dev.executor": "Run",
|
"npm.dev.executor": "Run",
|
||||||
"npm.lint.executor": "Run",
|
"npm.lint.executor": "Run",
|
||||||
"npm.prebuild.executor": "Run",
|
"npm.prebuild.executor": "Run",
|
||||||
"npm.script:create:tool.executor": "Run",
|
"npm.script:create:tool.executor": "Run",
|
||||||
"npm.test.executor": "Run",
|
"npm.test.executor": "Run",
|
||||||
"npm.test:e2e.executor": "Run",
|
"npm.test:e2e.executor": "Run",
|
||||||
"npm.test:e2e:run.executor": "Run",
|
"npm.test:e2e:run.executor": "Run",
|
||||||
"prettierjs.PrettierConfiguration.Package": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\prettier",
|
"prettierjs.PrettierConfiguration.Package": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\prettier",
|
||||||
"project.structure.last.edited": "Problems",
|
"project.structure.last.edited": "Problems",
|
||||||
"project.structure.proportion": "0.0",
|
"project.structure.proportion": "0.0",
|
||||||
"project.structure.side.proportion": "0.2",
|
"project.structure.side.proportion": "0.2",
|
||||||
"settings.editor.selected.configurable": "refactai_advanced_settings",
|
"settings.editor.selected.configurable": "refactai_advanced_settings",
|
||||||
"ts.external.directory.path": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib",
|
"ts.external.directory.path": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
}
|
}
|
||||||
}</component>
|
}]]></component>
|
||||||
<component name="ReactDesignerToolWindowState">
|
<component name="ReactDesignerToolWindowState">
|
||||||
<option name="myId2Visible">
|
<option name="myId2Visible">
|
||||||
<map>
|
<map>
|
||||||
@@ -200,21 +236,21 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="CopyFile.RECENT_KEYS">
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\@types" />
|
||||||
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\public\assets" />
|
||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\components\input" />
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\components\input" />
|
||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\.husky" />
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\.husky" />
|
||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\public\assets" />
|
|
||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\assets" />
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\assets" />
|
||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\.github" />
|
|
||||||
</key>
|
</key>
|
||||||
<key name="MoveFile.RECENT_KEYS">
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\@types" />
|
||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\public\assets" />
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\public\assets" />
|
||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\pages\tools" />
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\pages\tools" />
|
||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\pages\categories" />
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\pages\categories" />
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\components" />
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\components" />
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\components\options" />
|
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="Vitest.calculateTimeBetweenDates">
|
<component name="RunManager" selected="npm.dev">
|
||||||
<configuration name="calculateTimeBetweenDates" type="JavaScriptTestRunnerVitest" temporary="true" nameIsGenerated="true">
|
<configuration name="calculateTimeBetweenDates" type="JavaScriptTestRunnerVitest" temporary="true" nameIsGenerated="true">
|
||||||
<node-interpreter value="project" />
|
<node-interpreter value="project" />
|
||||||
<vitest-package value="$PROJECT_DIR$/node_modules/vitest" />
|
<vitest-package value="$PROJECT_DIR$/node_modules/vitest" />
|
||||||
@@ -293,11 +329,11 @@
|
|||||||
</list>
|
</list>
|
||||||
<recent_temporary>
|
<recent_temporary>
|
||||||
<list>
|
<list>
|
||||||
<item itemvalue="Vitest.calculateTimeBetweenDates" />
|
|
||||||
<item itemvalue="Vitest.timeBetweenDates" />
|
|
||||||
<item itemvalue="npm.dev" />
|
<item itemvalue="npm.dev" />
|
||||||
<item itemvalue="Vitest.replaceText function (regexp mode).should return the original text when passed an invalid regexp" />
|
<item itemvalue="Vitest.replaceText function (regexp mode).should return the original text when passed an invalid regexp" />
|
||||||
<item itemvalue="Vitest.parsePageRanges" />
|
<item itemvalue="Vitest.parsePageRanges" />
|
||||||
|
<item itemvalue="Vitest.timeBetweenDates" />
|
||||||
|
<item itemvalue="Vitest.calculateTimeBetweenDates" />
|
||||||
</list>
|
</list>
|
||||||
</recent_temporary>
|
</recent_temporary>
|
||||||
</component>
|
</component>
|
||||||
@@ -384,30 +420,7 @@
|
|||||||
<workItem from="1743018497879" duration="3895000" />
|
<workItem from="1743018497879" duration="3895000" />
|
||||||
<workItem from="1743047367993" duration="986000" />
|
<workItem from="1743047367993" duration="986000" />
|
||||||
<workItem from="1743103182313" duration="4264000" />
|
<workItem from="1743103182313" duration="4264000" />
|
||||||
</task>
|
<workItem from="1743348610793" duration="21855000" />
|
||||||
<task id="LOCAL-00124" summary="docs: readme">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1740614012237</created>
|
|
||||||
<option name="number" value="00124" />
|
|
||||||
<option name="presentableId" value="LOCAL-00124" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1740614012237</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00125" summary="docs: readme">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1740614185980</created>
|
|
||||||
<option name="number" value="00125" />
|
|
||||||
<option name="presentableId" value="LOCAL-00125" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1740614185980</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00126" summary="chore: handle enter press on search">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1740614957672</created>
|
|
||||||
<option name="number" value="00126" />
|
|
||||||
<option name="presentableId" value="LOCAL-00126" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1740614957672</updated>
|
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00127" summary="chore: show tooloptions in example">
|
<task id="LOCAL-00127" summary="chore: show tooloptions in example">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
@@ -777,7 +790,31 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1743106796406</updated>
|
<updated>1743106796406</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="173" />
|
<task id="LOCAL-00173" summary="fix: typos">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1743349732644</created>
|
||||||
|
<option name="number" value="00173" />
|
||||||
|
<option name="presentableId" value="LOCAL-00173" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1743349732644</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00174" summary="feat: compress video">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1743355099396</created>
|
||||||
|
<option name="number" value="00174" />
|
||||||
|
<option name="presentableId" value="LOCAL-00174" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1743355099396</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00175" summary="chore: compress video icon">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1743355166425</created>
|
||||||
|
<option name="number" value="00175" />
|
||||||
|
<option name="presentableId" value="LOCAL-00175" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1743355166426</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="176" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -824,9 +861,6 @@
|
|||||||
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
||||||
<option name="CHECK_NEW_TODO" value="false" />
|
<option name="CHECK_NEW_TODO" value="false" />
|
||||||
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
||||||
<MESSAGE value="feat: minify json" />
|
|
||||||
<MESSAGE value="feat: stringify json" />
|
|
||||||
<MESSAGE value="feat: arithmetic sequence" />
|
|
||||||
<MESSAGE value="style: tools height" />
|
<MESSAGE value="style: tools height" />
|
||||||
<MESSAGE value="chore: update meta" />
|
<MESSAGE value="chore: update meta" />
|
||||||
<MESSAGE value="feat: change pgn opacity" />
|
<MESSAGE value="feat: change pgn opacity" />
|
||||||
@@ -849,7 +883,10 @@
|
|||||||
<MESSAGE value="chore: show new tools in landing" />
|
<MESSAGE value="chore: show new tools in landing" />
|
||||||
<MESSAGE value="chore: zoom on hover" />
|
<MESSAGE value="chore: zoom on hover" />
|
||||||
<MESSAGE value="refactor: time between dates" />
|
<MESSAGE value="refactor: time between dates" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="refactor: time between dates" />
|
<MESSAGE value="fix: typos" />
|
||||||
|
<MESSAGE value="feat: compress video" />
|
||||||
|
<MESSAGE value="chore: compress video icon" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="chore: compress video icon" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XSLT-Support.FileAssociations.UIState">
|
<component name="XSLT-Support.FileAssociations.UIState">
|
||||||
<expand />
|
<expand />
|
||||||
|
9
@types/theme.d.ts
vendored
Normal file
9
@types/theme.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import '@mui/material/styles';
|
||||||
|
|
||||||
|
declare module '@mui/material/styles' {
|
||||||
|
interface TypeBackground {
|
||||||
|
hover?: string;
|
||||||
|
lightSecondary?: string;
|
||||||
|
darkSecondary?: string;
|
||||||
|
}
|
||||||
|
}
|
BIN
public/assets/background-dark.png
Normal file
BIN
public/assets/background-dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 140 KiB |
@@ -1,14 +1,14 @@
|
|||||||
import { BrowserRouter, useRoutes } from 'react-router-dom';
|
import { BrowserRouter, useRoutes } from 'react-router-dom';
|
||||||
import routesConfig from '../config/routesConfig';
|
import routesConfig from '../config/routesConfig';
|
||||||
import Navbar from './Navbar';
|
import Navbar from './Navbar';
|
||||||
import { Suspense } from 'react';
|
import { Suspense, useMemo, useState } from 'react';
|
||||||
import Loading from './Loading';
|
import Loading from './Loading';
|
||||||
import { ThemeProvider } from '@mui/material';
|
import { CssBaseline, ThemeProvider } from '@mui/material';
|
||||||
import theme from '../config/muiConfig';
|
|
||||||
import { CustomSnackBarProvider } from '../contexts/CustomSnackBarContext';
|
import { CustomSnackBarProvider } from '../contexts/CustomSnackBarContext';
|
||||||
import { SnackbarProvider } from 'notistack';
|
import { SnackbarProvider } from 'notistack';
|
||||||
import { tools } from '../tools';
|
import { tools } from '../tools';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
import { darkTheme, lightTheme } from '../config/muiConfig';
|
||||||
|
|
||||||
const AppRoutes = () => {
|
const AppRoutes = () => {
|
||||||
const updatedRoutesConfig = [...routesConfig];
|
const updatedRoutesConfig = [...routesConfig];
|
||||||
@@ -19,21 +19,29 @@ const AppRoutes = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const [darkMode, setDarkMode] = useState<boolean>(() => {
|
||||||
|
return localStorage.getItem('theme') === 'dark';
|
||||||
|
});
|
||||||
|
const theme = useMemo(() => (darkMode ? darkTheme : lightTheme), [darkMode]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
|
<CssBaseline />
|
||||||
<SnackbarProvider
|
<SnackbarProvider
|
||||||
maxSnack={5}
|
maxSnack={5}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: 'bottom',
|
vertical: 'bottom',
|
||||||
horizontal: 'right'
|
horizontal: 'right'
|
||||||
}}
|
}}
|
||||||
classes={{
|
|
||||||
containerRoot: 'bottom-0 right-0 mb-52 md:mb-68 mr-8 lg:mr-80 z-99'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<CustomSnackBarProvider>
|
<CustomSnackBarProvider>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Navbar />
|
<Navbar
|
||||||
|
onSwitchTheme={() => {
|
||||||
|
setDarkMode((prevState) => !prevState);
|
||||||
|
localStorage.setItem('theme', darkMode ? 'light' : 'dark');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Suspense fallback={<Loading />}>
|
<Suspense fallback={<Loading />}>
|
||||||
<AppRoutes />
|
<AppRoutes />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
@@ -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 Typography from '@mui/material/Typography';
|
||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
@@ -25,6 +25,7 @@ const exampleTools: { label: string; url: string }[] = [
|
|||||||
];
|
];
|
||||||
export default function Hero() {
|
export default function Hero() {
|
||||||
const [inputValue, setInputValue] = useState<string>('');
|
const [inputValue, setInputValue] = useState<string>('');
|
||||||
|
const theme = useTheme();
|
||||||
const [filteredTools, setFilteredTools] = useState<DefinedTool[]>(
|
const [filteredTools, setFilteredTools] = useState<DefinedTool[]>(
|
||||||
_.shuffle(tools)
|
_.shuffle(tools)
|
||||||
);
|
);
|
||||||
@@ -78,7 +79,7 @@ export default function Hero() {
|
|||||||
endAdornment: <SearchIcon />,
|
endAdornment: <SearchIcon />,
|
||||||
sx: {
|
sx: {
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
backgroundColor: 'white'
|
backgroundColor: 'background.paper'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onChange={(event) => handleInputChange(event, event.target.value)}
|
onChange={(event) => handleInputChange(event, event.target.value)}
|
||||||
@@ -125,11 +126,13 @@ export default function Hero() {
|
|||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
padding: 1,
|
padding: 1,
|
||||||
borderRadius: 3,
|
borderRadius: 3,
|
||||||
borderColor: 'grey',
|
borderColor: theme.palette.mode === 'dark' ? '#363b41' : 'grey',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'background.paper',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
'&:hover': { backgroundColor: '#FAFAFD' }
|
'&:hover': {
|
||||||
|
backgroundColor: 'background.hover'
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography>{tool.label}</Typography>
|
<Typography>{tool.label}</Typography>
|
||||||
|
@@ -17,8 +17,13 @@ import {
|
|||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
|
import DarkModeIcon from '@mui/icons-material/DarkMode';
|
||||||
|
|
||||||
const Navbar: React.FC = () => {
|
interface NavbarProps {
|
||||||
|
onSwitchTheme: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Navbar: React.FC<NavbarProps> = ({ onSwitchTheme }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
@@ -30,7 +35,9 @@ const Navbar: React.FC = () => {
|
|||||||
// { label: 'Features', path: '/features' }
|
// { label: 'Features', path: '/features' }
|
||||||
// { label: 'About Us', path: '/about-us' }
|
// { label: 'About Us', path: '/about-us' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const buttons: ReactNode[] = [
|
const buttons: ReactNode[] = [
|
||||||
|
<DarkModeIcon onClick={onSwitchTheme} style={{ cursor: 'pointer' }} />,
|
||||||
<Icon
|
<Icon
|
||||||
onClick={() => window.open('https://discord.gg/SDbbn3hT4b', '_blank')}
|
onClick={() => window.open('https://discord.gg/SDbbn3hT4b', '_blank')}
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
@@ -81,9 +88,10 @@ const Navbar: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<AppBar
|
<AppBar
|
||||||
position="static"
|
position="static"
|
||||||
style={{
|
sx={{
|
||||||
backgroundColor: '#F5F5FA',
|
background: 'transparent',
|
||||||
color: 'black'
|
boxShadow: 'none',
|
||||||
|
color: 'text.primary'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Toolbar
|
<Toolbar
|
||||||
|
@@ -31,7 +31,7 @@ function ToolLinks() {
|
|||||||
<Grid container spacing={2} mt={1}>
|
<Grid container spacing={2} mt={1}>
|
||||||
<Grid item md={12} lg={6}>
|
<Grid item md={12} lg={6}>
|
||||||
<StyledButton
|
<StyledButton
|
||||||
sx={{ backgroundColor: 'white' }}
|
sx={{ backgroundColor: 'background.paper' }}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={() => scrollToElement('tool')}
|
onClick={() => scrollToElement('tool')}
|
||||||
@@ -43,6 +43,7 @@ function ToolLinks() {
|
|||||||
<StyledButton
|
<StyledButton
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
sx={{ backgroundColor: 'background.paper' }}
|
||||||
onClick={() => scrollToElement('examples')}
|
onClick={() => scrollToElement('examples')}
|
||||||
>
|
>
|
||||||
See Examples
|
See Examples
|
||||||
|
@@ -38,7 +38,7 @@ export default function ToolLayout({
|
|||||||
display={'flex'}
|
display={'flex'}
|
||||||
flexDirection={'column'}
|
flexDirection={'column'}
|
||||||
alignItems={'center'}
|
alignItems={'center'}
|
||||||
sx={{ backgroundColor: '#F5F5FA' }}
|
sx={{ backgroundColor: 'background.default' }}
|
||||||
>
|
>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{`${title} - Omni Tools`}</title>
|
<title>{`${title} - Omni Tools`}</title>
|
||||||
|
@@ -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 { ToolCardProps } from './AllTools';
|
||||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
@@ -10,6 +18,7 @@ export default function ToolCard({
|
|||||||
link,
|
link,
|
||||||
icon
|
icon
|
||||||
}: ToolCardProps) {
|
}: ToolCardProps) {
|
||||||
|
const theme = useTheme();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
@@ -17,10 +26,13 @@ export default function ToolCard({
|
|||||||
raised
|
raised
|
||||||
sx={{
|
sx={{
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
bgcolor: '#5581b5',
|
bgcolor: 'background.darkSecondary',
|
||||||
borderColor: '#5581b5',
|
borderColor: 'background.darkSecondary',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
boxShadow: '6px 6px 12px #b8b9be, -6px -6px 12px #fff',
|
boxShadow:
|
||||||
|
theme.palette.mode === 'dark'
|
||||||
|
? null
|
||||||
|
: '6px 6px 12px #b8b9be, -6px -6px 12px #fff',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
|
@@ -38,14 +38,16 @@ export default function ExampleCard<T>({
|
|||||||
changeInputResult(sampleText, sampleOptions);
|
changeInputResult(sampleText, sampleOptions);
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
bgcolor: theme.palette.background.default,
|
bgcolor: 'background.lightSecondary',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
transition: 'background-color 0.3s ease',
|
transition: 'background-color 0.3s ease',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
'&:hover': {
|
'&: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'}`
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@@ -94,7 +94,7 @@ export default function BaseFileInput({
|
|||||||
border: preview ? 0 : 1,
|
border: preview ? 0 : 1,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
boxShadow: '5',
|
boxShadow: '5',
|
||||||
bgcolor: 'white',
|
bgcolor: 'background.paper',
|
||||||
position: 'relative'
|
position: 'relative'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -106,7 +106,8 @@ export default function BaseFileInput({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
backgroundImage: `url(${greyPattern})`,
|
backgroundImage:
|
||||||
|
theme.palette.mode === 'dark' ? null : `url(${greyPattern})`,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
overflow: 'hidden'
|
overflow: 'hidden'
|
||||||
}}
|
}}
|
||||||
@@ -126,7 +127,13 @@ export default function BaseFileInput({
|
|||||||
cursor: 'pointer'
|
cursor: 'pointer'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography color={theme.palette.grey['600']}>
|
<Typography
|
||||||
|
color={
|
||||||
|
theme.palette.mode === 'dark'
|
||||||
|
? theme.palette.grey['300']
|
||||||
|
: theme.palette.grey['600']
|
||||||
|
}
|
||||||
|
>
|
||||||
Click here to select a {type} from your device, press Ctrl+V to
|
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
|
use a {type} from your clipboard, drag and drop a file from
|
||||||
desktop
|
desktop
|
||||||
|
@@ -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<string | null>(null);
|
|
||||||
const theme = useTheme();
|
|
||||||
const { showSnackBar } = useContext(CustomSnackBarContext);
|
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
||||||
const imageRef = useRef<HTMLImageElement>(null);
|
|
||||||
const videoRef = useRef<HTMLVideoElement>(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<Crop>({
|
|
||||||
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<HTMLInputElement>) => {
|
|
||||||
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<HTMLImageElement>) => {
|
|
||||||
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<HTMLVideoElement>) => {
|
|
||||||
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 (
|
|
||||||
<Box>
|
|
||||||
<InputHeader title={title} />
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: '100%',
|
|
||||||
height: globalInputHeight,
|
|
||||||
border: preview ? 0 : 1,
|
|
||||||
borderRadius: 2,
|
|
||||||
boxShadow: '5',
|
|
||||||
bgcolor: 'white',
|
|
||||||
position: 'relative'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{preview ? (
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
backgroundImage: `url(${greyPattern})`,
|
|
||||||
position: 'relative',
|
|
||||||
overflow: 'hidden'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{type === 'image' &&
|
|
||||||
(showCropOverlay ? (
|
|
||||||
<ReactCrop
|
|
||||||
crop={crop}
|
|
||||||
onChange={handleCropChange}
|
|
||||||
onComplete={handleCropComplete}
|
|
||||||
circularCrop={cropShape === 'circular'}
|
|
||||||
style={{ maxWidth: '100%', maxHeight: globalInputHeight }}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
ref={imageRef}
|
|
||||||
src={preview}
|
|
||||||
alt="Preview"
|
|
||||||
style={{ maxWidth: '100%', maxHeight: globalInputHeight }}
|
|
||||||
onLoad={onImageLoad}
|
|
||||||
/>
|
|
||||||
</ReactCrop>
|
|
||||||
) : (
|
|
||||||
<img
|
|
||||||
ref={imageRef}
|
|
||||||
src={preview}
|
|
||||||
alt="Preview"
|
|
||||||
style={{ maxWidth: '100%', maxHeight: globalInputHeight }}
|
|
||||||
onLoad={onImageLoad}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
{type === 'video' && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: 'relative',
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<video
|
|
||||||
ref={videoRef}
|
|
||||||
src={preview}
|
|
||||||
style={{
|
|
||||||
maxWidth: '100%',
|
|
||||||
maxHeight: showTrimControls ? 'calc(100% - 50px)' : '100%'
|
|
||||||
}}
|
|
||||||
onLoadedMetadata={onVideoLoad}
|
|
||||||
controls={!showTrimControls}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{showTrimControls && videoDuration > 0 && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '10px 20px',
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
||||||
color: 'white',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
gap: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="caption">
|
|
||||||
Start: {formatTime(trimStart || 0)}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="caption">
|
|
||||||
End: {formatTime(trimEnd || videoDuration)}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
||||||
<div
|
|
||||||
className="range-slider-container"
|
|
||||||
style={{ margin: '20px 0', width: '100%' }}
|
|
||||||
>
|
|
||||||
<Slider
|
|
||||||
range
|
|
||||||
min={0}
|
|
||||||
max={videoDuration}
|
|
||||||
step={0.1}
|
|
||||||
value={[trimStart || 0, trimEnd || videoDuration]}
|
|
||||||
onChange={(values) => {
|
|
||||||
if (Array.isArray(values)) {
|
|
||||||
handleTrimChange(values[0], values[1]);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
allowCross={false}
|
|
||||||
pushable={0.1} // Minimum distance between handles
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
{type === 'audio' && (
|
|
||||||
<audio
|
|
||||||
src={preview}
|
|
||||||
controls
|
|
||||||
style={{ width: '100%', maxWidth: '500px' }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
onClick={handleImportClick}
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
padding: 5,
|
|
||||||
height: '100%',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography color={theme.palette.grey['600']}>
|
|
||||||
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
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
<InputFooter handleCopy={handleCopy} handleImport={handleImportClick} />
|
|
||||||
<input
|
|
||||||
ref={fileInputRef}
|
|
||||||
style={{ display: 'none' }}
|
|
||||||
type="file"
|
|
||||||
accept={accept.join(',')}
|
|
||||||
onChange={handleFileChange}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
@@ -52,7 +52,7 @@ export default function ToolTextInput({
|
|||||||
rows={10}
|
rows={10}
|
||||||
sx={{
|
sx={{
|
||||||
'&.MuiTextField-root': {
|
'&.MuiTextField-root': {
|
||||||
backgroundColor: 'white'
|
backgroundColor: 'background.paper'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
inputProps={{
|
inputProps={{
|
||||||
|
@@ -30,7 +30,7 @@ const ColorSelector: React.FC<ColorSelectorProps & TextFieldProps> = ({
|
|||||||
<Box mb={1}>
|
<Box mb={1}>
|
||||||
<Stack direction={'row'}>
|
<Stack direction={'row'}>
|
||||||
<TextField
|
<TextField
|
||||||
sx={{ backgroundColor: 'white' }}
|
sx={{ backgroundColor: 'background.paper' }}
|
||||||
value={color}
|
value={color}
|
||||||
onChange={handleColorChange}
|
onChange={handleColorChange}
|
||||||
{...props}
|
{...props}
|
||||||
|
@@ -19,7 +19,7 @@ const TextFieldWithDesc = ({
|
|||||||
<Box>
|
<Box>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
sx={{ backgroundColor: 'white' }}
|
sx={{ backgroundColor: 'background.paper' }}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(event) => onOwnChange(event.target.value)}
|
onChange={(event) => onOwnChange(event.target.value)}
|
||||||
{...props}
|
{...props}
|
||||||
|
@@ -36,7 +36,7 @@ export default function ToolOptions<T extends FormikValues>({
|
|||||||
mb: 2,
|
mb: 2,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
padding: 2,
|
padding: 2,
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: 'background.lightSecondary',
|
||||||
boxShadow: '2'
|
boxShadow: '2'
|
||||||
}}
|
}}
|
||||||
mt={2}
|
mt={2}
|
||||||
|
@@ -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 React, { useContext } from 'react';
|
||||||
import InputHeader from '../InputHeader';
|
import InputHeader from '../InputHeader';
|
||||||
import greyPattern from '@assets/grey-pattern.png';
|
import greyPattern from '@assets/grey-pattern.png';
|
||||||
@@ -21,6 +21,7 @@ export default function ToolFileResult({
|
|||||||
}) {
|
}) {
|
||||||
const [preview, setPreview] = React.useState<string | null>(null);
|
const [preview, setPreview] = React.useState<string | null>(null);
|
||||||
const { showSnackBar } = useContext(CustomSnackBarContext);
|
const { showSnackBar } = useContext(CustomSnackBarContext);
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -87,7 +88,7 @@ export default function ToolFileResult({
|
|||||||
border: preview ? 0 : 1,
|
border: preview ? 0 : 1,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
boxShadow: '5',
|
boxShadow: '5',
|
||||||
bgcolor: 'white'
|
bgcolor: 'background.paper'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
@@ -114,7 +115,8 @@ export default function ToolFileResult({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
backgroundImage: `url(${greyPattern})`
|
backgroundImage:
|
||||||
|
theme.palette.mode === 'dark' ? null : `url(${greyPattern})`
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{fileType === 'image' && (
|
{fileType === 'image' && (
|
||||||
|
@@ -52,7 +52,7 @@ export default function ToolTextResult({
|
|||||||
multiline
|
multiline
|
||||||
sx={{
|
sx={{
|
||||||
'&.MuiTextField-root': {
|
'&.MuiTextField-root': {
|
||||||
backgroundColor: 'white'
|
backgroundColor: 'background.paper'
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
rows={10}
|
rows={10}
|
||||||
|
@@ -1,13 +1,50 @@
|
|||||||
import { createTheme } from '@mui/material';
|
import { createTheme, ThemeOptions } from '@mui/material';
|
||||||
|
|
||||||
const theme = createTheme({
|
const sharedThemeOptions: ThemeOptions = {
|
||||||
typography: {
|
typography: {
|
||||||
button: {
|
button: {
|
||||||
textTransform: 'none'
|
textTransform: 'none'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
palette: { background: { default: '#ebf5ff' } },
|
|
||||||
zIndex: { snackbar: 100000 }
|
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' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { getToolsByCategory } from '@tools/index';
|
import { getToolsByCategory } from '@tools/index';
|
||||||
import Grid from '@mui/material/Grid';
|
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 { Link, useNavigate } from 'react-router-dom';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
@@ -19,6 +19,7 @@ const SingleCategory = function ({
|
|||||||
index: number;
|
index: number;
|
||||||
}) {
|
}) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const theme = useTheme();
|
||||||
const [hovered, setHovered] = useState<boolean>(false);
|
const [hovered, setHovered] = useState<boolean>(false);
|
||||||
const toggleHover = () => setHovered((prevState) => !prevState);
|
const toggleHover = () => setHovered((prevState) => !prevState);
|
||||||
return (
|
return (
|
||||||
@@ -32,7 +33,7 @@ const SingleCategory = function ({
|
|||||||
<Card
|
<Card
|
||||||
sx={{
|
sx={{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
backgroundColor: hovered ? '#FAFAFD' : 'white'
|
backgroundColor: hovered ? 'background.hover' : 'background.paper'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CardContent sx={{ height: '100%' }}>
|
<CardContent sx={{ height: '100%' }}>
|
||||||
@@ -52,7 +53,11 @@ const SingleCategory = function ({
|
|||||||
color={categoriesColors[index % categoriesColors.length]}
|
color={categoriesColors[index % categoriesColors.length]}
|
||||||
/>
|
/>
|
||||||
<Link
|
<Link
|
||||||
style={{ fontSize: 20, fontWeight: 700, color: 'black' }}
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 700,
|
||||||
|
color: theme.palette.mode === 'dark' ? 'white' : 'black'
|
||||||
|
}}
|
||||||
to={'/categories/' + category.type}
|
to={'/categories/' + category.type}
|
||||||
>
|
>
|
||||||
{category.title}
|
{category.title}
|
||||||
@@ -70,7 +75,7 @@ const SingleCategory = function ({
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid item xs={12} md={6}>
|
||||||
<Button
|
<Button
|
||||||
sx={{ backgroundColor: 'white' }}
|
sx={{ backgroundColor: 'background.default' }}
|
||||||
fullWidth
|
fullWidth
|
||||||
onClick={() => navigate(category.example.path)}
|
onClick={() => navigate(category.example.path)}
|
||||||
variant={'outlined'}
|
variant={'outlined'}
|
||||||
|
@@ -1,16 +1,23 @@
|
|||||||
import { Box } from '@mui/material';
|
import { Box, useTheme } from '@mui/material';
|
||||||
import Hero from 'components/Hero';
|
import Hero from 'components/Hero';
|
||||||
import Categories from './Categories';
|
import Categories from './Categories';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
const theme = useTheme();
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
padding={{
|
padding={{
|
||||||
xs: 1,
|
xs: 1,
|
||||||
md: 3,
|
md: 3,
|
||||||
lg: 5,
|
lg: 5
|
||||||
background: `url(/assets/background.svg)`,
|
}}
|
||||||
backgroundColor: '#F5F5FA'
|
sx={{
|
||||||
|
background: `url(/assets/${
|
||||||
|
theme.palette.mode === 'dark'
|
||||||
|
? 'background-dark.png'
|
||||||
|
: 'background.svg'
|
||||||
|
})`,
|
||||||
|
backgroundColor: 'background.default'
|
||||||
}}
|
}}
|
||||||
display={'flex'}
|
display={'flex'}
|
||||||
flexDirection={'column'}
|
flexDirection={'column'}
|
||||||
|
@@ -26,7 +26,7 @@ export default function Home() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ backgroundColor: '#F5F5FA' }}>
|
<Box sx={{ backgroundColor: 'background.default' }}>
|
||||||
<Box
|
<Box
|
||||||
padding={{ xs: 1, md: 3, lg: 5 }}
|
padding={{ xs: 1, md: 3, lg: 5 }}
|
||||||
display={'flex'}
|
display={'flex'}
|
||||||
@@ -55,12 +55,14 @@ export default function Home() {
|
|||||||
<Grid item xs={12} md={6} lg={4} key={tool.path}>
|
<Grid item xs={12} md={6} lg={4} key={tool.path}>
|
||||||
<Stack
|
<Stack
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'background.paper',
|
||||||
boxShadow: '5px 4px 2px #E9E9ED',
|
boxShadow: `5px 4px 2px ${
|
||||||
|
theme.palette.mode === 'dark' ? 'black' : '#E9E9ED'
|
||||||
|
}`,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: theme.palette.background.default // Change this to your desired hover color
|
backgroundColor: theme.palette.background.hover
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onClick={() => navigate('/' + tool.path)}
|
onClick={() => navigate('/' + tool.path)}
|
||||||
@@ -77,7 +79,12 @@ export default function Home() {
|
|||||||
color={categoriesColors[index % categoriesColors.length]}
|
color={categoriesColors[index % categoriesColors.length]}
|
||||||
/>
|
/>
|
||||||
<Box>
|
<Box>
|
||||||
<Link style={{ fontSize: 20 }} to={'/' + tool.path}>
|
<Link
|
||||||
|
style={{
|
||||||
|
fontSize: 20
|
||||||
|
}}
|
||||||
|
to={'/' + tool.path}
|
||||||
|
>
|
||||||
{tool.name}
|
{tool.name}
|
||||||
</Link>
|
</Link>
|
||||||
<Typography sx={{ mt: 2 }}>
|
<Typography sx={{ mt: 2 }}>
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { Box, Typography } from '@mui/material';
|
import { Box, Typography } from '@mui/material';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import ToolFileInput from '@components/input/ToolFileInput';
|
|
||||||
import ToolFileResult from '@components/result/ToolFileResult';
|
import ToolFileResult from '@components/result/ToolFileResult';
|
||||||
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
|
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
|
||||||
import ToolContent from '@components/ToolContent';
|
import ToolContent from '@components/ToolContent';
|
||||||
@@ -8,7 +7,6 @@ import { ToolComponentProps } from '@tools/defineTool';
|
|||||||
import { parsePageRanges, splitPdf } from './service';
|
import { parsePageRanges, splitPdf } from './service';
|
||||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||||
import { PDFDocument } from 'pdf-lib';
|
import { PDFDocument } from 'pdf-lib';
|
||||||
import { FormikProps } from 'formik';
|
|
||||||
import ToolPdfInput from '@components/input/ToolPdfInput';
|
import ToolPdfInput from '@components/input/ToolPdfInput';
|
||||||
|
|
||||||
type InitialValuesType = {
|
type InitialValuesType = {
|
||||||
|
@@ -15,7 +15,6 @@ export async function compressVideo(
|
|||||||
input: File,
|
input: File,
|
||||||
options: CompressVideoOptions
|
options: CompressVideoOptions
|
||||||
): Promise<File> {
|
): Promise<File> {
|
||||||
console.log('Compressing video...', options);
|
|
||||||
if (!ffmpeg.loaded) {
|
if (!ffmpeg.loaded) {
|
||||||
await ffmpeg.load({
|
await ffmpeg.load({
|
||||||
wasmURL:
|
wasmURL:
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import ToolFileInput from '@components/input/ToolFileInput';
|
|
||||||
import ToolFileResult from '@components/result/ToolFileResult';
|
import ToolFileResult from '@components/result/ToolFileResult';
|
||||||
import TextFieldWithDesc from 'components/options/TextFieldWithDesc';
|
import TextFieldWithDesc from 'components/options/TextFieldWithDesc';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
@@ -9,6 +8,8 @@ import { FrameOptions, GifReader, GifWriter } from 'omggif';
|
|||||||
import { gifBinaryToFile } from '@utils/gif';
|
import { gifBinaryToFile } from '@utils/gif';
|
||||||
import ToolContent from '@components/ToolContent';
|
import ToolContent from '@components/ToolContent';
|
||||||
import { ToolComponentProps } from '@tools/defineTool';
|
import { ToolComponentProps } from '@tools/defineTool';
|
||||||
|
import ToolVideoInput from '@components/input/ToolVideoInput';
|
||||||
|
import ToolImageInput from '@components/input/ToolImageInput';
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
newSpeed: 200
|
newSpeed: 200
|
||||||
@@ -108,7 +109,7 @@ export default function ChangeSpeed({ title }: ToolComponentProps) {
|
|||||||
title={title}
|
title={title}
|
||||||
input={input}
|
input={input}
|
||||||
inputComponent={
|
inputComponent={
|
||||||
<ToolFileInput
|
<ToolImageInput
|
||||||
value={input}
|
value={input}
|
||||||
onChange={setInput}
|
onChange={setInput}
|
||||||
accept={['image/gif']}
|
accept={['image/gif']}
|
||||||
|
@@ -2,11 +2,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "./src",
|
"baseUrl": "./src",
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"lib": [
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"dom",
|
|
||||||
"dom.iterable",
|
|
||||||
"esnext"
|
|
||||||
],
|
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
@@ -19,30 +15,14 @@
|
|||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"types": [
|
"types": ["vite/client", "vitest/globals", "@testing-library/jest-dom"],
|
||||||
"vite/client",
|
|
||||||
"vitest/globals",
|
|
||||||
"@testing-library/jest-dom"
|
|
||||||
],
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@tools/*": [
|
"@tools/*": ["./tools/*"],
|
||||||
"./tools/*"
|
"@assets/*": ["./assets/*"],
|
||||||
],
|
"@components/*": ["./components/*"],
|
||||||
"@assets/*": [
|
"@utils/*": ["./utils/*"]
|
||||||
"./assets/*"
|
|
||||||
],
|
|
||||||
"@components/*": [
|
|
||||||
"./components/*"
|
|
||||||
],
|
|
||||||
"@utils/*": [
|
|
||||||
"./utils/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src", "./@types"],
|
||||||
"src"
|
"exclude": ["node_modules"]
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user