Skip to content

Commit

Permalink
feat: svgo optimize icons
Browse files Browse the repository at this point in the history
  • Loading branch information
MrRobz committed Nov 14, 2021
1 parent a509aca commit fd7a22f
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 38 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
"@types/react": "^17.0.00",
"@types/react-dom": "^17.0.0",
"@types/react-router-dom": "^5.1.6",
"@types/svgo": "^2.6.0",
"@types/universal-analytics": "^0.4.5",
"@types/uuid": "^8.3.1",
"@types/webpack-env": "^1.15.2",
Expand Down Expand Up @@ -264,6 +265,7 @@
"react-router-dom": "^5.2.0",
"regenerator-runtime": "^0.13.5",
"source-map-support": "^0.5.19",
"svgo": "^2.8.0",
"universal-analytics": "^0.4.23",
"use-query-params": "^1.2.3",
"uuid": "^8.3.2"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { FC, useState, useEffect } from 'react';
import { Modal, Button } from 'components/ui/atomic-components';
import { Modal, Button, Checkbox } from 'components/ui/atomic-components';
import { ReactComponent as UploadIcon } from 'assets/icons/upload.svg';
import ImageUploading, { ImageListType } from 'react-images-uploading';
import { ReactComponent as DocumentIcon } from 'assets/icons/document.svg';
import { Collection, CollectionsApi } from 'data/collections';
import { useParams } from 'react-router-dom';
import { ipcRenderer } from 'electron';
import { useQueryClient } from 'react-query';
import { Icon } from 'data/icons';
import { addIconsToDb } from 'data/icons/utils';
import { CollectionsDropdown } from './CollectionsDropdown';

interface Props {
Expand All @@ -17,7 +14,9 @@ interface Props {
}

export const AddIconToCollectionModal: FC<Props> = ({ show, onClose }) => {
const queryClient = useQueryClient();
const [optimizeIcon, setOptimizeIcon] = useState<boolean>(
localStorage.getItem('optimizeIcon') === 'true'
);

const { collectionId }: { collectionId: string } = useParams();

Expand All @@ -42,32 +41,10 @@ export const AddIconToCollectionModal: FC<Props> = ({ show, onClose }) => {
fileName: icon.file?.name,
})),
folderPath: selectedCollection.folderSrc,
optimizeIcon,
});

// add icons to db
const icons = uploadedIcons
.filter((icon) => !!icon.file)
.map((icon) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const [name, type] = icon!.file!.name.split('.');

return {
name,
collectionId,
mime: type,
byteSize: icon.file?.size,
imageSrc: `${selectedCollection.folderSrc.replace(/\/$/, '')}/${icon.file?.name}`,
createdAt: Date.now(),
updatedAt: Date.now(),
} as Icon;
});

addIconsToDb(icons, collectionId)
.then(() => {
queryClient.invalidateQueries('icons-list');
onClose();
})
.catch(() => {});
onClose();
}
};

Expand Down Expand Up @@ -138,6 +115,29 @@ export const AddIconToCollectionModal: FC<Props> = ({ show, onClose }) => {
</div>
)}
</ImageUploading>

<div className="mt-4">
<Checkbox
checked={optimizeIcon}
label={
<>
SVGO optimize icon.{' '}
<a
className="text-blue-300 text-xs hover:text-blue-400"
href="https://github.com/svg/svgo"
target="_blank"
rel="noreferrer"
>
Learn more
</a>
</>
}
onChange={(val) => {
setOptimizeIcon(val);
localStorage.setItem('optimizeIcon', String(val));
}}
/>
</div>
</div>
</Modal>
);
Expand Down
10 changes: 6 additions & 4 deletions src/components/ui/atomic-components/checkbox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { FC, ChangeEvent } from 'react';
import { FC, ChangeEvent, ReactNode } from 'react';
import './styles.css';

export const Checkbox: FC<{
defaultChecked?: boolean;
label: string;
label: ReactNode;
checked?: boolean;
onChange: (val: boolean) => void;
}> = ({ label, defaultChecked, onChange }) => {
}> = ({ checked, label, defaultChecked, onChange }) => {
const checkBoxInputChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.checked;

Expand All @@ -17,7 +18,8 @@ export const Checkbox: FC<{
<input
type="checkbox"
name="checked-demo"
defaultChecked={!!defaultChecked}
defaultChecked={defaultChecked}
checked={checked}
className="form-tick appearance-none h-5 w-5 border border-gray-300 rounded-md focus:outline-none"
onChange={checkBoxInputChange}
/>
Expand Down
15 changes: 14 additions & 1 deletion src/main.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import log from 'electron-log';
import electronDl, { download } from 'electron-dl';
import { Icon } from 'data/icons';
import fs from 'fs';
import { optimize as svgOptimize } from 'svgo';

import chokidar, { FSWatcher } from 'chokidar';
import { svgoPluginsConfiguration } from './main/constants/svgoPluginsConfiguration';
import { activateAnalytics } from './main/utils/analytics';
import { getAllFiles } from './main/utils/getAllFiles';
import MenuBuilder from './menu';
Expand Down Expand Up @@ -202,9 +204,11 @@ ipcMain.on(
{
uploadedIcons,
folderPath,
optimizeIcon,
}: {
uploadedIcons: { dataURL: string; fileName: string }[];
folderPath: string;
optimizeIcon: boolean;
}
) => {
const regex = /^data:.+\/(.+);base64,(.*)$/;
Expand All @@ -222,9 +226,18 @@ ipcMain.on(
}

const buffer = Buffer.from(data, 'base64');

let fileData: Buffer | string = buffer;

if (optimizeIcon) {
fileData = svgOptimize(buffer, {
plugins: svgoPluginsConfiguration,
}).data;
}

const formattedPath = path.join(folderPath, filename);

fs.writeFile(formattedPath, buffer, () => {});
fs.writeFile(formattedPath, fileData, () => {});
}
});
}
Expand Down
144 changes: 144 additions & 0 deletions src/main/constants/svgoPluginsConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { Plugin } from 'svgo';

export const svgoPluginsConfiguration: Plugin[] = [
{
name: 'cleanupAttrs',
active: true,
},
{
name: 'cleanupEnableBackground',
active: true,
},
{
name: 'cleanupIDs',
active: true,
},
{
name: 'cleanupNumericValues',
active: true,
},
{
name: 'collapseGroups',
active: true,
},
{
name: 'convertColors',
active: true,
},
{
name: 'convertEllipseToCircle',
active: true,
},
{
name: 'convertPathData',
active: true,
},
{
name: 'convertShapeToPath',
active: false,
},
{
name: 'convertTransform',
active: true,
},
{
name: 'inlineStyles',
active: true,
},
{
name: 'mergePaths',
active: false,
},
{
name: 'mergeStyles',
active: true,
},
{
name: 'moveElemsAttrsToGroup',
active: true,
},
{
name: 'moveGroupAttrsToElems',
active: true,
},
{
name: 'removeComments',
active: true,
},
{
name: 'removeDesc',
active: true,
},
{
name: 'removeDoctype',
active: true,
},
{
name: 'removeEditorsNSData',
active: true,
},
{
name: 'removeEmptyAttrs',
active: true,
},
{
name: 'removeEmptyContainers',
active: true,
},
{
name: 'removeEmptyText',
active: true,
},
{
name: 'removeHiddenElems',
active: true,
},
{
name: 'removeMetadata',
active: true,
},
{
name: 'removeNonInheritableGroupAttrs',
active: true,
},
{
name: 'removeTitle',
active: true,
},
{
name: 'removeUnknownsAndDefaults',
active: true,
},
{
name: 'removeUnusedNS',
active: true,
},
{
name: 'removeUselessDefs',
active: true,
},
{
name: 'removeUselessStrokeAndFill',
active: true,
},
{
name: 'removeViewBox',
active: false,
},
{
name: 'removeXMLProcInst',
active: true,
},
{
name: 'sortDefsChildren',
active: true,
},
{
name: 'removeRasterImages',
active: false,
},
{
name: 'sortAttrs',
active: true,
},
];
Loading

0 comments on commit fd7a22f

Please sign in to comment.