mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-27 00:30:09 +02:00
port takeScreenshot
This commit is contained in:
@@ -85,7 +85,6 @@ export default class ContentWrap extends Component {
|
|||||||
}
|
}
|
||||||
}, this.updateDelay);
|
}, this.updateDelay);
|
||||||
}
|
}
|
||||||
clearConsole() {}
|
|
||||||
|
|
||||||
createPreviewFile(html, css, js) {
|
createPreviewFile(html, css, js) {
|
||||||
const shouldInlineJs =
|
const shouldInlineJs =
|
||||||
@@ -236,6 +235,8 @@ export default class ContentWrap extends Component {
|
|||||||
this.cm.css.refresh();
|
this.cm.css.refresh();
|
||||||
this.cm.js.refresh();
|
this.cm.js.refresh();
|
||||||
|
|
||||||
|
this.clearConsole();
|
||||||
|
|
||||||
// Set preview only when all modes are updated so that preview doesn't generate on partially
|
// Set preview only when all modes are updated so that preview doesn't generate on partially
|
||||||
// correct modes and also doesn't happen 3 times.
|
// correct modes and also doesn't happen 3 times.
|
||||||
Promise.all([
|
Promise.all([
|
||||||
@@ -626,6 +627,9 @@ export default class ContentWrap extends Component {
|
|||||||
this.props.onCodeSettingsChange('css', settings);
|
this.props.onCodeSettingsChange('css', settings);
|
||||||
this.setPreviewContent(true);
|
this.setPreviewContent(true);
|
||||||
}
|
}
|
||||||
|
getDemoFrame(callback) {
|
||||||
|
callback(this.frame);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@@ -55,7 +55,7 @@ export default class Footer extends Component {
|
|||||||
href=""
|
href=""
|
||||||
id="screenshotBtn"
|
id="screenshotBtn"
|
||||||
class="mode-btn hint--rounded hint--top-left show-when-extension"
|
class="mode-btn hint--rounded hint--top-left show-when-extension"
|
||||||
d-click="takeScreenshot"
|
onClick={this.props.screenshotBtnClickHandler}
|
||||||
aria-label="Take screenshot of preview"
|
aria-label="Take screenshot of preview"
|
||||||
>
|
>
|
||||||
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
|
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
|
||||||
|
@@ -31,6 +31,7 @@ import Profile from './Profile';
|
|||||||
import { auth } from '../auth';
|
import { auth } from '../auth';
|
||||||
import SupportDeveloperModal from './SupportDeveloperModal';
|
import SupportDeveloperModal from './SupportDeveloperModal';
|
||||||
import KeyboardShortcutsModal from './KeyboardShortcutsModal';
|
import KeyboardShortcutsModal from './KeyboardShortcutsModal';
|
||||||
|
import { takeScreenshot } from '../takeScreenshot';
|
||||||
|
|
||||||
if (module.hot) {
|
if (module.hot) {
|
||||||
require('preact/debug');
|
require('preact/debug');
|
||||||
@@ -839,6 +840,12 @@ export default class App extends Component {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
trackEvent('ui', 'exportBtnClicked');
|
trackEvent('ui', 'exportBtnClicked');
|
||||||
}
|
}
|
||||||
|
screenshotBtnClickHandler() {
|
||||||
|
this.contentWrap.getDemoFrame(frame => {
|
||||||
|
takeScreenshot(frame.getBoundingClientRect());
|
||||||
|
});
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@@ -892,6 +899,9 @@ export default class App extends Component {
|
|||||||
keyboardShortcutsBtnClickHandler={() =>
|
keyboardShortcutsBtnClickHandler={() =>
|
||||||
this.setState({ isKeyboardShortcutsModalOpen: true })
|
this.setState({ isKeyboardShortcutsModalOpen: true })
|
||||||
}
|
}
|
||||||
|
screenshotBtnClickHandler={this.screenshotBtnClickHandler.bind(
|
||||||
|
this
|
||||||
|
)}
|
||||||
hasUnseenChangelog={this.state.hasUnseenChangelog}
|
hasUnseenChangelog={this.state.hasUnseenChangelog}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
138
webmaker/src/takeScreenshot.js
Normal file
138
webmaker/src/takeScreenshot.js
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import {
|
||||||
|
handleDownloadsPermission
|
||||||
|
} from "./utils";
|
||||||
|
|
||||||
|
function saveScreenshot(dataURI) {
|
||||||
|
// convert base64 to raw binary data held in a string
|
||||||
|
// doesn't handle URLEncoded DataURIs
|
||||||
|
var byteString = atob(dataURI.split(',')[1]);
|
||||||
|
|
||||||
|
// separate out the mime component
|
||||||
|
var mimeString = dataURI
|
||||||
|
.split(',')[0]
|
||||||
|
.split(':')[1]
|
||||||
|
.split(';')[0];
|
||||||
|
|
||||||
|
// write the bytes of the string to an ArrayBuffer
|
||||||
|
var ab = new ArrayBuffer(byteString.length);
|
||||||
|
var ia = new Uint8Array(ab);
|
||||||
|
for (var i = 0; i < byteString.length; i++) {
|
||||||
|
ia[i] = byteString.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a blob for writing to a file
|
||||||
|
var blob = new Blob([ab], {
|
||||||
|
type: mimeString
|
||||||
|
});
|
||||||
|
var size = blob.size + 1024 / 2;
|
||||||
|
|
||||||
|
var d = new Date();
|
||||||
|
var fileName = [
|
||||||
|
'web-maker-screenshot',
|
||||||
|
d.getFullYear(),
|
||||||
|
d.getMonth() + 1,
|
||||||
|
d.getDate(),
|
||||||
|
d.getHours(),
|
||||||
|
d.getMinutes(),
|
||||||
|
d.getSeconds()
|
||||||
|
].join('-');
|
||||||
|
fileName += '.png';
|
||||||
|
|
||||||
|
function onWriteEnd() {
|
||||||
|
var filePath =
|
||||||
|
'filesystem:chrome-extension://' +
|
||||||
|
chrome.i18n.getMessage('@@extension_id') +
|
||||||
|
'/temporary/' +
|
||||||
|
fileName;
|
||||||
|
|
||||||
|
chrome.downloads.download({
|
||||||
|
url: filePath
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
// If there was an error, just open the screenshot in a tab.
|
||||||
|
// This happens in incognito mode where extension cannot access filesystem.
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
window.open(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorHandler(e) {
|
||||||
|
utils.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a blob for writing to a file
|
||||||
|
window.webkitRequestFileSystem(
|
||||||
|
window.TEMPORARY,
|
||||||
|
size,
|
||||||
|
fs => {
|
||||||
|
fs.root.getFile(
|
||||||
|
fileName, {
|
||||||
|
create: true
|
||||||
|
},
|
||||||
|
fileEntry => {
|
||||||
|
fileEntry.createWriter(fileWriter => {
|
||||||
|
fileWriter.onwriteend = onWriteEnd;
|
||||||
|
fileWriter.write(blob);
|
||||||
|
}, errorHandler);
|
||||||
|
},
|
||||||
|
errorHandler
|
||||||
|
);
|
||||||
|
},
|
||||||
|
errorHandler
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function takeScreenshot(boundRect) {
|
||||||
|
handleDownloadsPermission().then(() => {
|
||||||
|
// Hide tooltips so that they don't show in the screenshot
|
||||||
|
var s = document.createElement('style');
|
||||||
|
s.textContent =
|
||||||
|
'[class*="hint"]:after, [class*="hint"]:before { display: none!important; }';
|
||||||
|
document.body.appendChild(s);
|
||||||
|
|
||||||
|
function onImgLoad(image) {
|
||||||
|
var c = document.createElement('canvas');
|
||||||
|
var iframeBounds = boundRect;
|
||||||
|
c.width = iframeBounds.width;
|
||||||
|
c.height = iframeBounds.height;
|
||||||
|
var ctx = c.getContext('2d');
|
||||||
|
var devicePixelRatio = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
ctx.drawImage(
|
||||||
|
image,
|
||||||
|
iframeBounds.left * devicePixelRatio,
|
||||||
|
iframeBounds.top * devicePixelRatio,
|
||||||
|
iframeBounds.width * devicePixelRatio,
|
||||||
|
iframeBounds.height * devicePixelRatio,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
iframeBounds.width,
|
||||||
|
iframeBounds.height
|
||||||
|
);
|
||||||
|
image.removeEventListener('load', onImgLoad);
|
||||||
|
saveScreenshot(c.toDataURL());
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
debugger
|
||||||
|
chrome.tabs.captureVisibleTab(
|
||||||
|
null, {
|
||||||
|
format: 'png',
|
||||||
|
quality: 100
|
||||||
|
},
|
||||||
|
function (dataURI) {
|
||||||
|
s.remove();
|
||||||
|
if (dataURI) {
|
||||||
|
var image = new Image();
|
||||||
|
image.src = dataURI;
|
||||||
|
image.addEventListener('load', () => onImgLoad(image, dataURI));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}, 50);
|
||||||
|
|
||||||
|
trackEvent('ui', 'takeScreenshotBtnClick');
|
||||||
|
});
|
||||||
|
};
|
Reference in New Issue
Block a user