mirror of
https://github.com/responsively-org/responsively-app
synced 2024-11-10 23:04:20 +00:00
feat(desktop-app): add viewport screenshot option
This commit is contained in:
parent
8e70d87497
commit
797c951d3c
6 changed files with 273 additions and 143 deletions
|
@ -5,7 +5,7 @@ import Grid from '@material-ui/core/Grid';
|
||||||
import Tooltip from '@material-ui/core/Tooltip';
|
import Tooltip from '@material-ui/core/Tooltip';
|
||||||
import ScrollDownIcon from '../icons/ScrollDown';
|
import ScrollDownIcon from '../icons/ScrollDown';
|
||||||
import ScrollUpIcon from '../icons/ScrollUp';
|
import ScrollUpIcon from '../icons/ScrollUp';
|
||||||
import ScreenshotIcon from '../icons/Screenshot';
|
import ScreenshotIcon from '../icons/FullScreenshot';
|
||||||
import DeviceRotateIcon from '../icons/DeviceRotate';
|
import DeviceRotateIcon from '../icons/DeviceRotate';
|
||||||
import InspectElementIcon from '../icons/InspectElement';
|
import InspectElementIcon from '../icons/InspectElement';
|
||||||
import MutedIcon from '../icons/Muted';
|
import MutedIcon from '../icons/Muted';
|
||||||
|
@ -68,9 +68,19 @@ const ScrollControls = ({
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item className={cx(commonStyles.icons, commonStyles.enabled)}>
|
<Grid item className={cx(commonStyles.icons, commonStyles.enabled)}>
|
||||||
<Tooltip title={browser.allDevicesMuted? "Unmute all devices": "Mute all devices"}>
|
<Tooltip
|
||||||
|
title={
|
||||||
|
browser.allDevicesMuted
|
||||||
|
? 'Unmute all devices'
|
||||||
|
: 'Mute all devices'
|
||||||
|
}
|
||||||
|
>
|
||||||
<div onClick={onAllDevicesMutedChange}>
|
<div onClick={onAllDevicesMutedChange}>
|
||||||
{ browser.allDevicesMuted ? (<MutedIcon {...iconProps} />):(<UnmutedIcon {...iconProps} />) }
|
{browser.allDevicesMuted ? (
|
||||||
|
<MutedIcon {...iconProps} />
|
||||||
|
) : (
|
||||||
|
<UnmutedIcon {...iconProps} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import console from 'electron-timber';
|
||||||
import BugIcon from '../icons/Bug';
|
import BugIcon from '../icons/Bug';
|
||||||
import MutedIcon from '../icons/Muted';
|
import MutedIcon from '../icons/Muted';
|
||||||
import UnmutedIcon from '../icons/Unmuted';
|
import UnmutedIcon from '../icons/Unmuted';
|
||||||
|
import FullScreenshotIcon from '../icons/FullScreenshot';
|
||||||
import ScreenshotIcon from '../icons/Screenshot';
|
import ScreenshotIcon from '../icons/Screenshot';
|
||||||
import DeviceRotateIcon from '../icons/DeviceRotate';
|
import DeviceRotateIcon from '../icons/DeviceRotate';
|
||||||
import {iconsColor} from '../../constants/colors';
|
import {iconsColor} from '../../constants/colors';
|
||||||
|
@ -34,7 +35,7 @@ import {CAPABILITIES} from '../../constants/devices';
|
||||||
import styles from './style.module.css';
|
import styles from './style.module.css';
|
||||||
import commonStyles from '../common.styles.css';
|
import commonStyles from '../common.styles.css';
|
||||||
import UnplugIcon from '../icons/Unplug';
|
import UnplugIcon from '../icons/Unplug';
|
||||||
import {captureFullPage} from './screenshotUtil';
|
import {captureScreenshot} from './screenshotUtil';
|
||||||
import {
|
import {
|
||||||
DEVTOOLS_MODES,
|
DEVTOOLS_MODES,
|
||||||
INDIVIDUAL_LAYOUT,
|
INDIVIDUAL_LAYOUT,
|
||||||
|
@ -352,15 +353,22 @@ class WebView extends Component {
|
||||||
this.webviewRef.current.send('scrollUpMessage');
|
this.webviewRef.current.send('scrollUpMessage');
|
||||||
};
|
};
|
||||||
|
|
||||||
processScreenshotEvent = async ({now}) => {
|
processScreenshotEvent = async ({
|
||||||
|
now,
|
||||||
|
fullScreen = true,
|
||||||
|
}: {
|
||||||
|
now?: Date,
|
||||||
|
fullScreen?: boolean,
|
||||||
|
}) => {
|
||||||
this.setState({screenshotInProgress: true});
|
this.setState({screenshotInProgress: true});
|
||||||
await captureFullPage(
|
await captureScreenshot({
|
||||||
this.props.browser.address,
|
address: this.props.browser.address,
|
||||||
this.props.device,
|
device: this.props.device,
|
||||||
this.webviewRef.current,
|
webView: this.webviewRef.current,
|
||||||
now != null,
|
createSeparateDir: now != null,
|
||||||
now
|
fullScreen,
|
||||||
);
|
now,
|
||||||
|
});
|
||||||
this.setState({screenshotInProgress: false});
|
this.setState({screenshotInProgress: false});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -779,11 +787,23 @@ class WebView extends Component {
|
||||||
commonStyles.icons,
|
commonStyles.icons,
|
||||||
commonStyles.enabled
|
commonStyles.enabled
|
||||||
)}
|
)}
|
||||||
onClick={() => this.processScreenshotEvent({})}
|
onClick={() => this.processScreenshotEvent({fullScreen: false})}
|
||||||
>
|
>
|
||||||
<ScreenshotIcon height={18} color={iconsColor} />
|
<ScreenshotIcon height={18} color={iconsColor} />
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
<Tooltip title="Take Full Size Screenshot">
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
styles.webViewToolbarIcons,
|
||||||
|
commonStyles.icons,
|
||||||
|
commonStyles.enabled
|
||||||
|
)}
|
||||||
|
onClick={this.processScreenshotEvent}
|
||||||
|
>
|
||||||
|
<FullScreenshotIcon height={18} color={iconsColor} />
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
<Tooltip title="Tilt Device">
|
<Tooltip title="Tilt Device">
|
||||||
<div
|
<div
|
||||||
className={cx(styles.webViewToolbarIcons, commonStyles.icons, {
|
className={cx(styles.webViewToolbarIcons, commonStyles.icons, {
|
||||||
|
|
|
@ -11,16 +11,25 @@ import fs from 'fs-extra';
|
||||||
import PromiseWorker from 'promise-worker';
|
import PromiseWorker from 'promise-worker';
|
||||||
import NotificationMessage from '../NotificationMessage';
|
import NotificationMessage from '../NotificationMessage';
|
||||||
import {userPreferenceSettings} from '../../settings/userPreferenceSettings';
|
import {userPreferenceSettings} from '../../settings/userPreferenceSettings';
|
||||||
|
import {type Device} from '../../constants/devices';
|
||||||
|
|
||||||
const mergeImg = Promise.promisifyAll(_mergeImg);
|
const mergeImg = Promise.promisifyAll(_mergeImg);
|
||||||
|
|
||||||
export const captureFullPage = async (
|
const captureScreenshot = async ({
|
||||||
address,
|
address,
|
||||||
device,
|
device,
|
||||||
webView,
|
webView,
|
||||||
createSeparateDir,
|
createSeparateDir,
|
||||||
now
|
now,
|
||||||
) => {
|
fullScreen = false,
|
||||||
|
}: {
|
||||||
|
address: string,
|
||||||
|
device: Device,
|
||||||
|
webView: WebviewElement,
|
||||||
|
createSeparateDir: boolean,
|
||||||
|
now?: Date,
|
||||||
|
fullScreen: boolean,
|
||||||
|
}) => {
|
||||||
const worker = new Worker('./imageWorker.js');
|
const worker = new Worker('./imageWorker.js');
|
||||||
const promiseWorker = new PromiseWorker(worker);
|
const promiseWorker = new PromiseWorker(worker);
|
||||||
const toastId = toast.info(
|
const toastId = toast.info(
|
||||||
|
@ -30,96 +39,14 @@ export const captureFullPage = async (
|
||||||
/>,
|
/>,
|
||||||
{autoClose: false}
|
{autoClose: false}
|
||||||
);
|
);
|
||||||
// Hiding scrollbars in the screenshot
|
const webViewUtils = new WebViewUtils(webView);
|
||||||
await webView.insertCSS(`
|
const insertedCSSKey = await webViewUtils.hideScrollbarAndFixedPositionedElements();
|
||||||
.responsivelyApp__ScreenshotInProgress::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.responsivelyApp__HiddenForScreenshot {
|
const images = fullScreen
|
||||||
display: none !important;
|
? await webViewUtils.getFullScreenImages(promiseWorker)
|
||||||
}
|
: [await webViewUtils.getViewportImage(promiseWorker)];
|
||||||
`);
|
|
||||||
|
|
||||||
// Get the windows's scroll details
|
await webViewUtils.unHideScrollbarAndFixedPositionedElements(insertedCSSKey);
|
||||||
let scrollX = 0;
|
|
||||||
let scrollY = 0;
|
|
||||||
const pageX = 0;
|
|
||||||
const pageY = 0;
|
|
||||||
const {
|
|
||||||
previousScrollPosition,
|
|
||||||
scrollHeight,
|
|
||||||
viewPortHeight,
|
|
||||||
scrollWidth,
|
|
||||||
viewPortWidth,
|
|
||||||
} = await webView.executeJavaScript(`
|
|
||||||
document.body.classList.add('responsivelyApp__ScreenshotInProgress');
|
|
||||||
responsivelyApp.screenshotVar = {
|
|
||||||
previousScrollPosition : {
|
|
||||||
left: window.scrollX,
|
|
||||||
top: window.scrollY,
|
|
||||||
},
|
|
||||||
scrollHeight: document.body.scrollHeight,
|
|
||||||
scrollWidth: document.body.scrollWidth,
|
|
||||||
viewPortHeight: document.documentElement.clientHeight,
|
|
||||||
viewPortWidth: document.documentElement.clientWidth,
|
|
||||||
};
|
|
||||||
responsivelyApp.screenshotVar;
|
|
||||||
`);
|
|
||||||
|
|
||||||
const images = [];
|
|
||||||
|
|
||||||
for (
|
|
||||||
let pageY = 0;
|
|
||||||
scrollY < scrollHeight;
|
|
||||||
pageY++, scrollY = viewPortHeight * pageY
|
|
||||||
) {
|
|
||||||
scrollX = 0;
|
|
||||||
const columnImages = [];
|
|
||||||
for (
|
|
||||||
let pageX = 0;
|
|
||||||
scrollX < scrollWidth;
|
|
||||||
pageX++, scrollX = viewPortWidth * pageX
|
|
||||||
) {
|
|
||||||
await webView.executeJavaScript(`
|
|
||||||
window.scrollTo(${scrollX}, ${scrollY})
|
|
||||||
responsivelyApp.hideFixedPositionElementsForScreenshot();
|
|
||||||
`);
|
|
||||||
await _delay(200);
|
|
||||||
const options = {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: viewPortWidth,
|
|
||||||
height: viewPortHeight,
|
|
||||||
};
|
|
||||||
if (scrollX + viewPortWidth > scrollWidth) {
|
|
||||||
options.width = scrollWidth - scrollX;
|
|
||||||
options.x = viewPortWidth - options.width;
|
|
||||||
}
|
|
||||||
if (scrollY + viewPortHeight > scrollHeight) {
|
|
||||||
options.height = scrollHeight - scrollY;
|
|
||||||
options.y = viewPortHeight - options.height;
|
|
||||||
}
|
|
||||||
const image = await _takeSnapshot(webView, options);
|
|
||||||
columnImages.push(image);
|
|
||||||
}
|
|
||||||
const pngs = columnImages.map(img => img.toPNG());
|
|
||||||
images.push(
|
|
||||||
await promiseWorker.postMessage(
|
|
||||||
{
|
|
||||||
images: pngs,
|
|
||||||
direction: 'horizontal',
|
|
||||||
},
|
|
||||||
[...pngs]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
webView.executeJavaScript(`
|
|
||||||
window.scrollTo(${JSON.stringify(previousScrollPosition)});
|
|
||||||
document.body.classList.remove('responsivelyApp__ScreenshotInProgress');
|
|
||||||
responsivelyApp.unHideElementsHiddenForScreenshot();
|
|
||||||
`);
|
|
||||||
|
|
||||||
toast.update(toastId, {
|
toast.update(toastId, {
|
||||||
render: (
|
render: (
|
||||||
|
@ -130,17 +57,20 @@ export const captureFullPage = async (
|
||||||
),
|
),
|
||||||
type: toast.TYPE.INFO,
|
type: toast.TYPE.INFO,
|
||||||
});
|
});
|
||||||
|
|
||||||
const resultFilename = _getScreenshotFileName(
|
const resultFilename = _getScreenshotFileName(
|
||||||
address,
|
address,
|
||||||
device,
|
device,
|
||||||
now,
|
now,
|
||||||
createSeparateDir
|
createSeparateDir
|
||||||
);
|
);
|
||||||
|
|
||||||
const mergedImage = await promiseWorker.postMessage({
|
const mergedImage = await promiseWorker.postMessage({
|
||||||
images,
|
images,
|
||||||
direction: 'vertical',
|
direction: 'vertical',
|
||||||
resultFilename,
|
resultFilename,
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.update(toastId, {
|
toast.update(toastId, {
|
||||||
render: (
|
render: (
|
||||||
<NotificationMessage tick message={`${device.name} screenshot taken!`} />
|
<NotificationMessage tick message={`${device.name} screenshot taken!`} />
|
||||||
|
@ -148,18 +78,157 @@ export const captureFullPage = async (
|
||||||
type: toast.TYPE.INFO,
|
type: toast.TYPE.INFO,
|
||||||
autoClose: 2000,
|
autoClose: 2000,
|
||||||
});
|
});
|
||||||
|
|
||||||
await _delay(250);
|
await _delay(250);
|
||||||
shell.showItemInFolder(path.join(resultFilename.dir, resultFilename.file));
|
shell.showItemInFolder(path.join(resultFilename.dir, resultFilename.file));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WebViewUtils {
|
||||||
|
webView: WebviewElement;
|
||||||
|
|
||||||
|
constructor(webView) {
|
||||||
|
this.webView = webView;
|
||||||
|
}
|
||||||
|
|
||||||
|
getWindowSizeAndScrollDetails(): Promise {
|
||||||
|
return this.webView.executeJavaScript(`
|
||||||
|
responsivelyApp.screenshotVar = {
|
||||||
|
previousScrollPosition : {
|
||||||
|
left: window.scrollX,
|
||||||
|
top: window.scrollY,
|
||||||
|
},
|
||||||
|
scrollHeight: document.body.scrollHeight,
|
||||||
|
scrollWidth: document.body.scrollWidth,
|
||||||
|
viewPortHeight: document.documentElement.clientHeight,
|
||||||
|
viewPortWidth: document.documentElement.clientWidth,
|
||||||
|
};
|
||||||
|
responsivelyApp.screenshotVar;
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async scrollTo(scrollX: number, scrollY: number): Promise {
|
||||||
|
await this.webView.executeJavaScript(`
|
||||||
|
window.scrollTo(${scrollX}, ${scrollY})
|
||||||
|
`);
|
||||||
|
// wait a little for the scroll to take effect.
|
||||||
|
await _delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
async hideScrollbarAndFixedPositionedElements(): Promise<string> {
|
||||||
|
const key = await this.webView.insertCSS(`
|
||||||
|
.responsivelyApp__ScreenshotInProgress::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsivelyApp__HiddenForScreenshot {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
await this.webView.executeJavaScript(`
|
||||||
|
document.body.classList.add('responsivelyApp__ScreenshotInProgress');
|
||||||
|
responsivelyApp.hideFixedPositionElementsForScreenshot();
|
||||||
|
`);
|
||||||
|
|
||||||
|
// wait a little for the 'hide' effect to take place.
|
||||||
|
await _delay(200);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
async unHideScrollbarAndFixedPositionedElements(insertedCSSKey): Promise {
|
||||||
|
await this.webView.removeInsertedCSS(insertedCSSKey);
|
||||||
|
return this.webView.executeJavaScript(`
|
||||||
|
document.body.classList.remove('responsivelyApp__ScreenshotInProgress');
|
||||||
|
responsivelyApp.unHideElementsHiddenForScreenshot();
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFullScreenImages(promiseWorker: PromiseWorker): Promise {
|
||||||
|
const {
|
||||||
|
previousScrollPosition,
|
||||||
|
scrollHeight,
|
||||||
|
viewPortHeight,
|
||||||
|
scrollWidth,
|
||||||
|
viewPortWidth,
|
||||||
|
} = await this.getWindowSizeAndScrollDetails();
|
||||||
|
|
||||||
|
const images = [];
|
||||||
|
let scrollX = 0;
|
||||||
|
let scrollY = 0;
|
||||||
|
for (
|
||||||
|
let pageY = 0;
|
||||||
|
scrollY < scrollHeight;
|
||||||
|
pageY++, scrollY = viewPortHeight * pageY
|
||||||
|
) {
|
||||||
|
scrollX = 0;
|
||||||
|
const columnImages = [];
|
||||||
|
for (
|
||||||
|
let pageX = 0;
|
||||||
|
scrollX < scrollWidth;
|
||||||
|
pageX++, scrollX = viewPortWidth * pageX
|
||||||
|
) {
|
||||||
|
await this.scrollTo(scrollX, scrollY);
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: viewPortWidth,
|
||||||
|
height: viewPortHeight,
|
||||||
|
};
|
||||||
|
if (scrollX + viewPortWidth > scrollWidth) {
|
||||||
|
options.width = scrollWidth - scrollX;
|
||||||
|
options.x = viewPortWidth - options.width;
|
||||||
|
}
|
||||||
|
if (scrollY + viewPortHeight > scrollHeight) {
|
||||||
|
options.height = scrollHeight - scrollY;
|
||||||
|
options.y = viewPortHeight - options.height;
|
||||||
|
}
|
||||||
|
const image = await this.takeSnapshot(options);
|
||||||
|
columnImages.push(image);
|
||||||
|
}
|
||||||
|
const pngs = columnImages.map(img => img.toPNG());
|
||||||
|
images.push(
|
||||||
|
await promiseWorker.postMessage(
|
||||||
|
{
|
||||||
|
images: pngs,
|
||||||
|
direction: 'horizontal',
|
||||||
|
},
|
||||||
|
[...pngs]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollTo(previousScrollPosition.left, previousScrollPosition.top);
|
||||||
|
|
||||||
|
return images;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getViewportImage(promiseWorker: PromiseWorker): Promise {
|
||||||
|
const image = await this.takeSnapshot();
|
||||||
|
const png = image.toPNG();
|
||||||
|
|
||||||
|
return promiseWorker.postMessage(
|
||||||
|
{
|
||||||
|
images: [png],
|
||||||
|
direction: 'horizontal',
|
||||||
|
},
|
||||||
|
[png]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
takeSnapshot(options): Promise {
|
||||||
|
return remote.webContents
|
||||||
|
.fromId(this.webView.getWebContentsId())
|
||||||
|
.capturePage(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const _delay = ms =>
|
const _delay = ms =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
setTimeout(() => resolve(), ms);
|
setTimeout(() => resolve(), ms);
|
||||||
});
|
});
|
||||||
|
|
||||||
const _takeSnapshot = (webView, options) =>
|
|
||||||
remote.webContents.fromId(webView.getWebContentsId()).capturePage(options);
|
|
||||||
|
|
||||||
function _getScreenshotFileName(
|
function _getScreenshotFileName(
|
||||||
address,
|
address,
|
||||||
device,
|
device,
|
||||||
|
@ -189,7 +258,7 @@ function _getScreenshotFileName(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getWebsiteName = address => {
|
const getWebsiteName = (address: string) => {
|
||||||
let domain = '';
|
let domain = '';
|
||||||
if (address.startsWith('file://')) {
|
if (address.startsWith('file://')) {
|
||||||
const fileNameStartingIndex = address.lastIndexOf('/') + 1;
|
const fileNameStartingIndex = address.lastIndexOf('/') + 1;
|
||||||
|
@ -208,3 +277,5 @@ export const getWebsiteName = address => {
|
||||||
}
|
}
|
||||||
return domain.charAt(0).toUpperCase() + domain.slice(1);
|
return domain.charAt(0).toUpperCase() + domain.slice(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export {getWebsiteName, captureScreenshot};
|
||||||
|
|
41
desktop-app/app/components/icons/FullScreenshot.js
Normal file
41
desktop-app/app/components/icons/FullScreenshot.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import React, {Fragment} from 'react';
|
||||||
|
|
||||||
|
export default ({width, height, color, padding, margin}) => (
|
||||||
|
<Fragment>
|
||||||
|
{/* <svg
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
fill={color}
|
||||||
|
style={{padding, margin}}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path d="M20,10.5a1,1,0,0,0-1,1v7a1,1,0,0,1-1,1H4a1,1,0,0,1-1-1v-8a1,1,0,0,1,1-1H6a1,1,0,0,0,1-.68l.54-1.64a1,1,0,0,1,.95-.68H14a1,1,0,0,0,0-2H8.44A3,3,0,0,0,5.6,6.55l-.32,1H4a3,3,0,0,0-3,3v8a3,3,0,0,0,3,3H18a3,3,0,0,0,3-3v-7A1,1,0,0,0,20,10.5Zm-9-1a4,4,0,1,0,4,4A4,4,0,0,0,11,9.5Zm0,6a2,2,0,1,1,2-2A2,2,0,0,1,11,15.5Zm11-11H21v-1a1,1,0,0,0-2,0v1H18a1,1,0,0,0,0,2h1v1a1,1,0,0,0,2,0v-1h1a1,1,0,0,0,0-2Z" />
|
||||||
|
</svg> */}
|
||||||
|
<svg
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
fill={color}
|
||||||
|
style={{padding, margin}}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
version="1.1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
className="screenshotIcon"
|
||||||
|
>
|
||||||
|
<g transform="translate(0,-952.36218)">
|
||||||
|
<path
|
||||||
|
d="m 83,958.36218 c -1.1046,0 -2,0.89543 -2,2 l 0,7 -7,0 c -1.10457,0 -2,0.8954 -2,2 0,1.1046 0.89543,2 2,2 l 7,0 0,7 c 0,1.10457 0.8954,2 2,2 1.1046,0 2,-0.89543 2,-2 l 0,-7 7,0 c 1.10457,0 2,-0.8954 2,-2 0,-1.1046 -0.89543,-2 -2,-2 l -7,0 0,-7 c 0,-1.10457 -0.8954,-2 -2,-2 z m -48,22 c -0.78068,0.007 -1.3909,0.40265 -1.71875,0.96875 l -6.4375,11.03125 -12.84375,0 c -4.3973999,0 -8,3.6026 -8,8.00002 l 0,38 c 0,4.3974 3.6026001,8 8,8 l 62,0 c 4.3974,0 8,-3.6026 8,-8 l 0,-38 c 0,-4.39742 -3.6026,-8.00002 -8,-8.00002 l -12.84375,0 -6.4375,-11.03125 C 56.3641,980.74168 55.68774,980.36046 55,980.36218 l -20,0 z m 1.125,4 17.75,0 6.40625,11 c 0.34687,0.60075 1.02507,0.99534 1.71875,1 l 14,0 c 2.25056,0 4,1.74944 4,4.00002 l 0,38 c 0,2.2505 -1.74944,4 -4,4 l -62,0 c -2.25056,0 -4,-1.7495 -4,-4 l 0,-38 c 0,-2.25058 1.74944,-4.00002 4,-4.00002 l 14,0 c 0.69368,-0.005 1.37188,-0.39925 1.71875,-1 l 6.40625,-11 z M 45,1002.3622 c -8.81287,0 -16,7.1871 -16,16 0,8.8128 7.18713,16 16,16 8.81286,0 16,-7.1872 16,-16 0,-8.8129 -7.18714,-16 -16,-16 z m 0,4 c 6.6511,0 12,5.3489 12,12 0,6.6511 -5.3489,12 -12,12 -6.65111,0 -12,-5.3489 -12,-12 0,-6.6511 5.34889,-12 12,-12 z"
|
||||||
|
fill={color}
|
||||||
|
fillOpacity="1"
|
||||||
|
stroke="none"
|
||||||
|
marker="none"
|
||||||
|
visibility="visible"
|
||||||
|
display="inline"
|
||||||
|
overflow="visible"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</Fragment>
|
||||||
|
);
|
|
@ -1,41 +1,23 @@
|
||||||
import React, {Fragment} from 'react';
|
import React, {Fragment} from 'react';
|
||||||
|
|
||||||
export default ({width, height, color, padding, margin}) => (
|
export default ({width, height, color, padding, margin}) => (
|
||||||
<Fragment>
|
<svg
|
||||||
{/* <svg
|
width={width}
|
||||||
width={width}
|
height={height}
|
||||||
height={height}
|
fill={color}
|
||||||
|
viewBox="0 0 78 91"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
fill={color}
|
fill={color}
|
||||||
style={{padding, margin}}
|
d="M29 25C28.2193 25.007 27.6091 25.4026 27.2812 25.9687L20.8438 37H8C3.6026 37 0 40.6026 0 45V83C0 87.3974 3.6026 91 8 91H70C74.3974 91 78 87.3974 78 83V45C78 40.6026 74.3974 37 70 37H57.1562L50.7188 25.9687C50.3641 25.3795 49.6877 24.9983 49 25H29ZM30.125 29H47.875L54.2812 40C54.6281 40.6007 55.3063 40.9953 56 41H70C72.2506 41 74 42.7494 74 45V83C74 85.2505 72.2506 87 70 87H8C5.74944 87 4 85.2505 4 83V45C4 42.7494 5.74944 41 8 41H22C22.6937 40.995 23.3719 40.6007 23.7188 40L30.125 29ZM39 47C30.1871 47 23 54.1871 23 63C23 71.8128 30.1871 79 39 79C47.8129 79 55 71.8128 55 63C55 54.1871 47.8129 47 39 47ZM39 51C45.6511 51 51 56.3489 51 63C51 69.6511 45.6511 75 39 75C32.3489 75 27 69.6511 27 63C27 56.3489 32.3489 51 39 51Z"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
/>
|
||||||
viewBox="0 0 24 24"
|
<path
|
||||||
>
|
|
||||||
<path d="M20,10.5a1,1,0,0,0-1,1v7a1,1,0,0,1-1,1H4a1,1,0,0,1-1-1v-8a1,1,0,0,1,1-1H6a1,1,0,0,0,1-.68l.54-1.64a1,1,0,0,1,.95-.68H14a1,1,0,0,0,0-2H8.44A3,3,0,0,0,5.6,6.55l-.32,1H4a3,3,0,0,0-3,3v8a3,3,0,0,0,3,3H18a3,3,0,0,0,3-3v-7A1,1,0,0,0,20,10.5Zm-9-1a4,4,0,1,0,4,4A4,4,0,0,0,11,9.5Zm0,6a2,2,0,1,1,2-2A2,2,0,0,1,11,15.5Zm11-11H21v-1a1,1,0,0,0-2,0v1H18a1,1,0,0,0,0,2h1v1a1,1,0,0,0,2,0v-1h1a1,1,0,0,0,0-2Z" />
|
|
||||||
</svg> */}
|
|
||||||
<svg
|
|
||||||
width={width}
|
|
||||||
height={height}
|
|
||||||
fill={color}
|
fill={color}
|
||||||
style={{padding, margin}}
|
d="M60 15.5L65 1H76.5L69.5 13H74.5L60 30.5L65 15.5H60Z"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
stroke="black"
|
||||||
version="1.1"
|
strokeWidth="2"
|
||||||
x="0px"
|
strokeLinejoin="round"
|
||||||
y="0px"
|
/>
|
||||||
viewBox="0 0 100 100"
|
</svg>
|
||||||
className="screenshotIcon"
|
|
||||||
>
|
|
||||||
<g transform="translate(0,-952.36218)">
|
|
||||||
<path
|
|
||||||
d="m 83,958.36218 c -1.1046,0 -2,0.89543 -2,2 l 0,7 -7,0 c -1.10457,0 -2,0.8954 -2,2 0,1.1046 0.89543,2 2,2 l 7,0 0,7 c 0,1.10457 0.8954,2 2,2 1.1046,0 2,-0.89543 2,-2 l 0,-7 7,0 c 1.10457,0 2,-0.8954 2,-2 0,-1.1046 -0.89543,-2 -2,-2 l -7,0 0,-7 c 0,-1.10457 -0.8954,-2 -2,-2 z m -48,22 c -0.78068,0.007 -1.3909,0.40265 -1.71875,0.96875 l -6.4375,11.03125 -12.84375,0 c -4.3973999,0 -8,3.6026 -8,8.00002 l 0,38 c 0,4.3974 3.6026001,8 8,8 l 62,0 c 4.3974,0 8,-3.6026 8,-8 l 0,-38 c 0,-4.39742 -3.6026,-8.00002 -8,-8.00002 l -12.84375,0 -6.4375,-11.03125 C 56.3641,980.74168 55.68774,980.36046 55,980.36218 l -20,0 z m 1.125,4 17.75,0 6.40625,11 c 0.34687,0.60075 1.02507,0.99534 1.71875,1 l 14,0 c 2.25056,0 4,1.74944 4,4.00002 l 0,38 c 0,2.2505 -1.74944,4 -4,4 l -62,0 c -2.25056,0 -4,-1.7495 -4,-4 l 0,-38 c 0,-2.25058 1.74944,-4.00002 4,-4.00002 l 14,0 c 0.69368,-0.005 1.37188,-0.39925 1.71875,-1 l 6.40625,-11 z M 45,1002.3622 c -8.81287,0 -16,7.1871 -16,16 0,8.8128 7.18713,16 16,16 8.81286,0 16,-7.1872 16,-16 0,-8.8129 -7.18714,-16 -16,-16 z m 0,4 c 6.6511,0 12,5.3489 12,12 0,6.6511 -5.3489,12 -12,12 -6.65111,0 -12,-5.3489 -12,-12 0,-6.6511 5.34889,-12 12,-12 z"
|
|
||||||
fill={color}
|
|
||||||
fillOpacity="1"
|
|
||||||
stroke="none"
|
|
||||||
marker="none"
|
|
||||||
visibility="visible"
|
|
||||||
display="inline"
|
|
||||||
overflow="visible"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</Fragment>
|
|
||||||
);
|
);
|
||||||
|
|
6
desktop-app/flow-typed/electron.js
vendored
Normal file
6
desktop-app/flow-typed/electron.js
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
declare class WebviewElement extends HTMLElement {
|
||||||
|
insertCSS: string => Promise<string>;
|
||||||
|
executeJavaScript: string => Promise<any>;
|
||||||
|
getWebContentsId: () => number;
|
||||||
|
removeInsertedCSS: number => Promise<void>;
|
||||||
|
}
|
Loading…
Reference in a new issue