feat: flameshot generator
This commit is contained in:
parent
4a753376b7
commit
0d65ee1a32
9 changed files with 183 additions and 80 deletions
|
@ -82,11 +82,12 @@ The default port is `3000`, once you have accessed it you can see a login screen
|
|||
# ShareX (Windows)
|
||||
This section requires [ShareX](https://www.getsharex.com/).
|
||||
|
||||
After navigating to Zipline, click on the top right corner where it says your username and click Manage Account. Scroll down to see "ShareX Config", select the one you would prefer using. After this you can import the .sxcu into sharex. [More information here](https://zipl.vercel.app/docs/uploaders/sharex)
|
||||
After navigating to Zipline, click on the top right corner where it says your username and click Manage Account. Scroll down to see "ShareX Config", select the one you would prefer using. After this you can import the .sxcu into sharex. [More information here](https://zipl.vercel.app/docs/guides/uploaders/sharex)
|
||||
|
||||
# Flameshot (Linux)
|
||||
This section requires [Flameshot](https://www.flameshot.org/), [jq](https://stedolan.github.io/jq/), and [xsel](https://github.com/kfish/xsel).
|
||||
|
||||
You can either use the script below, or generate one directly from Zipline (just like how you can generate a ShareX config).
|
||||
To upload files using flameshot we will use a script. Replace $TOKEN and $HOST with your own values, you probably know how to do this if you use linux.
|
||||
|
||||
```shell
|
||||
|
|
|
@ -23,6 +23,8 @@ module.exports = {
|
|||
domains: [
|
||||
// For sharex icon in manage user
|
||||
'getsharex.com',
|
||||
// For flameshot icon, and maybe in the future other stuff from github
|
||||
'raw.githubusercontent.com',
|
||||
],
|
||||
},
|
||||
poweredByHeader: false,
|
||||
|
|
7
src/components/icons/FlameshotIcon.tsx
Normal file
7
src/components/icons/FlameshotIcon.tsx
Normal file
|
@ -0,0 +1,7 @@
|
|||
// https://github.com/flameshot-org/flameshot/blob/master/data/img/app/flameshot.svg
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function FlameshotIcon({ ...props }) {
|
||||
return <Image src='https://raw.githubusercontent.com/flameshot-org/flameshot/master/data/img/app/flameshot.svg' width={24} height={24} {...props} />;
|
||||
}
|
|
@ -3,5 +3,5 @@
|
|||
import Image from 'next/image';
|
||||
|
||||
export default function ShareXIcon({ ...props }) {
|
||||
return <Image src='https://getsharex.com/img/ShareX_Logo.svg' width={15} height={15} {...props} />;
|
||||
return <Image src='https://getsharex.com/img/ShareX_Logo.svg' width={24} height={24} {...props} />;
|
||||
}
|
|
@ -25,6 +25,8 @@ import TagIcon from './TagIcon';
|
|||
import ClockIcon from './ClockIcon';
|
||||
import ExternalLinkIcon from './ExternalLinkIcon';
|
||||
import ShareXIcon from './ShareXIcon';
|
||||
import DownloadIcon from './DownloadIcon';
|
||||
import FlameshotIcon from './FlameshotIcon';
|
||||
|
||||
export {
|
||||
ActivityIcon,
|
||||
|
@ -54,4 +56,6 @@ export {
|
|||
ClockIcon,
|
||||
ExternalLinkIcon,
|
||||
ShareXIcon,
|
||||
DownloadIcon,
|
||||
FlameshotIcon,
|
||||
};
|
72
src/components/pages/Manage/Flameshot.tsx
Normal file
72
src/components/pages/Manage/Flameshot.tsx
Normal file
|
@ -0,0 +1,72 @@
|
|||
import { Button, Checkbox, Group, Modal, NumberInput, Select, Title } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { DownloadIcon } from 'components/icons';
|
||||
import { useState } from 'react';
|
||||
import { GeneratorModal } from './GeneratorModal';
|
||||
|
||||
export default function Flameshot({ user, open, setOpen }) {
|
||||
const onSubmit = values => {
|
||||
const curl = [
|
||||
'curl',
|
||||
'-H',
|
||||
'"Content-Type: multipart/form-data"',
|
||||
'-H',
|
||||
`"authorization: ${user?.token}"`,
|
||||
'-F',
|
||||
'file=@/tmp/ss.png',
|
||||
`${window.location.protocol + '//' + window.location.hostname + (window.location.port ? ':' + window.location.port : '')}/api/upload`,
|
||||
];
|
||||
|
||||
const extraHeaders = {};
|
||||
|
||||
if (values.format !== 'RANDOM') {
|
||||
extraHeaders['Format'] = values.format;
|
||||
} else {
|
||||
delete extraHeaders['Format'];
|
||||
}
|
||||
|
||||
if (values.imageCompression !== 0) {
|
||||
extraHeaders['Image-Compression-Percent'] = values.imageCompression;
|
||||
} else {
|
||||
delete extraHeaders['Image-Compression-Percent'];
|
||||
}
|
||||
|
||||
if (values.zeroWidthSpace) {
|
||||
extraHeaders['Zws'] = 'true';
|
||||
} else {
|
||||
delete extraHeaders['Zws'];
|
||||
}
|
||||
|
||||
if (values.embed) {
|
||||
extraHeaders['Embed'] = 'true';
|
||||
} else {
|
||||
delete extraHeaders['Embed'];
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(extraHeaders)) {
|
||||
curl.push('-H');
|
||||
curl.push(`"${key}: ${value}"`);
|
||||
}
|
||||
|
||||
const shell = `#!/bin/bash
|
||||
flameshot gui -r > /tmp/ss.png;
|
||||
${curl.join(' ')} | jq -r '.files[0]' | tr -d '\n' | xsel -ib;
|
||||
`;
|
||||
|
||||
const pseudoElement = document.createElement('a');
|
||||
pseudoElement.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(shell));
|
||||
pseudoElement.setAttribute('download', 'zipline.sh');
|
||||
pseudoElement.style.display = 'none';
|
||||
document.body.appendChild(pseudoElement);
|
||||
pseudoElement.click();
|
||||
pseudoElement.parentNode.removeChild(pseudoElement);
|
||||
};
|
||||
|
||||
return <GeneratorModal
|
||||
opened={open}
|
||||
onClose={() => setOpen(false)}
|
||||
title='Flameshot'
|
||||
desc='To use this script, you need Flameshot, curl, jq, and xsel installed. This script is intended for use on Linux only.'
|
||||
onSubmit={onSubmit}
|
||||
/>;
|
||||
}
|
77
src/components/pages/Manage/GeneratorModal.tsx
Normal file
77
src/components/pages/Manage/GeneratorModal.tsx
Normal file
|
@ -0,0 +1,77 @@
|
|||
import { Modal, Select, NumberInput, Group, Checkbox, Button, Title, Text } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { DownloadIcon } from 'components/icons';
|
||||
|
||||
export function GeneratorModal({ opened, onClose, title, onSubmit, ...other }) {
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
format: 'RANDOM',
|
||||
imageCompression: 0,
|
||||
zeroWidthSpace: false,
|
||||
embed: false,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
opened={opened}
|
||||
onClose={onClose}
|
||||
title={<Title order={3}>{title}</Title>}
|
||||
size='lg'
|
||||
>
|
||||
{other.desc && <Text>{other.desc}</Text>}
|
||||
<form onSubmit={form.onSubmit(values => onSubmit(values))}>
|
||||
<Select
|
||||
label='Select file name format'
|
||||
data={[
|
||||
{ value: 'RANDOM', label: 'Random (alphanumeric)' },
|
||||
{ value: 'DATE', label: 'Date' },
|
||||
{ value: 'UUID', label: 'UUID' },
|
||||
{ value: 'NAME', label: 'Name (keeps original file name)' },
|
||||
]}
|
||||
id='format'
|
||||
{...form.getInputProps('format')}
|
||||
/>
|
||||
|
||||
<NumberInput
|
||||
label={'Image Compression (leave at 0 if you don\'t want to compress)'}
|
||||
max={100}
|
||||
min={0}
|
||||
mt='md'
|
||||
id='imageCompression'
|
||||
{...form.getInputProps('imageCompression')}
|
||||
/>
|
||||
|
||||
<Group grow mt='md'>
|
||||
<Checkbox
|
||||
label='Zero Width Space'
|
||||
id='zeroWidthSpace'
|
||||
{...form.getInputProps('zeroWidthSpace', { type: 'checkbox' })}
|
||||
/>
|
||||
<Checkbox
|
||||
label='Embed'
|
||||
id='embed'
|
||||
{...form.getInputProps('embed', { type: 'checkbox' })}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group grow>
|
||||
<Button
|
||||
mt='md'
|
||||
onClick={form.reset}
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
mt='md'
|
||||
rightIcon={<DownloadIcon />}
|
||||
type='submit'
|
||||
>
|
||||
Download
|
||||
</Button>
|
||||
</Group>
|
||||
</form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
import { Button, Checkbox, Group, Modal, NumberInput, Select, Title } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import DownloadIcon from 'components/icons/DownloadIcon';
|
||||
import { DownloadIcon } from 'components/icons';
|
||||
import { useState } from 'react';
|
||||
import { GeneratorModal } from './GeneratorModal';
|
||||
|
||||
export default function ShareX({ user, open, setOpen }) {
|
||||
const [config, setConfig] = useState({
|
||||
|
@ -18,16 +19,7 @@ export default function ShareX({ user, open, setOpen }) {
|
|||
FileFormName: 'file',
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
format: 'RANDOM',
|
||||
imageCompression: 0,
|
||||
zeroWidthSpace: false,
|
||||
embed: false,
|
||||
},
|
||||
});
|
||||
|
||||
const download = values => {
|
||||
const onSubmit = values => {
|
||||
if (values.format !== 'RANDOM') {
|
||||
config.Headers['Format'] = values.format;
|
||||
setConfig(config);
|
||||
|
@ -69,66 +61,10 @@ export default function ShareX({ user, open, setOpen }) {
|
|||
pseudoElement.parentNode.removeChild(pseudoElement);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
opened={open}
|
||||
onClose={() => setOpen(false)}
|
||||
title={<Title order={3}>ShareX</Title>}
|
||||
size='lg'
|
||||
>
|
||||
|
||||
<form onSubmit={form.onSubmit(values => download(values))}>
|
||||
<Select
|
||||
label='Select file name format'
|
||||
data={[
|
||||
{ value: 'RANDOM', label: 'Random (alphanumeric)' },
|
||||
{ value: 'DATE', label: 'Date' },
|
||||
{ value: 'UUID', label: 'UUID' },
|
||||
{ value: 'NAME', label: 'Name (keeps original file name)' },
|
||||
]}
|
||||
id='format'
|
||||
{...form.getInputProps('format')}
|
||||
/>
|
||||
|
||||
<NumberInput
|
||||
label={'Image Compression (leave at 0 if you don\'t want to compress)'}
|
||||
max={100}
|
||||
min={0}
|
||||
mt='md'
|
||||
id='imageCompression'
|
||||
{...form.getInputProps('imageCompression')}
|
||||
/>
|
||||
|
||||
<Group grow mt='md'>
|
||||
<Checkbox
|
||||
label='Zero Width Space'
|
||||
id='zeroWidthSpace'
|
||||
{...form.getInputProps('zeroWidthSpace', { type: 'checkbox' })}
|
||||
/>
|
||||
<Checkbox
|
||||
label='Embed'
|
||||
id='embed'
|
||||
{...form.getInputProps('embed', { type: 'checkbox' })}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group grow>
|
||||
<Button
|
||||
mt='md'
|
||||
onClick={form.reset}
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
mt='md'
|
||||
rightIcon={<DownloadIcon />}
|
||||
type='submit'
|
||||
>
|
||||
Download
|
||||
</Button>
|
||||
</Group>
|
||||
</form>
|
||||
</Modal>
|
||||
);
|
||||
return <GeneratorModal
|
||||
opened={open}
|
||||
onClose={() => setOpen(false)}
|
||||
title='ShareX'
|
||||
onSubmit={onSubmit}
|
||||
/>;
|
||||
}
|
|
@ -3,7 +3,7 @@ import { useForm } from '@mantine/form';
|
|||
import { randomId, useInterval } from '@mantine/hooks';
|
||||
import { useModals } from '@mantine/modals';
|
||||
import { showNotification, updateNotification } from '@mantine/notifications';
|
||||
import { CrossIcon, DeleteIcon, SettingsIcon, ShareXIcon } from 'components/icons';
|
||||
import { CrossIcon, DeleteIcon, FlameshotIcon, SettingsIcon, ShareXIcon } from 'components/icons';
|
||||
import DownloadIcon from 'components/icons/DownloadIcon';
|
||||
import Link from 'components/Link';
|
||||
import MutedText from 'components/MutedText';
|
||||
|
@ -13,6 +13,7 @@ import { bytesToRead } from 'lib/clientUtils';
|
|||
import { updateUser } from 'lib/redux/reducers/user';
|
||||
import { useStoreDispatch, useStoreSelector } from 'lib/redux/store';
|
||||
import { useEffect, useState } from 'react';
|
||||
import Flameshot from './Flameshot';
|
||||
import ShareX from './ShareX';
|
||||
|
||||
function ExportDataTooltip({ children }) {
|
||||
|
@ -24,7 +25,8 @@ export default function Manage() {
|
|||
const dispatch = useStoreDispatch();
|
||||
const modals = useModals();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [shareXOpen, setShareXOpen] = useState(false);
|
||||
const [flameshotOpen, setFlameshotOpen] = useState(false);
|
||||
const [exports, setExports] = useState([]);
|
||||
const [file, setFile] = useState<File>(null);
|
||||
const [fileDataURL, setFileDataURL] = useState(user.avatar ?? null);
|
||||
|
@ -297,12 +299,14 @@ export default function Manage() {
|
|||
)}
|
||||
</Card>
|
||||
|
||||
<Title my='md'>ShareX Config</Title>
|
||||
<Title my='md'>Uploaders</Title>
|
||||
<Group>
|
||||
<Button onClick={() => setOpen(true)} rightIcon={<ShareXIcon />}>Generate ShareX Config</Button>
|
||||
<Button size='xl' onClick={() => setShareXOpen(true)} rightIcon={<ShareXIcon />}>Generate ShareX Config</Button>
|
||||
<Button size='xl' onClick={() => setFlameshotOpen(true)} rightIcon={<FlameshotIcon />}>Generate Flameshot Script</Button>
|
||||
</Group>
|
||||
|
||||
<ShareX user={user} open={open} setOpen={setOpen} />
|
||||
<ShareX user={user} open={shareXOpen} setOpen={setShareXOpen} />
|
||||
<Flameshot user={user} open={flameshotOpen} setOpen={setFlameshotOpen} />
|
||||
</>
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue