refactor: apply eslint
This commit is contained in:
@@ -1,80 +1,80 @@
|
||||
import { Suspense } from 'react';
|
||||
import { Suspense } from "react";
|
||||
|
||||
import { Routes, Route, Outlet } from "react-router-dom";
|
||||
import Home from "./pages/Home";
|
||||
import About from "./pages/About";
|
||||
import Dashboard from "./pages/Dashboard";
|
||||
import ToPdf from "./pages/convert/ToPdf"
|
||||
import Impose from "./pages/page-operations/Impose"
|
||||
import ToPdf from "./pages/convert/ToPdf";
|
||||
import Impose from "./pages/page-operations/Impose";
|
||||
import NoMatch from "./pages/NoMatch";
|
||||
import NavBar from "./components/NavBar";
|
||||
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import { Container } from "react-bootstrap";
|
||||
|
||||
import i18n from "i18next";
|
||||
import { useTranslation, initReactI18next } from "react-i18next";
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import ar from './locales/ar.json';
|
||||
import en from './locales/en.json';
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
import ar from "./locales/ar.json";
|
||||
import en from "./locales/en.json";
|
||||
|
||||
import './general.css'
|
||||
import "./general.css";
|
||||
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next) // passes i18n down to react-i18next
|
||||
.init({
|
||||
fallbackLng: "en",
|
||||
resources: { ar,en },
|
||||
});
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next) // passes i18n down to react-i18next
|
||||
.init({
|
||||
fallbackLng: "en",
|
||||
resources: { ar,en },
|
||||
});
|
||||
|
||||
export default function App() {
|
||||
|
||||
return (
|
||||
<Suspense fallback="loading">
|
||||
{/* Routes nest inside one another. Nested route paths build upon
|
||||
return (
|
||||
<Suspense fallback="loading">
|
||||
{/* Routes nest inside one another. Nested route paths build upon
|
||||
parent route paths, and nested route elements render inside
|
||||
parent route elements. See the note about <Outlet> below. */}
|
||||
<Routes>
|
||||
<Route path="/" element={<Layout />}>
|
||||
<Route index element={<Home />} />
|
||||
<Route path="about" element={<About />} />
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
<Routes>
|
||||
<Route path="/" element={<Layout />}>
|
||||
<Route index element={<Home />} />
|
||||
<Route path="about" element={<About />} />
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
|
||||
{/* Using path="*"" means "match anything", so this route
|
||||
{/* Using path="*"" means "match anything", so this route
|
||||
acts like a catch-all for URLs that we don't have explicit
|
||||
routes for. */}
|
||||
<Route path="*" element={<NoMatch />} />
|
||||
</Route>
|
||||
<Route path="/convert" element={<Layout />}>
|
||||
<Route path="file-to-pdf" element={<ToPdf />} />
|
||||
<Route path="*" element={<NoMatch />} />
|
||||
</Route>
|
||||
<Route path="/page-operations" element={<Layout />}>
|
||||
<Route path="impose" element={<Impose />} />
|
||||
<Route path="*" element={<NoMatch />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
);
|
||||
<Route path="*" element={<NoMatch />} />
|
||||
</Route>
|
||||
<Route path="/convert" element={<Layout />}>
|
||||
<Route path="file-to-pdf" element={<ToPdf />} />
|
||||
<Route path="*" element={<NoMatch />} />
|
||||
</Route>
|
||||
<Route path="/page-operations" element={<Layout />}>
|
||||
<Route path="impose" element={<Impose />} />
|
||||
<Route path="*" element={<NoMatch />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
function Layout() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div lang-direction={t('language.direction')}>
|
||||
<NavBar/>
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div lang-direction={t("language.direction")}>
|
||||
<NavBar/>
|
||||
|
||||
{/* An <Outlet> renders whatever child route is currently active,
|
||||
{/* An <Outlet> renders whatever child route is currently active,
|
||||
so you can think about this <Outlet> as a placeholder for
|
||||
the child routes we defined above. */}
|
||||
<Container fluid="sm" className="">
|
||||
<div className="row justify-content-center">
|
||||
<div className="col-md-6">
|
||||
<Outlet/>
|
||||
</div>
|
||||
<Container fluid="sm" className="">
|
||||
<div className="row justify-content-center">
|
||||
<div className="col-md-6">
|
||||
<Outlet/>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import Form from 'react-bootstrap/Form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FieldConstraint, RecordConstraint } from '@stirling-pdf/shared-operations/src/dynamic-ui/OperatorConstraints'
|
||||
import Form from "react-bootstrap/Form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FieldConstraint, RecordConstraint } from "@stirling-pdf/shared-operations/src/dynamic-ui/OperatorConstraints";
|
||||
|
||||
interface DynamicParameterFieldsProps {
|
||||
constraints: RecordConstraint;
|
||||
@@ -13,15 +13,15 @@ const DynamicParameterFields: React.FC<DynamicParameterFieldsProps> = ({constrai
|
||||
|
||||
return (<>
|
||||
{Object.entries(constraints.record).map(([fieldName, value]) => {
|
||||
console.log(fieldName, value)
|
||||
console.log(fieldName, value);
|
||||
const globallyUniqueId = joinKeyPath([...parentKeyPath, fieldName]);
|
||||
return <div className='mb-3' key={fieldName} >
|
||||
<label htmlFor={globallyUniqueId}>{t(value.displayNameKey)}</label>
|
||||
{fieldConstraintToElement(fieldName, parentKeyPath, globallyUniqueId, value)}
|
||||
</div>
|
||||
</div>;
|
||||
})}
|
||||
</>);
|
||||
}
|
||||
};
|
||||
|
||||
function joinKeyPath(keyPath: string[]) {
|
||||
return keyPath.join(".");
|
||||
@@ -29,7 +29,7 @@ function joinKeyPath(keyPath: string[]) {
|
||||
|
||||
function fieldConstraintToElement(fieldName: string, parentKeyPath: string[], globallyUniqueId: string, fieldConstraint: FieldConstraint) {
|
||||
if (Array.isArray(fieldConstraint.type)) {
|
||||
if (fieldConstraint.type.every(e => typeof e == 'string' || typeof e == 'number')) {
|
||||
if (fieldConstraint.type.every(e => typeof e == "string" || typeof e == "number")) {
|
||||
return (
|
||||
<Form.Select id={globallyUniqueId} name={fieldName}>
|
||||
<option value="" disabled>Select an option</option>
|
||||
@@ -37,27 +37,27 @@ function fieldConstraintToElement(fieldName: string, parentKeyPath: string[], gl
|
||||
</Form.Select>
|
||||
);
|
||||
} else {
|
||||
return <div key={fieldName}>Error: Field type '{fieldConstraint.type}' not supported</div>
|
||||
return <div key={fieldName}>Error: Field type '{fieldConstraint.type}' not supported</div>;
|
||||
}
|
||||
} else if (typeof fieldConstraint.type == 'string') {
|
||||
} else if (typeof fieldConstraint.type == "string") {
|
||||
switch (fieldConstraint.type) {
|
||||
case "file.pdf":
|
||||
return <input id={globallyUniqueId} type="file" name={fieldName} required={fieldConstraint.required} className="form-control required" accept="application/pdf" multiple={false}/>;
|
||||
case "files.pdf":
|
||||
return <input id={globallyUniqueId} type="file" name={fieldName} required={fieldConstraint.required} className="form-control required" accept="application/pdf" multiple={true}/>;
|
||||
case "string":
|
||||
return <input id={globallyUniqueId} type="text" name={fieldName} required={fieldConstraint.required} />;
|
||||
case "number":
|
||||
return <input id={globallyUniqueId} type="number" name={fieldName} required={fieldConstraint.required} />;
|
||||
default:
|
||||
return <div key={fieldName}>Error: Field type '{fieldConstraint.type}' not supported</div>
|
||||
case "file.pdf":
|
||||
return <input id={globallyUniqueId} type="file" name={fieldName} required={fieldConstraint.required} className="form-control required" accept="application/pdf" multiple={false}/>;
|
||||
case "files.pdf":
|
||||
return <input id={globallyUniqueId} type="file" name={fieldName} required={fieldConstraint.required} className="form-control required" accept="application/pdf" multiple={true}/>;
|
||||
case "string":
|
||||
return <input id={globallyUniqueId} type="text" name={fieldName} required={fieldConstraint.required} />;
|
||||
case "number":
|
||||
return <input id={globallyUniqueId} type="number" name={fieldName} required={fieldConstraint.required} />;
|
||||
default:
|
||||
return <div key={fieldName}>Error: Field type '{fieldConstraint.type}' not supported</div>;
|
||||
}
|
||||
} else if (fieldConstraint.type instanceof RecordConstraint) {
|
||||
//return <DynamicParameterFields constraints={fieldConstraint.type} parentKeyPath={[...parentKeyPath, fieldName]}/>
|
||||
return <div key={fieldName}>Error: Field type 'RecordConstraint' not supported yet!</div>
|
||||
return <div key={fieldName}>Error: Field type 'RecordConstraint' not supported yet!</div>;
|
||||
}
|
||||
|
||||
return <div key={fieldName}>Error: Field type '{fieldConstraint.type}' not supported</div>
|
||||
return <div key={fieldName}>Error: Field type '{fieldConstraint.type}' not supported</div>;
|
||||
}
|
||||
|
||||
export default DynamicParameterFields;
|
||||
@@ -2,25 +2,25 @@
|
||||
import { AiOutlineMergeCells, AiOutlineSplitCells } from "react-icons/ai";
|
||||
import { BiCrop, BiSprayCan } from "react-icons/bi";
|
||||
import {
|
||||
BsTools, BsSortNumericDown, BsArrowClockwise, BsFileEarmarkX, BsLayoutSplit, BsPalette, BsArrowUpSquare, Bs1Square, BsFileEarmarkPdf,
|
||||
BsArrowLeftRight, BsFileEarmarkImage, BsFileEarmark, BsFiletypeHtml, BsLink, BsFiletypeMd, BsFileEarmarkWord, BsFiletypePpt, BsFiletypeTxt,
|
||||
BsFiletypeXml, BsLock, BsUnlock, BsShieldLock, BsDroplet, BsAward, BsEraserFill, BsCardList, BsClipboardData, BsFile, BsFileEarmarkRichtext,
|
||||
BsFileZip, BsFiletypeJs, BsFonts, BsImages, BsInfoCircle, BsSearch, BsShieldCheck, BsVectorPen, BsWrench, BsArrowsCollapse, BsGrid, Bs123,
|
||||
BsArrowsFullscreen
|
||||
BsTools, BsSortNumericDown, BsArrowClockwise, BsFileEarmarkX, BsLayoutSplit, BsPalette, BsArrowUpSquare, Bs1Square, BsFileEarmarkPdf,
|
||||
BsArrowLeftRight, BsFileEarmarkImage, BsFileEarmark, BsFiletypeHtml, BsLink, BsFiletypeMd, BsFileEarmarkWord, BsFiletypePpt, BsFiletypeTxt,
|
||||
BsFiletypeXml, BsLock, BsUnlock, BsShieldLock, BsDroplet, BsAward, BsEraserFill, BsCardList, BsClipboardData, BsFile, BsFileEarmarkRichtext,
|
||||
BsFileZip, BsFiletypeJs, BsFonts, BsImages, BsInfoCircle, BsSearch, BsShieldCheck, BsVectorPen, BsWrench, BsArrowsCollapse, BsGrid, Bs123,
|
||||
BsArrowsFullscreen
|
||||
} from "react-icons/bs";
|
||||
import { MdOutlineScanner, MdOutlineBalance } from "react-icons/md";
|
||||
import { IconType } from "react-icons";
|
||||
|
||||
import Container from 'react-bootstrap/Container';
|
||||
import Nav from 'react-bootstrap/Nav';
|
||||
import Navbar from 'react-bootstrap/Navbar';
|
||||
import NavDropdown from 'react-bootstrap/NavDropdown';
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Container from "react-bootstrap/Container";
|
||||
import Nav from "react-bootstrap/Nav";
|
||||
import Navbar from "react-bootstrap/Navbar";
|
||||
import NavDropdown from "react-bootstrap/NavDropdown";
|
||||
import { LinkContainer } from "react-router-bootstrap";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import LanguagePicker from "./toolbar/LanguagePicker";
|
||||
import Logo from '../../public/stirling-pdf-logo.svg'
|
||||
import './NavBar.css';
|
||||
import Logo from "../../public/stirling-pdf-logo.svg";
|
||||
import "./NavBar.css";
|
||||
|
||||
interface NavInfoItem {
|
||||
displayText: string;
|
||||
@@ -31,143 +31,143 @@ interface NavInfoItem {
|
||||
interface NavInfoSublist {
|
||||
displayText: string;
|
||||
icon: IconType;
|
||||
sublist: Array<NavInfoItem>;
|
||||
sublist: NavInfoItem[];
|
||||
}
|
||||
|
||||
function convertToNavLink(item: NavInfoItem, index: number) {
|
||||
return <LinkContainer key={"nav-link-"+index} to={item.dest}><Nav.Link className="nav-icon" title={item.tooltip}><item.icon/><span>{item.displayText}</span></Nav.Link></LinkContainer>;
|
||||
return <LinkContainer key={"nav-link-"+index} to={item.dest}><Nav.Link className="nav-icon" title={item.tooltip}><item.icon/><span>{item.displayText}</span></Nav.Link></LinkContainer>;
|
||||
}
|
||||
function convertToNavDropdownItem(item: NavInfoItem | null, index: number) {
|
||||
if (item == null)
|
||||
return <NavDropdown.Divider key={"nav-dropdown-divider-"+index}/>;
|
||||
if (item == null)
|
||||
return <NavDropdown.Divider key={"nav-dropdown-divider-"+index}/>;
|
||||
|
||||
return (
|
||||
<LinkContainer to={item.dest} key={"nav-dropdown-item-"+index}>
|
||||
<NavDropdown.Item className="nav-icon" title={item.tooltip}>
|
||||
<item.icon/>
|
||||
<span>{item.displayText}</span>
|
||||
</NavDropdown.Item>
|
||||
</LinkContainer>
|
||||
);
|
||||
return (
|
||||
<LinkContainer to={item.dest} key={"nav-dropdown-item-"+index}>
|
||||
<NavDropdown.Item className="nav-icon" title={item.tooltip}>
|
||||
<item.icon/>
|
||||
<span>{item.displayText}</span>
|
||||
</NavDropdown.Item>
|
||||
</LinkContainer>
|
||||
);
|
||||
}
|
||||
function convertToNavDropdown(sublist: NavInfoSublist, index: number) {
|
||||
var myTitle = <>
|
||||
<span className="nav-icon">
|
||||
<sublist.icon/>
|
||||
<span>{sublist.displayText}</span>
|
||||
</span>
|
||||
</>;
|
||||
const myTitle = <>
|
||||
<span className="nav-icon">
|
||||
<sublist.icon/>
|
||||
<span>{sublist.displayText}</span>
|
||||
</span>
|
||||
</>;
|
||||
|
||||
return (
|
||||
<NavDropdown title={myTitle} id="basic-nav-dropdown" key={"nav-dropdown-"+index}>
|
||||
{sublist.sublist.map((item, i) => convertToNavDropdownItem(item, i))}
|
||||
</NavDropdown>
|
||||
);
|
||||
return (
|
||||
<NavDropdown title={myTitle} id="basic-nav-dropdown" key={"nav-dropdown-"+index}>
|
||||
{sublist.sublist.map((item, i) => convertToNavDropdownItem(item, i))}
|
||||
</NavDropdown>
|
||||
);
|
||||
}
|
||||
|
||||
function NavBar() {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const navInfo = [
|
||||
{displayText: t('multiTool.title'), icon: BsTools, dest: "/home", tooltip: t('home.multiTool.desc')},
|
||||
{displayText: t('navbar.pageOps'), icon: BsFileEarmarkPdf, sublist: [
|
||||
{ displayText: t('home.merge.title'), icon: AiOutlineMergeCells, dest: "/dashboard", tooltip: t('home.merge.desc') },
|
||||
{ displayText: t('home.split.title'), icon: AiOutlineSplitCells, dest: "/about", tooltip: t('home.split.desc') },
|
||||
{ displayText: t('home.pdfOrganiser.title'), icon: BsSortNumericDown, dest: "/nothing-here", tooltip: t('home.pdfOrganiser.desc') },
|
||||
{ displayText: t('home.rotate.title'), icon: BsArrowClockwise, dest: "/nothing-here", tooltip: t('home.rotate.desc') },
|
||||
{ displayText: t('home.removePages.title'), icon: BsFileEarmarkX, dest: "/nothing-here", tooltip: t('home.removePages.desc') },
|
||||
{ displayText: t('home.pageLayout.title'), icon: BsGrid, dest: "/page-operations/impose", tooltip: t('home.pageLayout.desc') },
|
||||
{ displayText: t('home.scalePages.title'), icon: BsArrowsFullscreen, dest: "/nothing-here", tooltip: t('home.scalePages.desc') },
|
||||
{ displayText: t('home.autoSplitPDF.title'), icon: BsLayoutSplit, dest: "/nothing-here", tooltip: t('home.autoSplitPDF.desc') },
|
||||
{ displayText: t('home.adjust-contrast.title'), icon: BsPalette, dest: "/nothing-here", tooltip: t('home.adjust-contrast.desc') },
|
||||
{ displayText: t('home.crop.title'), icon: BiCrop, dest: "/nothing-here", tooltip: t('home.crop.desc') },
|
||||
{ displayText: t('home.extractPage.title'), icon: BsArrowUpSquare, dest: "/nothing-here", tooltip: t('home.extractPage.desc') },
|
||||
{ displayText: t('home.PdfToSinglePage.title'), icon: Bs1Square, dest: "/nothing-here", tooltip: t('home.PdfToSinglePage.desc') },
|
||||
]},
|
||||
{displayText: t('navbar.convert'), icon: BsArrowLeftRight, sublist: [
|
||||
{ displayText: t('home.imageToPdf.title'), icon: BsFileEarmarkImage, dest: "/dashboard", tooltip: t('home.imageToPdf.desc') },
|
||||
{ displayText: t('home.fileToPDF.title'), icon: BsFileEarmark, dest: "/convert/file-to-pdf", tooltip: t('home.fileToPDF.desc') },
|
||||
{ displayText: t('home.HTMLToPDF.title'), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t('home.HTMLToPDF.desc') },
|
||||
{ displayText: t('home.URLToPDF.title'), icon: BsLink, dest: "/nothing-here", tooltip: t('home.URLToPDF.desc') },
|
||||
{ displayText: t('home.MarkdownToPDF.title'), icon: BsFiletypeMd, dest: "/nothing-here", tooltip: t('home.MarkdownToPDF.desc') },
|
||||
null,
|
||||
{ displayText: t('home.pdfToImage.title'), icon: BsFileEarmarkImage, dest: "/nothing-here", tooltip: t('home.pdfToImage.desc') },
|
||||
{ displayText: t('home.PDFToWord.title'), icon: BsFileEarmarkWord, dest: "/nothing-here", tooltip: t('home.PDFToWord.desc') },
|
||||
{ displayText: t('home.PDFToPresentation.title'), icon: BsFiletypePpt, dest: "/nothing-here", tooltip: t('home.PDFToPresentation.desc') },
|
||||
{ displayText: t('home.PDFToText.title'), icon: BsFiletypeTxt, dest: "/nothing-here", tooltip: t('home.PDFToText.desc') },
|
||||
{ displayText: t('home.PDFToHTML.title'), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t('home.PDFToHTML.desc') },
|
||||
{ displayText: t('home.PDFToXML.title'), icon: BsFiletypeXml, dest: "/nothing-here", tooltip: t('home.PDFToXML.desc') },
|
||||
{ displayText: t('home.pdfToPDFA.title'), icon: BsFileEarmarkPdf, dest: "/nothing-here", tooltip: t('home.pdfToPDFA.desc') },
|
||||
]},
|
||||
{displayText: t('navbar.security'), icon: BsShieldCheck, sublist: [
|
||||
{ displayText: t('home.addPassword.title'), icon: BsLock, dest: "/dashboard", tooltip: t('home.addPassword.desc') },
|
||||
{ displayText: t('home.removePassword.title'), icon: BsUnlock, dest: "/nothing-here", tooltip: t('home.removePassword.desc') },
|
||||
{ displayText: t('home.permissions.title'), icon: BsShieldLock, dest: "/nothing-here", tooltip: t('home.permissions.desc') },
|
||||
{ displayText: t('home.watermark.title'), icon: BsDroplet, dest: "/nothing-here", tooltip: t('home.watermark.desc') },
|
||||
{ displayText: t('home.certSign.title'), icon: BsAward, dest: "/nothing-here", tooltip: t('home.certSign.desc') },
|
||||
{ displayText: t('home.sanitizePdf.title'), icon: BiSprayCan, dest: "/nothing-here", tooltip: t('home.sanitizePdf.desc') },
|
||||
{ displayText: t('home.autoRedact.title'), icon: BsEraserFill, dest: "/nothing-here", tooltip: t('home.autoRedact.desc') },
|
||||
]},
|
||||
{displayText: t('navbar.other'), icon: BsCardList, sublist: [
|
||||
{ displayText: t('home.ocr.title'), icon: BsSearch, dest: "/dashboard", tooltip: t('home.ocr.desc') },
|
||||
{ displayText: t('home.addImage.title'), icon: BsFileEarmarkRichtext, dest: "/nothing-here", tooltip: t('home.addImage.desc') },
|
||||
{ displayText: t('home.compressPdfs.title'), icon: BsFileZip, dest: "/nothing-here", tooltip: t('home.compressPdfs.desc') },
|
||||
{ displayText: t('home.extractImages.title'), icon: BsImages, dest: "/nothing-here", tooltip: t('home.extractImages.desc') },
|
||||
{ displayText: t('home.changeMetadata.title'), icon: BsClipboardData, dest: "/nothing-here", tooltip: t('home.changeMetadata.desc') },
|
||||
{ displayText: t('home.ScannerImageSplit.title'), icon: MdOutlineScanner, dest: "/nothing-here", tooltip: t('home.ScannerImageSplit.desc') },
|
||||
{ displayText: t('home.sign.title'), icon: BsVectorPen, dest: "/nothing-here", tooltip: t('home.sign.desc') },
|
||||
{ displayText: t('home.flatten.title'), icon: BsArrowsCollapse, dest: "/nothing-here", tooltip: t('home.flatten.desc') },
|
||||
{ displayText: t('home.repair.title'), icon: BsWrench, dest: "/nothing-here", tooltip: t('home.repair.desc') },
|
||||
{ displayText: t('home.removeBlanks.title'), icon: BsFile, dest: "/nothing-here", tooltip: t('home.removeBlanks.desc') },
|
||||
{ displayText: t('home.compare.title'), icon: MdOutlineBalance, dest: "/nothing-here", tooltip: t('home.compare.desc') },
|
||||
{ displayText: t('home.add-page-numbers.title'), icon: Bs123, dest: "/nothing-here", tooltip: t('home.add-page-numbers.desc') },
|
||||
{ displayText: t('home.auto-rename.title'), icon: BsFonts, dest: "/nothing-here", tooltip: t('home.auto-rename.desc') },
|
||||
{ displayText: t('home.getPdfInfo.title'), icon: BsInfoCircle, dest: "/nothing-here", tooltip: t('home.getPdfInfo.desc') },
|
||||
{ displayText: t('home.showJS.title'), icon: BsFiletypeJs, dest: "/nothing-here", tooltip: t('home.showJS.desc') },
|
||||
]},
|
||||
] as Array<NavInfoItem | NavInfoSublist>;
|
||||
const navInfo = [
|
||||
{displayText: t("multiTool.title"), icon: BsTools, dest: "/home", tooltip: t("home.multiTool.desc")},
|
||||
{displayText: t("navbar.pageOps"), icon: BsFileEarmarkPdf, sublist: [
|
||||
{ displayText: t("home.merge.title"), icon: AiOutlineMergeCells, dest: "/dashboard", tooltip: t("home.merge.desc") },
|
||||
{ displayText: t("home.split.title"), icon: AiOutlineSplitCells, dest: "/about", tooltip: t("home.split.desc") },
|
||||
{ displayText: t("home.pdfOrganiser.title"), icon: BsSortNumericDown, dest: "/nothing-here", tooltip: t("home.pdfOrganiser.desc") },
|
||||
{ displayText: t("home.rotate.title"), icon: BsArrowClockwise, dest: "/nothing-here", tooltip: t("home.rotate.desc") },
|
||||
{ displayText: t("home.removePages.title"), icon: BsFileEarmarkX, dest: "/nothing-here", tooltip: t("home.removePages.desc") },
|
||||
{ displayText: t("home.pageLayout.title"), icon: BsGrid, dest: "/page-operations/impose", tooltip: t("home.pageLayout.desc") },
|
||||
{ displayText: t("home.scalePages.title"), icon: BsArrowsFullscreen, dest: "/nothing-here", tooltip: t("home.scalePages.desc") },
|
||||
{ displayText: t("home.autoSplitPDF.title"), icon: BsLayoutSplit, dest: "/nothing-here", tooltip: t("home.autoSplitPDF.desc") },
|
||||
{ displayText: t("home.adjust-contrast.title"), icon: BsPalette, dest: "/nothing-here", tooltip: t("home.adjust-contrast.desc") },
|
||||
{ displayText: t("home.crop.title"), icon: BiCrop, dest: "/nothing-here", tooltip: t("home.crop.desc") },
|
||||
{ displayText: t("home.extractPage.title"), icon: BsArrowUpSquare, dest: "/nothing-here", tooltip: t("home.extractPage.desc") },
|
||||
{ displayText: t("home.PdfToSinglePage.title"), icon: Bs1Square, dest: "/nothing-here", tooltip: t("home.PdfToSinglePage.desc") },
|
||||
]},
|
||||
{displayText: t("navbar.convert"), icon: BsArrowLeftRight, sublist: [
|
||||
{ displayText: t("home.imageToPdf.title"), icon: BsFileEarmarkImage, dest: "/dashboard", tooltip: t("home.imageToPdf.desc") },
|
||||
{ displayText: t("home.fileToPDF.title"), icon: BsFileEarmark, dest: "/convert/file-to-pdf", tooltip: t("home.fileToPDF.desc") },
|
||||
{ displayText: t("home.HTMLToPDF.title"), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t("home.HTMLToPDF.desc") },
|
||||
{ displayText: t("home.URLToPDF.title"), icon: BsLink, dest: "/nothing-here", tooltip: t("home.URLToPDF.desc") },
|
||||
{ displayText: t("home.MarkdownToPDF.title"), icon: BsFiletypeMd, dest: "/nothing-here", tooltip: t("home.MarkdownToPDF.desc") },
|
||||
null,
|
||||
{ displayText: t("home.pdfToImage.title"), icon: BsFileEarmarkImage, dest: "/nothing-here", tooltip: t("home.pdfToImage.desc") },
|
||||
{ displayText: t("home.PDFToWord.title"), icon: BsFileEarmarkWord, dest: "/nothing-here", tooltip: t("home.PDFToWord.desc") },
|
||||
{ displayText: t("home.PDFToPresentation.title"), icon: BsFiletypePpt, dest: "/nothing-here", tooltip: t("home.PDFToPresentation.desc") },
|
||||
{ displayText: t("home.PDFToText.title"), icon: BsFiletypeTxt, dest: "/nothing-here", tooltip: t("home.PDFToText.desc") },
|
||||
{ displayText: t("home.PDFToHTML.title"), icon: BsFiletypeHtml, dest: "/nothing-here", tooltip: t("home.PDFToHTML.desc") },
|
||||
{ displayText: t("home.PDFToXML.title"), icon: BsFiletypeXml, dest: "/nothing-here", tooltip: t("home.PDFToXML.desc") },
|
||||
{ displayText: t("home.pdfToPDFA.title"), icon: BsFileEarmarkPdf, dest: "/nothing-here", tooltip: t("home.pdfToPDFA.desc") },
|
||||
]},
|
||||
{displayText: t("navbar.security"), icon: BsShieldCheck, sublist: [
|
||||
{ displayText: t("home.addPassword.title"), icon: BsLock, dest: "/dashboard", tooltip: t("home.addPassword.desc") },
|
||||
{ displayText: t("home.removePassword.title"), icon: BsUnlock, dest: "/nothing-here", tooltip: t("home.removePassword.desc") },
|
||||
{ displayText: t("home.permissions.title"), icon: BsShieldLock, dest: "/nothing-here", tooltip: t("home.permissions.desc") },
|
||||
{ displayText: t("home.watermark.title"), icon: BsDroplet, dest: "/nothing-here", tooltip: t("home.watermark.desc") },
|
||||
{ displayText: t("home.certSign.title"), icon: BsAward, dest: "/nothing-here", tooltip: t("home.certSign.desc") },
|
||||
{ displayText: t("home.sanitizePdf.title"), icon: BiSprayCan, dest: "/nothing-here", tooltip: t("home.sanitizePdf.desc") },
|
||||
{ displayText: t("home.autoRedact.title"), icon: BsEraserFill, dest: "/nothing-here", tooltip: t("home.autoRedact.desc") },
|
||||
]},
|
||||
{displayText: t("navbar.other"), icon: BsCardList, sublist: [
|
||||
{ displayText: t("home.ocr.title"), icon: BsSearch, dest: "/dashboard", tooltip: t("home.ocr.desc") },
|
||||
{ displayText: t("home.addImage.title"), icon: BsFileEarmarkRichtext, dest: "/nothing-here", tooltip: t("home.addImage.desc") },
|
||||
{ displayText: t("home.compressPdfs.title"), icon: BsFileZip, dest: "/nothing-here", tooltip: t("home.compressPdfs.desc") },
|
||||
{ displayText: t("home.extractImages.title"), icon: BsImages, dest: "/nothing-here", tooltip: t("home.extractImages.desc") },
|
||||
{ displayText: t("home.changeMetadata.title"), icon: BsClipboardData, dest: "/nothing-here", tooltip: t("home.changeMetadata.desc") },
|
||||
{ displayText: t("home.ScannerImageSplit.title"), icon: MdOutlineScanner, dest: "/nothing-here", tooltip: t("home.ScannerImageSplit.desc") },
|
||||
{ displayText: t("home.sign.title"), icon: BsVectorPen, dest: "/nothing-here", tooltip: t("home.sign.desc") },
|
||||
{ displayText: t("home.flatten.title"), icon: BsArrowsCollapse, dest: "/nothing-here", tooltip: t("home.flatten.desc") },
|
||||
{ displayText: t("home.repair.title"), icon: BsWrench, dest: "/nothing-here", tooltip: t("home.repair.desc") },
|
||||
{ displayText: t("home.removeBlanks.title"), icon: BsFile, dest: "/nothing-here", tooltip: t("home.removeBlanks.desc") },
|
||||
{ displayText: t("home.compare.title"), icon: MdOutlineBalance, dest: "/nothing-here", tooltip: t("home.compare.desc") },
|
||||
{ displayText: t("home.add-page-numbers.title"), icon: Bs123, dest: "/nothing-here", tooltip: t("home.add-page-numbers.desc") },
|
||||
{ displayText: t("home.auto-rename.title"), icon: BsFonts, dest: "/nothing-here", tooltip: t("home.auto-rename.desc") },
|
||||
{ displayText: t("home.getPdfInfo.title"), icon: BsInfoCircle, dest: "/nothing-here", tooltip: t("home.getPdfInfo.desc") },
|
||||
{ displayText: t("home.showJS.title"), icon: BsFiletypeJs, dest: "/nothing-here", tooltip: t("home.showJS.desc") },
|
||||
]},
|
||||
] as (NavInfoItem | NavInfoSublist)[];
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Navbar expand="lg" className="bg-light">
|
||||
<Container>
|
||||
<LinkContainer to="/home">
|
||||
<Navbar.Brand className="nav-icon">
|
||||
<img src={Logo} alt="Image" className="main-icon" />
|
||||
<span className="icon-text">Stirling PDF</span>
|
||||
</Navbar.Brand>
|
||||
</LinkContainer>
|
||||
<Navbar.Toggle aria-controls="basic-navbar-nav"/>
|
||||
<Navbar.Collapse id="basic-navbar-nav">
|
||||
return (
|
||||
<Navbar expand="lg" className="bg-light">
|
||||
<Container>
|
||||
<LinkContainer to="/home">
|
||||
<Navbar.Brand className="nav-icon">
|
||||
<img src={Logo} alt="Image" className="main-icon" />
|
||||
<span className="icon-text">Stirling PDF</span>
|
||||
</Navbar.Brand>
|
||||
</LinkContainer>
|
||||
<Navbar.Toggle aria-controls="basic-navbar-nav"/>
|
||||
<Navbar.Collapse id="basic-navbar-nav">
|
||||
|
||||
<Nav>
|
||||
{navInfo.map((ni, idx) => {
|
||||
var element;
|
||||
if ('dest' in ni) {
|
||||
element = convertToNavLink(ni, idx);
|
||||
} else {
|
||||
element = convertToNavDropdown(ni, idx);
|
||||
}
|
||||
const out: JSX.Element[] = [];
|
||||
if (idx >= 1 ) {
|
||||
out.push( <div className="nav-item nav-item-separator" key={"nav-item-separator-"+idx}></div> );
|
||||
}
|
||||
out.push(element);
|
||||
return out;
|
||||
})}
|
||||
</Nav>
|
||||
<Nav>
|
||||
{navInfo.map((ni, idx) => {
|
||||
let element;
|
||||
if ("dest" in ni) {
|
||||
element = convertToNavLink(ni, idx);
|
||||
} else {
|
||||
element = convertToNavDropdown(ni, idx);
|
||||
}
|
||||
const out: JSX.Element[] = [];
|
||||
if (idx >= 1 ) {
|
||||
out.push( <div className="nav-item nav-item-separator" key={"nav-item-separator-"+idx}></div> );
|
||||
}
|
||||
out.push(element);
|
||||
return out;
|
||||
})}
|
||||
</Nav>
|
||||
|
||||
<div className="flex-fill-remaining-space"></div>
|
||||
<div className="flex-fill-remaining-space"></div>
|
||||
|
||||
<Nav>
|
||||
<LanguagePicker />
|
||||
</Nav>
|
||||
<Nav>
|
||||
<LanguagePicker />
|
||||
</Nav>
|
||||
|
||||
</Navbar.Collapse>
|
||||
</Container>
|
||||
</Navbar>
|
||||
);
|
||||
</Navbar.Collapse>
|
||||
</Container>
|
||||
</Navbar>
|
||||
);
|
||||
}
|
||||
|
||||
export default NavBar;
|
||||
@@ -1,29 +1,29 @@
|
||||
|
||||
import NavDropdown from 'react-bootstrap/NavDropdown';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { BsGlobe2 } from 'react-icons/bs';
|
||||
import NavDropdown from "react-bootstrap/NavDropdown";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { BsGlobe2 } from "react-icons/bs";
|
||||
|
||||
function generateSublist() {
|
||||
const { i18n } = useTranslation();
|
||||
const out: JSX.Element[] = [];
|
||||
const languages = i18n.options.resources;
|
||||
for (var key in languages) {
|
||||
const lang: any = languages[key].translation;
|
||||
const staticKey = key;
|
||||
out.push((
|
||||
<NavDropdown.Item key={"language-"+key} className="nav-icon" onClick={()=>i18n.changeLanguage(staticKey)}>
|
||||
<span>{lang.language?.flag}</span>
|
||||
<span>{lang.language?.name}</span>
|
||||
</NavDropdown.Item>
|
||||
));
|
||||
}
|
||||
return <>{out}</>;
|
||||
const { i18n } = useTranslation();
|
||||
const out: JSX.Element[] = [];
|
||||
const languages = i18n.options.resources;
|
||||
for (const key in languages) {
|
||||
const lang: any = languages[key].translation;
|
||||
const staticKey = key;
|
||||
out.push((
|
||||
<NavDropdown.Item key={"language-"+key} className="nav-icon" onClick={()=>i18n.changeLanguage(staticKey)}>
|
||||
<span>{lang.language?.flag}</span>
|
||||
<span>{lang.language?.name}</span>
|
||||
</NavDropdown.Item>
|
||||
));
|
||||
}
|
||||
return <>{out}</>;
|
||||
}
|
||||
|
||||
export default function LanguagePicker() {
|
||||
return (
|
||||
<NavDropdown id="languages-dropdown" title={<><span className="nav-icon"><BsGlobe2/></span></>}>
|
||||
{generateSublist()}
|
||||
</NavDropdown>
|
||||
);
|
||||
return (
|
||||
<NavDropdown id="languages-dropdown" title={<><span className="nav-icon"><BsGlobe2/></span></>}>
|
||||
{generateSublist()}
|
||||
</NavDropdown>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
declare module '@stirling-pdf/shared-operations/wasm/pdfcpu/pdfcpu-wrapper-browser.js' {
|
||||
declare module "@stirling-pdf/shared-operations/wasm/pdfcpu/pdfcpu-wrapper-browser.js" {
|
||||
export async function oneToOne(wasmArray: any, snapshot: any): Promise<Uint8Array>;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import App from "./App";
|
||||
import "./index.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
function About() {
|
||||
return (
|
||||
<div>
|
||||
<h2>About</h2>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<h2>About</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default About;
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
function Dashboard() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Dashboard</h2>
|
||||
return (
|
||||
<div>
|
||||
<h2>Dashboard</h2>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis aliquet felis in ornare molestie. Quisque et dolor gravida, vulputate libero ultricies, suscipit diam. Pellentesque semper eget purus et rutrum. Duis fringilla elementum tellus, ut egestas nisi ultrices sed. Fusce id elit ipsum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla facilisi. Duis varius, orci vel tempor cursus, elit tellus interdum sem, at vulputate lorem ex et dolor. Vestibulum purus mauris, consequat viverra gravida eget, fermentum a lacus. Phasellus eu varius dolor. Etiam a vulputate sapien. Etiam pulvinar, neque eu elementum imperdiet, nibh ex lobortis magna, ut varius lectus ante tristique massa.
|
||||
|
||||
Nullam quis porttitor sapien. Suspendisse dictum enim vitae tristique aliquet. Nunc imperdiet pellentesque quam, sit amet luctus dui dignissim non. Vivamus eleifend sagittis mauris, at imperdiet nisl. Morbi rutrum magna ut tortor euismod efficitur. Pellentesque quis tortor consectetur, lobortis turpis eget, tincidunt turpis. Nulla consectetur massa ex. Donec lectus purus, interdum sit amet sapien eu, maximus dapibus diam. Suspendisse potenti. In lacinia augue massa, et vulputate eros convallis id. Suspendisse bibendum sagittis posuere. Integer ullamcorper odio eget risus venenatis, non mollis arcu lacinia. Vestibulum feugiat arcu elit, eu varius enim fermentum vitae.
|
||||
@@ -42,8 +42,8 @@ Proin faucibus efficitur sollicitudin. Curabitur pharetra lectus ut metus molest
|
||||
Aenean tincidunt scelerisque ante non vestibulum. Curabitur eleifend ipsum sem, elementum ornare enim ornare eu. In molestie sodales mattis. Morbi ac posuere lorem. Aliquam in nisi ac ipsum euismod bibendum eget id urna. Quisque suscipit lectus non magna varius venenatis sed sit amet lectus. Nam leo nisl, imperdiet at lorem fringilla, lacinia bibendum lacus. Nunc auctor mauris at orci condimentum venenatis at non augue. Donec iaculis aliquam risus. Suspendisse vel massa leo.
|
||||
|
||||
Mauris sed est turpis. Nullam ut magna eu elit vehicula tempus. Sed mollis ultrices eleifend. Curabitur metus felis, sodales a turpis accumsan, ultricies feugiat arcu. Donec sit amet dui commodo, lacinia sem facilisis, lobortis urna. Donec cursus arcu ex, ac imperdiet lorem rutrum at. Curabitur faucibus erat in dolor placerat, vel blandit ligula eleifend. Morbi blandit nisl ut arcu semper consequat. Nulla malesuada convallis lectus a egestas. Sed volutpat metus vitae libero pulvinar, ut pretium magna malesuada.
|
||||
</div>
|
||||
);
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Dashboard;
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Home</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Home</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
function NoMatch() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Nothing to see here!</h2>
|
||||
<p>
|
||||
<Link to="/">Go to the home page 3</Link>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<h2>Nothing to see here!</h2>
|
||||
<p>
|
||||
<Link to="/">Go to the home page 3</Link>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default NoMatch;
|
||||
@@ -2,7 +2,7 @@
|
||||
import { isLibreOfficeInstalled } from "../../utils/libre-office-utils";
|
||||
|
||||
const hasLibreOffice = await isLibreOfficeInstalled();
|
||||
console.log(hasLibreOffice)
|
||||
console.log(hasLibreOffice);
|
||||
|
||||
function About() {
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import DynamicParameterFields from "../../components/DynamicParameterFields";
|
||||
import { ImposeParamConstraints } from "@stirling-pdf/shared-operations/src/functions/impose";
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
function Impose() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
export function appendToFilename(inputPath: string, toAppend: string) {
|
||||
const parts = inputPath.split('.');
|
||||
const parts = inputPath.split(".");
|
||||
if (parts.length > 1) {
|
||||
parts[parts.length-2] = parts[parts.length-2] + toAppend;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import { readBinaryFile, writeBinaryFile, removeDir, BaseDirectory } from '@tauri-apps/api/fs';
|
||||
import { PdfFile,RepresentationType } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile'
|
||||
import { runShell, isTauriAvailable } from './tauri-wrapper';
|
||||
import { readBinaryFile, writeBinaryFile, removeDir, BaseDirectory } from "@tauri-apps/api/fs";
|
||||
import { PdfFile,RepresentationType } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile";
|
||||
import { runShell, isTauriAvailable } from "./tauri-wrapper";
|
||||
|
||||
export async function fileToPdf(byteArray: Uint8Array, filename: string): Promise<PdfFile> {
|
||||
const randUuid = crypto.randomUUID();
|
||||
@@ -18,9 +18,9 @@ export async function fileToPdf(byteArray: Uint8Array, filename: string): Promis
|
||||
}
|
||||
console.debug(`${stream}, ${randUuid}: ${message}`);
|
||||
});
|
||||
const lastMessage = messageList[messageList.length-1]
|
||||
const lastMessage = messageList[messageList.length-1];
|
||||
const outputFilePath = lastMessage.split(" -> ")[1].split(".pdf")[0]+".pdf";
|
||||
const outputFilePathSplit = outputFilePath.toString().split("[\\/]")
|
||||
const outputFilePathSplit = outputFilePath.toString().split("[\\/]");
|
||||
const outputFileName = outputFilePathSplit[outputFilePathSplit.length-1];
|
||||
const outputBytes = await readBinaryFile(outputFilePath);
|
||||
|
||||
@@ -42,7 +42,7 @@ export async function isLibreOfficeInstalled() {
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
console.log("messageList", messageList)
|
||||
console.log("messageList", messageList);
|
||||
const result = messageList[0].match("LibreOffice ([0-9]+\.){4}.*");
|
||||
return result ? true : false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import SharedOperations, { OperationsType } from '@stirling-pdf/shared-operations/src'
|
||||
import { ImposeParamsType } from '@stirling-pdf/shared-operations/src/functions/impose'
|
||||
import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"
|
||||
import SharedOperations, { OperationsType } from "@stirling-pdf/shared-operations/src";
|
||||
import { ImposeParamsType } from "@stirling-pdf/shared-operations/src/functions/impose";
|
||||
import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile";
|
||||
|
||||
// Import injected libraries here!
|
||||
import * as pdfcpuWrapper from "@stirling-pdf/shared-operations/wasm/pdfcpu/pdfcpu-wrapper-browser.js";
|
||||
@@ -13,5 +13,5 @@ async function impose(params: ImposeParamsType): Promise<PdfFile> {
|
||||
const toExport: OperationsType = {
|
||||
...SharedOperations,
|
||||
impose,
|
||||
}
|
||||
};
|
||||
export default toExport;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
import { open, save } from '@tauri-apps/api/dialog';
|
||||
import { readBinaryFile, writeBinaryFile } from '@tauri-apps/api/fs';
|
||||
import { Command } from '@tauri-apps/api/shell'
|
||||
import { open, save } from "@tauri-apps/api/dialog";
|
||||
import { readBinaryFile, writeBinaryFile } from "@tauri-apps/api/fs";
|
||||
import { Command } from "@tauri-apps/api/shell";
|
||||
|
||||
export type TauriBrowserFile = {
|
||||
export interface TauriBrowserFile {
|
||||
name: string,
|
||||
relativePath?: string,
|
||||
data: Uint8Array,
|
||||
@@ -29,13 +29,13 @@ export function isTauriAvailable() {
|
||||
}
|
||||
|
||||
// [*] = Not available in browser
|
||||
type SelectFilesDialogOptions = {
|
||||
interface SelectFilesDialogOptions {
|
||||
defaultPath?: string, // [*] the default path to open the dialog on
|
||||
directory?: boolean, // should the dialog be a directory dialog
|
||||
filters?: Array<{ // list of file type filters
|
||||
filters?: { // list of file type filters
|
||||
name: string, // category name eg. 'Images'
|
||||
extensions: string[] // list of extensions eg ['png', 'jpeg', 'jpg']
|
||||
}>,
|
||||
}[],
|
||||
multiple?: boolean, // allow multiple selections
|
||||
recursive?: boolean, // [*] If directory is true, indicates that it will be read recursively later. Defines whether subdirectories will be allowed on the scope or not.
|
||||
title?: string // [*] the title of the dialog
|
||||
@@ -43,7 +43,7 @@ type SelectFilesDialogOptions = {
|
||||
export function openFiles(options: SelectFilesDialogOptions): Promise<TauriBrowserFile[] | null> {
|
||||
return new Promise(async (resolve) => {
|
||||
if (isTauriAvailable()) {
|
||||
var selected = await open(options);
|
||||
let selected = await open(options);
|
||||
if (!selected) {
|
||||
resolve(null);
|
||||
return;
|
||||
@@ -65,15 +65,15 @@ export function openFiles(options: SelectFilesDialogOptions): Promise<TauriBrows
|
||||
resolve(files);
|
||||
return;
|
||||
} else {
|
||||
var input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
const input = document.createElement("input");
|
||||
input.type = "file";
|
||||
if (options.directory) input.setAttribute("webkitdirectory", "");
|
||||
if (options.filters) input.setAttribute("accept", options.filters.flatMap(f => f.extensions).map(ext => "."+ext).join(", "));
|
||||
if (options.multiple) input.setAttribute("multiple", "");
|
||||
|
||||
input.onchange = async () => {
|
||||
if (input.files && input.files.length) {
|
||||
console.log("input.files", input.files)
|
||||
console.log("input.files", input.files);
|
||||
const files: TauriBrowserFile[] = [];
|
||||
for (const f of input.files) {
|
||||
const contents = new Uint8Array(await f.arrayBuffer());
|
||||
@@ -91,8 +91,8 @@ export function openFiles(options: SelectFilesDialogOptions): Promise<TauriBrows
|
||||
|
||||
// detect the user clicking cancel
|
||||
document.body.onfocus = () => {
|
||||
setTimeout(()=>resolve(null), 200); // the timeout is needed because 'document.body.onfocus' is called before 'input.onchange'
|
||||
}
|
||||
setTimeout(()=>{ resolve(null) }, 200); // the timeout is needed because 'document.body.onfocus' is called before 'input.onchange'
|
||||
};
|
||||
|
||||
input.click();
|
||||
}
|
||||
@@ -100,40 +100,40 @@ export function openFiles(options: SelectFilesDialogOptions): Promise<TauriBrows
|
||||
}
|
||||
|
||||
// [*] = Not available in browser
|
||||
type DownloadFilesDialogOptions = {
|
||||
interface DownloadFilesDialogOptions {
|
||||
defaultPath?: string, // the default path to open the dialog on
|
||||
filters?: Array<{ // [*] list of file type filters
|
||||
filters?: { // [*] list of file type filters
|
||||
name: string, // category name eg. 'Images'
|
||||
extensions: string[] // list of extensions eg ['png', 'jpeg', 'jpg']
|
||||
}>,
|
||||
}[],
|
||||
title?: string // [*] the title of the dialog
|
||||
}
|
||||
export async function downloadFile(fileData: Uint8Array, options: DownloadFilesDialogOptions): Promise<undefined> {
|
||||
if (isTauriAvailable()) {
|
||||
const pathToSave = await save(options);
|
||||
console.log("pathToSave", pathToSave)
|
||||
console.log("pathToSave", pathToSave);
|
||||
if (pathToSave) {
|
||||
await writeBinaryFile(pathToSave, fileData);
|
||||
}
|
||||
} else {
|
||||
const pdfBlob = new Blob([fileData], { type: 'application/pdf' });
|
||||
const pdfBlob = new Blob([fileData], { type: "application/pdf" });
|
||||
const url = URL.createObjectURL(pdfBlob);
|
||||
const downloadOption = localStorage.getItem('downloadOption');
|
||||
const downloadOption = localStorage.getItem("downloadOption");
|
||||
|
||||
// ensure filename is not a path
|
||||
const separator = options.defaultPath?.includes("\\") ? "\\" : "/";
|
||||
const filename = options.defaultPath?.split(separator).pop();
|
||||
const filenameToUse = filename ? filename : 'edited.pdf';
|
||||
const filenameToUse = filename ? filename : "edited.pdf";
|
||||
|
||||
if (downloadOption === 'sameWindow') {
|
||||
if (downloadOption === "sameWindow") {
|
||||
// Open the file in the same window
|
||||
window.location.href = url;
|
||||
} else if (downloadOption === 'newWindow') {
|
||||
} else if (downloadOption === "newWindow") {
|
||||
// Open the file in a new window
|
||||
window.open(url, '_blank');
|
||||
window.open(url, "_blank");
|
||||
} else {
|
||||
// Download the file
|
||||
const downloadLink = document.createElement('a');
|
||||
const downloadLink = document.createElement("a");
|
||||
downloadLink.href = url;
|
||||
downloadLink.download = filenameToUse;
|
||||
downloadLink.click();
|
||||
@@ -152,18 +152,18 @@ export function runShell(commandName: string, args: string[], callback: (message
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
||||
const comm = new Command(commandName, args);
|
||||
comm.on('close', data => {
|
||||
comm.on("close", data => {
|
||||
if (data.code === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Command failed with exit code ${data.code} and signal ${data.signal}`));
|
||||
}
|
||||
});
|
||||
comm.on('error', error => callback(error, "error"));
|
||||
comm.stdout.on('data', line => callback(line, "stdout"));
|
||||
comm.stderr.on('data', line => callback(line, "stderr"));
|
||||
comm.on("error", error => { callback(error, "error") });
|
||||
comm.stdout.on("data", line => { callback(line, "stdout") });
|
||||
comm.stderr.on("data", line => { callback(line, "stderr") });
|
||||
|
||||
const child = await comm.spawn();
|
||||
console.debug(`Started child process with pid: ${child.pid}`)
|
||||
console.debug(`Started child process with pid: ${child.pid}`);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user