diff --git a/CHANGELOG.md b/CHANGELOG.md
index a5b0ebd9d..4547a9576 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,9 @@ Sometimes the changelog has notes (not comprehensive) acknowledging people's wor
### v1.11.14
+**v1.11.14.4** *(2015-10-26)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.14.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.14.4/builds/4chan-X-noupdate.crx "Chromium version")]
+- Support drawing on frames from WebMs.
+
**v1.11.14.3** *(2015-10-25)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.14.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.14.3/builds/4chan-X-noupdate.crx "Chromium version")]
- Support opening a blank canvas from boards other than /i/. With no file selected, oekaki button in QR shows/hides the new image controls.
- Support resume (retaining layers and undo history) in Tegaki when possible. Only available when re-opening the last image edited.
diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx
index 0a1a57870..18ff86968 100644
Binary files a/builds/4chan-X-beta.crx and b/builds/4chan-X-beta.crx differ
diff --git a/builds/4chan-X-beta.meta.js b/builds/4chan-X-beta.meta.js
index 213c1db86..812344f51 100644
--- a/builds/4chan-X-beta.meta.js
+++ b/builds/4chan-X-beta.meta.js
@@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X beta
-// @version 1.11.14.3
+// @version 1.11.14.4
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
diff --git a/builds/4chan-X-beta.user.js b/builds/4chan-X-beta.user.js
index 5aa8b569a..03b648c0e 100644
--- a/builds/4chan-X-beta.user.js
+++ b/builds/4chan-X-beta.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X beta
-// @version 1.11.14.3
+// @version 1.11.14.4
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -414,7 +414,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.14.3',
+ VERSION: '1.11.14.4',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -7376,7 +7376,7 @@
if (blob) {
return QR.handleFiles([blob]);
} else {
- return QR.error("Can't load image.");
+ return QR.error("Can't load file.");
}
});
},
@@ -8951,8 +8951,8 @@
});
},
node: function() {
- var link, ref;
- if (!((ref = this.file) != null ? ref.isImage : void 0)) {
+ var link;
+ if (!(this.file && (this.file.isImage || this.file.isVideo))) {
return;
}
if (this.isClone) {
@@ -8971,19 +8971,41 @@
return $.on(link, 'click', QR.oekaki.editFile);
},
editFile: function() {
- var post;
+ var currentTime, isVideo, post, ref;
if (!QR.postingIsEnabled) {
return;
}
QR.quote.call(this);
post = Get.postFromNode(this);
+ isVideo = post.file.isVideo;
+ currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0;
return CrossOrigin.file(post.file.url, function(blob) {
- if (blob) {
+ var video;
+ if (!blob) {
+ return QR.error("Can't load file.");
+ } else if (isVideo) {
+ video = $.el('video');
+ $.on(video, 'loadedmetadata', function() {
+ $.on(video, 'seeked', function() {
+ var canvas;
+ canvas = $.el('canvas', {
+ width: video.videoWidth,
+ height: video.videoHeight
+ });
+ canvas.getContext('2d').drawImage(video, 0, 0);
+ return canvas.toBlob(function(snapshot) {
+ snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png';
+ QR.handleFiles([snapshot]);
+ return QR.oekaki.edit();
+ });
+ });
+ return video.currentTime = currentTime;
+ });
+ return video.src = URL.createObjectURL(blob);
+ } else {
blob.name = post.file.name;
QR.handleFiles([blob]);
return QR.oekaki.edit();
- } else {
- return QR.error("Can't load image.");
}
});
},
@@ -9075,19 +9097,20 @@
}));
};
cb = function(e) {
- var img;
+ var file, isVideo;
document.removeEventListener('QRFile', cb, false);
if (!e.detail) {
return error('No file to edit.');
}
- if (!/^image\//.test(e.detail.type)) {
+ if (!/^(image|video)\//.test(e.detail.type)) {
return error('Not an image.');
}
- img = new Image();
- img.onerror = function() {
- return error('Could not open image.');
- };
- img.onload = function() {
+ isVideo = /^video\//.test(e.detail.type);
+ file = document.createElement(isVideo ? 'video' : 'img');
+ file.addEventListener('error', function() {
+ return error('Could not open file.', false);
+ });
+ file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() {
if (Tegaki.bg) {
Tegaki.destroy();
}
@@ -9095,13 +9118,13 @@
Tegaki.open({
onDone: FCX.oekakiCB,
onCancel: function() {},
- width: img.naturalWidth,
- height: img.naturalHeight,
+ width: file.naturalWidth || file.videoWidth,
+ height: file.naturalHeight || file.videoHeight,
bgColor: 'transparent'
});
- return Tegaki.activeCtx.drawImage(img, 0, 0);
- };
- return img.src = URL.createObjectURL(e.detail);
+ return Tegaki.activeCtx.drawImage(file, 0, 0);
+ }, false);
+ return file.src = URL.createObjectURL(e.detail);
};
if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) {
FCX.oekakiName = name;
diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx
index a463df0ea..5f42c94f0 100644
Binary files a/builds/4chan-X-noupdate.crx and b/builds/4chan-X-noupdate.crx differ
diff --git a/builds/4chan-X-noupdate.user.js b/builds/4chan-X-noupdate.user.js
index 786e191d7..0a091018d 100644
--- a/builds/4chan-X-noupdate.user.js
+++ b/builds/4chan-X-noupdate.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
-// @version 1.11.14.3
+// @version 1.11.14.4
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -414,7 +414,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.14.3',
+ VERSION: '1.11.14.4',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -7376,7 +7376,7 @@
if (blob) {
return QR.handleFiles([blob]);
} else {
- return QR.error("Can't load image.");
+ return QR.error("Can't load file.");
}
});
},
@@ -8951,8 +8951,8 @@
});
},
node: function() {
- var link, ref;
- if (!((ref = this.file) != null ? ref.isImage : void 0)) {
+ var link;
+ if (!(this.file && (this.file.isImage || this.file.isVideo))) {
return;
}
if (this.isClone) {
@@ -8971,19 +8971,41 @@
return $.on(link, 'click', QR.oekaki.editFile);
},
editFile: function() {
- var post;
+ var currentTime, isVideo, post, ref;
if (!QR.postingIsEnabled) {
return;
}
QR.quote.call(this);
post = Get.postFromNode(this);
+ isVideo = post.file.isVideo;
+ currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0;
return CrossOrigin.file(post.file.url, function(blob) {
- if (blob) {
+ var video;
+ if (!blob) {
+ return QR.error("Can't load file.");
+ } else if (isVideo) {
+ video = $.el('video');
+ $.on(video, 'loadedmetadata', function() {
+ $.on(video, 'seeked', function() {
+ var canvas;
+ canvas = $.el('canvas', {
+ width: video.videoWidth,
+ height: video.videoHeight
+ });
+ canvas.getContext('2d').drawImage(video, 0, 0);
+ return canvas.toBlob(function(snapshot) {
+ snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png';
+ QR.handleFiles([snapshot]);
+ return QR.oekaki.edit();
+ });
+ });
+ return video.currentTime = currentTime;
+ });
+ return video.src = URL.createObjectURL(blob);
+ } else {
blob.name = post.file.name;
QR.handleFiles([blob]);
return QR.oekaki.edit();
- } else {
- return QR.error("Can't load image.");
}
});
},
@@ -9075,19 +9097,20 @@
}));
};
cb = function(e) {
- var img;
+ var file, isVideo;
document.removeEventListener('QRFile', cb, false);
if (!e.detail) {
return error('No file to edit.');
}
- if (!/^image\//.test(e.detail.type)) {
+ if (!/^(image|video)\//.test(e.detail.type)) {
return error('Not an image.');
}
- img = new Image();
- img.onerror = function() {
- return error('Could not open image.');
- };
- img.onload = function() {
+ isVideo = /^video\//.test(e.detail.type);
+ file = document.createElement(isVideo ? 'video' : 'img');
+ file.addEventListener('error', function() {
+ return error('Could not open file.', false);
+ });
+ file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() {
if (Tegaki.bg) {
Tegaki.destroy();
}
@@ -9095,13 +9118,13 @@
Tegaki.open({
onDone: FCX.oekakiCB,
onCancel: function() {},
- width: img.naturalWidth,
- height: img.naturalHeight,
+ width: file.naturalWidth || file.videoWidth,
+ height: file.naturalHeight || file.videoHeight,
bgColor: 'transparent'
});
- return Tegaki.activeCtx.drawImage(img, 0, 0);
- };
- return img.src = URL.createObjectURL(e.detail);
+ return Tegaki.activeCtx.drawImage(file, 0, 0);
+ }, false);
+ return file.src = URL.createObjectURL(e.detail);
};
if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) {
FCX.oekakiName = name;
diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx
index 6f689b6cd..6e4a32142 100644
Binary files a/builds/4chan-X.crx and b/builds/4chan-X.crx differ
diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js
index 0589d599f..20fc0904f 100644
--- a/builds/4chan-X.meta.js
+++ b/builds/4chan-X.meta.js
@@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X
-// @version 1.11.14.3
+// @version 1.11.14.4
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js
index 5803dfdbf..a312d2079 100644
--- a/builds/4chan-X.user.js
+++ b/builds/4chan-X.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
-// @version 1.11.14.3
+// @version 1.11.14.4
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -414,7 +414,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.14.3',
+ VERSION: '1.11.14.4',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -7376,7 +7376,7 @@
if (blob) {
return QR.handleFiles([blob]);
} else {
- return QR.error("Can't load image.");
+ return QR.error("Can't load file.");
}
});
},
@@ -8951,8 +8951,8 @@
});
},
node: function() {
- var link, ref;
- if (!((ref = this.file) != null ? ref.isImage : void 0)) {
+ var link;
+ if (!(this.file && (this.file.isImage || this.file.isVideo))) {
return;
}
if (this.isClone) {
@@ -8971,19 +8971,41 @@
return $.on(link, 'click', QR.oekaki.editFile);
},
editFile: function() {
- var post;
+ var currentTime, isVideo, post, ref;
if (!QR.postingIsEnabled) {
return;
}
QR.quote.call(this);
post = Get.postFromNode(this);
+ isVideo = post.file.isVideo;
+ currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0;
return CrossOrigin.file(post.file.url, function(blob) {
- if (blob) {
+ var video;
+ if (!blob) {
+ return QR.error("Can't load file.");
+ } else if (isVideo) {
+ video = $.el('video');
+ $.on(video, 'loadedmetadata', function() {
+ $.on(video, 'seeked', function() {
+ var canvas;
+ canvas = $.el('canvas', {
+ width: video.videoWidth,
+ height: video.videoHeight
+ });
+ canvas.getContext('2d').drawImage(video, 0, 0);
+ return canvas.toBlob(function(snapshot) {
+ snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png';
+ QR.handleFiles([snapshot]);
+ return QR.oekaki.edit();
+ });
+ });
+ return video.currentTime = currentTime;
+ });
+ return video.src = URL.createObjectURL(blob);
+ } else {
blob.name = post.file.name;
QR.handleFiles([blob]);
return QR.oekaki.edit();
- } else {
- return QR.error("Can't load image.");
}
});
},
@@ -9075,19 +9097,20 @@
}));
};
cb = function(e) {
- var img;
+ var file, isVideo;
document.removeEventListener('QRFile', cb, false);
if (!e.detail) {
return error('No file to edit.');
}
- if (!/^image\//.test(e.detail.type)) {
+ if (!/^(image|video)\//.test(e.detail.type)) {
return error('Not an image.');
}
- img = new Image();
- img.onerror = function() {
- return error('Could not open image.');
- };
- img.onload = function() {
+ isVideo = /^video\//.test(e.detail.type);
+ file = document.createElement(isVideo ? 'video' : 'img');
+ file.addEventListener('error', function() {
+ return error('Could not open file.', false);
+ });
+ file.addEventListener((isVideo ? 'loadeddata' : 'load'), function() {
if (Tegaki.bg) {
Tegaki.destroy();
}
@@ -9095,13 +9118,13 @@
Tegaki.open({
onDone: FCX.oekakiCB,
onCancel: function() {},
- width: img.naturalWidth,
- height: img.naturalHeight,
+ width: file.naturalWidth || file.videoWidth,
+ height: file.naturalHeight || file.videoHeight,
bgColor: 'transparent'
});
- return Tegaki.activeCtx.drawImage(img, 0, 0);
- };
- return img.src = URL.createObjectURL(e.detail);
+ return Tegaki.activeCtx.drawImage(file, 0, 0);
+ }, false);
+ return file.src = URL.createObjectURL(e.detail);
};
if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) {
FCX.oekakiName = name;
diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip
index e3ccecc1f..232cd5260 100644
Binary files a/builds/4chan-X.zip and b/builds/4chan-X.zip differ
diff --git a/builds/updates-beta.xml b/builds/updates-beta.xml
index 6fa8146bd..3a87001cf 100644
--- a/builds/updates-beta.xml
+++ b/builds/updates-beta.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/builds/updates.xml b/builds/updates.xml
index c9893599e..283385829 100644
--- a/builds/updates.xml
+++ b/builds/updates.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/package.json b/package.json
index 1e7dae233..ea8187179 100644
--- a/package.json
+++ b/package.json
@@ -4,8 +4,8 @@
"meta": {
"name": "4chan X",
"fork": "ccd0",
- "version": "1.11.14.3",
- "date": "2015-10-26T06:21:56.818Z",
+ "version": "1.11.14.4",
+ "date": "2015-10-26T18:29:12.872Z",
"page": "https://www.4chan-x.net/",
"downloads": "https://www.4chan-x.net/builds/",
"oldVersions": "https://raw.githubusercontent.com/ccd0/4chan-x/",