diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ba18eaa2..02a9fcdce 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +<<<<<<< HEAD +======= +### v1.7.3 +*2014-04-07* + +**ccd0** +- Fix behavior of .webm videos expanded within inline quotes. +- Contract thumbnails in quoted previews to avoid crashes caused by videos in quoted previews on some systems. +- Change interface when both `Autoplay` and `Show Controls` are unchecked. In this mode, videos are now activated by clicking on them. The first click expands the video, the second click plays the video, and the third click contracts it. +- Add item `Expand videos` in `Image Expansion` menu, which enables expansion of videos by `Expand All Images`. Disabled by default. Previously videos were expanded. +- Disable autoplay for videos expanded by `Expand All Images`. + +### v1.7.2 +*2014-04-07* + +>>>>>>> ccd0 **ccd0** - Restore thread expansion with JSON navigation disabled. @@ -36,13 +52,15 @@ **ccd0**: - Support hover for .webm videos. - Add .webm to supported posting types. -- Add option to enable/disable sound. +- Add option `Allow Sound` to enable/disable sound. Enabled by default. ## v1.5.0 *2014-04-04* **ccd0**: - Support expansion of .webm videos. +- New setting: `Autoplay`, enabled by default. Causes videos to play immediately when expanded. +- New setting: `Show Controls`, enabled by default. Shows native controls on videos. ### v1.4.7 *2014-04-03* diff --git a/LICENSE b/LICENSE index 56c761ecb..ffac59f17 100755 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.7.2 - 2014-04-07 +* 4chan X - Version 1.7.3 - 2014-04-08 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js index 8d5b78fe5..2bc1fb1c8 100755 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.7.2 +// @version 1.7.3 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index dfb988903..d3cf64e6a 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.7.2 +// @version 1.7.3 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -24,7 +24,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.7.2 - 2014-04-07 +* 4chan X - Version 1.7.3 - 2014-04-08 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -244,6 +244,7 @@ 'Fit width': [false, ''], 'Fit height': [false, ''], 'Expand spoilers': [true, 'Expand all images along with spoilers.'], + 'Expand videos': [false, 'Expand all images also expands videos (no autoplay).'], 'Expand from here': [false, 'Expand all images only from current position to thread end.'], 'Advance on contract': [false, 'Advance to next post when contracting an expanded image.'] }, @@ -373,7 +374,7 @@ doc = d.documentElement; g = { - VERSION: '1.7.2', + VERSION: '1.7.3', NAMESPACE: '4chan X.', boards: {} }; @@ -7928,7 +7929,7 @@ ImageExpand = { init: function() { - if (!Conf['Image Expansion']) { + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { return; } this.EAI = $.el('a', { @@ -7937,34 +7938,33 @@ title: 'Expand All Images', href: 'javascript:;' }); - $.on(this.EAI, 'click', this.cb.toggleAll); + $.on(this.EAI, 'click', ImageExpand.cb.toggleAll); Header.addShortcut(this.EAI, 3); - $.on(d, 'scroll visibilitychange', this.cb.playVideos); return Post.callbacks.push({ name: 'Image Expansion', cb: this.node }); }, node: function() { - var thumb; - if (!(this.file && (this.file.isImage || this.file.isVideo))) { + var clone, thumb, _ref, _ref1; + if (!(((_ref = this.file) != null ? _ref.isImage : void 0) || ((_ref1 = this.file) != null ? _ref1.isVideo : void 0))) { return; } thumb = this.file.thumb; $.on(thumb.parentNode, 'click', ImageExpand.cb.toggle); - if (this.isClone) { - if (this.file.isImage && this.file.isExpanding) { - ImageExpand.contract(this); - ImageExpand.expand(this); - return; - } - if (this.file.isExpanded && this.file.isVideo) { - ImageExpand.setupVideoControls(this); - return; - } - } - if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler)) { + if (this.isClone && $.hasClass(thumb, 'expanding')) { + ImageExpand.contract(this); return ImageExpand.expand(this); + } else if (this.isClone && this.file.isExpanded && this.file.isVideo) { + clone = this; + ImageExpand.setupVideoControls(clone); + if (!clone.origin.file.fullImage.paused) { + return $.queueTask(function() { + return ImageExpand.startVideo(clone); + }); + } + } else if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler) && (Conf['Expand videos'] || !this.file.isVideo)) { + return ImageExpand.expand(this, null, true); } }, cb: { @@ -7981,53 +7981,40 @@ return ImageExpand.toggle(post); }, toggleAll: function() { - var func; + var func, toggle; $.event('CloseMenu'); + toggle = function(post) { + var file; + file = post.file; + if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) { + return; + } + if (ImageExpand.on && (!Conf['Expand spoilers'] && file.isSpoiler || !Conf['Expand videos'] && file.isVideo || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0)) { + return; + } + return $.queueTask(func, post); + }; if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) { ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress'; ImageExpand.EAI.title = 'Contract All Images'; - func = ImageExpand.expand; + func = function(post) { + return ImageExpand.expand(post, null, true); + }; } else { ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand'; ImageExpand.EAI.title = 'Expand All Images'; func = ImageExpand.contract; } return g.posts.forEach(function(post) { - var file, _i, _len, _ref; - _ref = [post].concat(post.clones); + var _i, _len, _ref; + toggle(post); + _ref = post.clones; for (_i = 0, _len = _ref.length; _i < _len; _i++) { post = _ref[_i]; - file = post.file; - if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) { - return; - } - if (ImageExpand.on && (post.isHidden || !Conf['Expand spoilers'] && post.file.isSpoiler || !doc.contains(post.nodes.root) || Conf['Expand from here'] && Header.getTopOf(post.file.thumb) < 0)) { - return; - } - $.queueTask(func, post); + toggle(post); } }); }, - playVideos: function(e) { - var fullID, play, post, _i, _len, _ref, _ref1; - _ref = g.posts; - for (fullID in _ref) { - post = _ref[fullID]; - if (!(post.file && post.file.isVideo && post.file.isExpanded)) { - continue; - } - _ref1 = [post].concat(post.clones); - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - post = _ref1[_i]; - play = !d.hidden && !post.isHidden && doc.contains(post.nodes.root) && Header.isNodeVisible(post.nodes.root); - if (play) { - post.file.fullImage.play(); - } else { - post.file.fullImage.pause(); - } - } - } - }, setFitness: function() { return (this.checked ? $.addClass : $.rmClass)(doc, this.name.toLowerCase().replace(/\s+/g, '-')); } @@ -8035,7 +8022,7 @@ toggle: function(post) { var headRect, left, root, thumb, top, x, y, _ref; thumb = post.file.thumb; - if (!(post.file.isExpanded || post.file.isExpanding)) { + if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) { ImageExpand.expand(post); return; } @@ -8083,10 +8070,9 @@ } $.rmClass(post.nodes.root, 'expanded-image'); $.rmClass(post.file.thumb, 'expanding'); - delete post.file.isExpanding; return post.file.isExpanded = false; }, - expand: function(post, src) { + expand: function(post, src, disableAutoplay) { var el, isVideo, thumb, _ref; _ref = post.file, thumb = _ref.thumb, isVideo = _ref.isVideo; if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) { @@ -8109,42 +8095,49 @@ $.after(thumb, el); } return $.asap((function() { - return el.videoHeight || el.naturalHeight; + if (isVideo) { + return el.videoHeight; + } else { + return el.naturalHeight; + } }), function() { - return ImageExpand.completeExpand(post); + return ImageExpand.completeExpand(post, disableAutoplay); }); }, - completeExpand: function(post) { - var bottom, complete, thumb; + completeExpand: function(post, disableAutoplay) { + var bottom, thumb; thumb = post.file.thumb; if (!$.hasClass(thumb, 'expanding')) { return; } - delete post.file.isExpanding; - post.file.isExpanded = true; - complete = function() { - $.addClass(post.nodes.root, 'expanded-image'); - $.rmClass(post.file.thumb, 'expanding'); - if (post.file.isVideo) { - return ImageExpand.setupVideo(post); - } - }; if (!post.nodes.root.parentNode) { - complete(); + ImageExpand.completeExpand2(post); return; } - if (post.file.isVideo && !d.hidden && Header.isNodeVisible(post.nodes.root)) { - post.file.fullImage.play(); - } bottom = post.nodes.root.getBoundingClientRect().bottom; return $.queueTask(function() { - complete(); + ImageExpand.completeExpand2(post, disableAutoplay); if (!(bottom <= 0)) { return; } return window.scrollBy(0, post.nodes.root.getBoundingClientRect().bottom - bottom); }); }, + completeExpand2: function(post, disableAutoplay) { + var thumb; + thumb = post.file.thumb; + $.addClass(post.nodes.root, 'expanded-image'); + $.rmClass(post.file.thumb, 'expanding'); + post.file.isExpanded = true; + if (post.file.isVideo) { + ImageExpand.setupVideoControls(post); + post.file.fullImage.muted = !Conf['Allow Sound']; + post.file.fullImage.controls = Conf['Show Controls']; + if (Conf['Autoplay'] && !disableAutoplay) { + return ImageExpand.startVideo(post); + } + } + }, videoCB: { click: function(e) { if (this.paused && !this.controls) { @@ -8199,34 +8192,29 @@ } return $.add(file.text, file.videoControls); }, - setupVideo: function(post) { - var file, video; - ImageExpand.setupVideoControls(post); + startVideo: function(post) { + var controls, file, video; file = post.file; video = file.fullImage; - video.muted = !Conf['Allow Sound']; - video.controls = Conf['Show Controls']; - if (Conf['Autoplay']) { - video.controls = false; - video.play(); - if (Conf['Show Controls']) { - return $.asap((function() { - return (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || !file.isExpanded; - }), function() { - if (file.isExpanded) { - return video.controls = true; - } - }, 500); - } + controls = video.controls; + video.controls = false; + video.play(); + if (controls) { + return $.asap((function() { + return (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || !file.isExpanded; + }), function() { + if (file.isExpanded) { + return video.controls = true; + } + }, 500); } }, error: function() { var URL, post, src, timeoutID; post = Get.postFromNode(this); - post.file.isReady = false; $.rm(this); delete post.file.fullImage; - if (!(post.file.isExpanding || post.file.isExpanded)) { + if (!($.hasClass(post.file.thumb, 'expanding') || $.hasClass(post.nodes.root, 'expanded-image'))) { return; } ImageExpand.contract(post); @@ -8271,7 +8259,7 @@ menu: { init: function() { var conf, createSubEntry, el, name, subEntries, _ref; - if (!Conf['Image Expansion']) { + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { return; } el = $.el('span', { @@ -12964,7 +12952,7 @@ return; } $.event('CloseMenu'); - html = "
"; + html = "
"; Settings.overlay = overlay = $.el('div', { id: 'overlay' }); diff --git a/builds/crx/manifest.json b/builds/crx/manifest.json index 6c06910bd..70aeb5e13 100755 --- a/builds/crx/manifest.json +++ b/builds/crx/manifest.json @@ -1,6 +1,6 @@ { "name": "4chan X", - "version": "1.7.2", + "version": "1.7.3", "manifest_version": 2, "description": "Cross-browser userscript for maximum lurking on 4chan.", "icons": { diff --git a/builds/crx/script.js b/builds/crx/script.js index 83ef2a85f..ec1e9a1b4 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.7.2 - 2014-04-07 +* 4chan X - Version 1.7.3 - 2014-04-08 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -220,6 +220,7 @@ 'Fit width': [false, ''], 'Fit height': [false, ''], 'Expand spoilers': [true, 'Expand all images along with spoilers.'], + 'Expand videos': [false, 'Expand all images also expands videos (no autoplay).'], 'Expand from here': [false, 'Expand all images only from current position to thread end.'], 'Advance on contract': [false, 'Advance to next post when contracting an expanded image.'] }, @@ -349,7 +350,7 @@ doc = d.documentElement; g = { - VERSION: '1.7.2', + VERSION: '1.7.3', NAMESPACE: '4chan X.', boards: {} }; @@ -7967,7 +7968,7 @@ ImageExpand = { init: function() { - if (!Conf['Image Expansion']) { + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { return; } this.EAI = $.el('a', { @@ -7976,34 +7977,33 @@ title: 'Expand All Images', href: 'javascript:;' }); - $.on(this.EAI, 'click', this.cb.toggleAll); + $.on(this.EAI, 'click', ImageExpand.cb.toggleAll); Header.addShortcut(this.EAI, 3); - $.on(d, 'scroll visibilitychange', this.cb.playVideos); return Post.callbacks.push({ name: 'Image Expansion', cb: this.node }); }, node: function() { - var thumb; - if (!(this.file && (this.file.isImage || this.file.isVideo))) { + var clone, thumb, _ref, _ref1; + if (!(((_ref = this.file) != null ? _ref.isImage : void 0) || ((_ref1 = this.file) != null ? _ref1.isVideo : void 0))) { return; } thumb = this.file.thumb; $.on(thumb.parentNode, 'click', ImageExpand.cb.toggle); - if (this.isClone) { - if (this.file.isImage && this.file.isExpanding) { - ImageExpand.contract(this); - ImageExpand.expand(this); - return; - } - if (this.file.isExpanded && this.file.isVideo) { - ImageExpand.setupVideoControls(this); - return; - } - } - if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler)) { + if (this.isClone && $.hasClass(thumb, 'expanding')) { + ImageExpand.contract(this); return ImageExpand.expand(this); + } else if (this.isClone && this.file.isExpanded && this.file.isVideo) { + clone = this; + ImageExpand.setupVideoControls(clone); + if (!clone.origin.file.fullImage.paused) { + return $.queueTask(function() { + return ImageExpand.startVideo(clone); + }); + } + } else if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler) && (Conf['Expand videos'] || !this.file.isVideo)) { + return ImageExpand.expand(this, null, true); } }, cb: { @@ -8020,53 +8020,40 @@ return ImageExpand.toggle(post); }, toggleAll: function() { - var func; + var func, toggle; $.event('CloseMenu'); + toggle = function(post) { + var file; + file = post.file; + if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) { + return; + } + if (ImageExpand.on && (!Conf['Expand spoilers'] && file.isSpoiler || !Conf['Expand videos'] && file.isVideo || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0)) { + return; + } + return $.queueTask(func, post); + }; if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) { ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress'; ImageExpand.EAI.title = 'Contract All Images'; - func = ImageExpand.expand; + func = function(post) { + return ImageExpand.expand(post, null, true); + }; } else { ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand'; ImageExpand.EAI.title = 'Expand All Images'; func = ImageExpand.contract; } return g.posts.forEach(function(post) { - var file, _i, _len, _ref; - _ref = [post].concat(post.clones); + var _i, _len, _ref; + toggle(post); + _ref = post.clones; for (_i = 0, _len = _ref.length; _i < _len; _i++) { post = _ref[_i]; - file = post.file; - if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) { - return; - } - if (ImageExpand.on && (post.isHidden || !Conf['Expand spoilers'] && post.file.isSpoiler || !doc.contains(post.nodes.root) || Conf['Expand from here'] && Header.getTopOf(post.file.thumb) < 0)) { - return; - } - $.queueTask(func, post); + toggle(post); } }); }, - playVideos: function(e) { - var fullID, play, post, _i, _len, _ref, _ref1; - _ref = g.posts; - for (fullID in _ref) { - post = _ref[fullID]; - if (!(post.file && post.file.isVideo && post.file.isExpanded)) { - continue; - } - _ref1 = [post].concat(post.clones); - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - post = _ref1[_i]; - play = !d.hidden && !post.isHidden && doc.contains(post.nodes.root) && Header.isNodeVisible(post.nodes.root); - if (play) { - post.file.fullImage.play(); - } else { - post.file.fullImage.pause(); - } - } - } - }, setFitness: function() { return (this.checked ? $.addClass : $.rmClass)(doc, this.name.toLowerCase().replace(/\s+/g, '-')); } @@ -8074,7 +8061,7 @@ toggle: function(post) { var headRect, left, root, thumb, top, x, y, _ref; thumb = post.file.thumb; - if (!(post.file.isExpanded || post.file.isExpanding)) { + if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) { ImageExpand.expand(post); return; } @@ -8122,10 +8109,9 @@ } $.rmClass(post.nodes.root, 'expanded-image'); $.rmClass(post.file.thumb, 'expanding'); - delete post.file.isExpanding; return post.file.isExpanded = false; }, - expand: function(post, src) { + expand: function(post, src, disableAutoplay) { var el, isVideo, thumb, _ref; _ref = post.file, thumb = _ref.thumb, isVideo = _ref.isVideo; if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) { @@ -8148,42 +8134,49 @@ $.after(thumb, el); } return $.asap((function() { - return el.videoHeight || el.naturalHeight; + if (isVideo) { + return el.videoHeight; + } else { + return el.naturalHeight; + } }), function() { - return ImageExpand.completeExpand(post); + return ImageExpand.completeExpand(post, disableAutoplay); }); }, - completeExpand: function(post) { - var bottom, complete, thumb; + completeExpand: function(post, disableAutoplay) { + var bottom, thumb; thumb = post.file.thumb; if (!$.hasClass(thumb, 'expanding')) { return; } - delete post.file.isExpanding; - post.file.isExpanded = true; - complete = function() { - $.addClass(post.nodes.root, 'expanded-image'); - $.rmClass(post.file.thumb, 'expanding'); - if (post.file.isVideo) { - return ImageExpand.setupVideo(post); - } - }; if (!post.nodes.root.parentNode) { - complete(); + ImageExpand.completeExpand2(post); return; } - if (post.file.isVideo && !d.hidden && Header.isNodeVisible(post.nodes.root)) { - post.file.fullImage.play(); - } bottom = post.nodes.root.getBoundingClientRect().bottom; return $.queueTask(function() { - complete(); + ImageExpand.completeExpand2(post, disableAutoplay); if (!(bottom <= 0)) { return; } return window.scrollBy(0, post.nodes.root.getBoundingClientRect().bottom - bottom); }); }, + completeExpand2: function(post, disableAutoplay) { + var thumb; + thumb = post.file.thumb; + $.addClass(post.nodes.root, 'expanded-image'); + $.rmClass(post.file.thumb, 'expanding'); + post.file.isExpanded = true; + if (post.file.isVideo) { + ImageExpand.setupVideoControls(post); + post.file.fullImage.muted = !Conf['Allow Sound']; + post.file.fullImage.controls = Conf['Show Controls']; + if (Conf['Autoplay'] && !disableAutoplay) { + return ImageExpand.startVideo(post); + } + } + }, videoCB: { click: function(e) { if (this.paused && !this.controls) { @@ -8238,34 +8231,29 @@ } return $.add(file.text, file.videoControls); }, - setupVideo: function(post) { - var file, video; - ImageExpand.setupVideoControls(post); + startVideo: function(post) { + var controls, file, video; file = post.file; video = file.fullImage; - video.muted = !Conf['Allow Sound']; - video.controls = Conf['Show Controls']; - if (Conf['Autoplay']) { - video.controls = false; - video.play(); - if (Conf['Show Controls']) { - return $.asap((function() { - return (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || !file.isExpanded; - }), function() { - if (file.isExpanded) { - return video.controls = true; - } - }, 500); - } + controls = video.controls; + video.controls = false; + video.play(); + if (controls) { + return $.asap((function() { + return (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || !file.isExpanded; + }), function() { + if (file.isExpanded) { + return video.controls = true; + } + }, 500); } }, error: function() { var URL, post, src, timeoutID; post = Get.postFromNode(this); - post.file.isReady = false; $.rm(this); delete post.file.fullImage; - if (!(post.file.isExpanding || post.file.isExpanded)) { + if (!($.hasClass(post.file.thumb, 'expanding') || $.hasClass(post.nodes.root, 'expanded-image'))) { return; } ImageExpand.contract(post); @@ -8284,7 +8272,7 @@ } } timeoutID = setTimeout(ImageExpand.expand, 10000, post); - return $.ajax(post.file.URL, { + return $.ajax(this.src, { onloadend: function() { if (this.status !== 404) { return; @@ -8299,7 +8287,7 @@ menu: { init: function() { var conf, createSubEntry, el, name, subEntries, _ref; - if (!Conf['Image Expansion']) { + if (g.VIEW === 'catalog' || !Conf['Image Expansion']) { return; } el = $.el('span', { @@ -12985,7 +12973,7 @@ return; } $.event('CloseMenu'); - html = "
"; + html = "
"; Settings.overlay = overlay = $.el('div', { id: 'overlay' }); diff --git a/builds/updates.xml b/builds/updates.xml index 297567ff5..91f3bcbc5 100644 --- a/builds/updates.xml +++ b/builds/updates.xml @@ -1,7 +1,7 @@ - + diff --git a/latest.js b/latest.js index e0c83c476..e1f2e9b46 100755 --- a/latest.js +++ b/latest.js @@ -1 +1 @@ -postMessage({version:'1.7.2'},'*') +postMessage({version:'1.7.3'},'*') diff --git a/package.json b/package.json index e8555da3c..7ae878427 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "4chan-X", - "version": "1.7.2", + "version": "1.7.3", "description": "Cross-browser userscript for maximum lurking on 4chan.", "meta": { "name": "4chan X", diff --git a/src/General/Config.coffee b/src/General/Config.coffee index 7c6e29609..5276c4793 100755 --- a/src/General/Config.coffee +++ b/src/General/Config.coffee @@ -409,6 +409,10 @@ Config = true 'Expand all images along with spoilers.' ] + 'Expand videos': [ + false + 'Expand all images also expands videos (no autoplay).' + ] 'Expand from here': [ false 'Expand all images only from current position to thread end.' diff --git a/src/General/html/Settings/Settings.html b/src/General/html/Settings/Settings.html index 0180a448f..f0f00094e 100755 --- a/src/General/html/Settings/Settings.html +++ b/src/General/html/Settings/Settings.html @@ -6,10 +6,10 @@ Import |  Reset Settings |  - <%= meta.name %> | - #{g.VERSION} | - Issues | + <%= meta.name %> |  + #{g.VERSION} |  + Issues |  -
\ No newline at end of file +
diff --git a/src/Images/ImageExpand.coffee b/src/Images/ImageExpand.coffee index cd330fd75..41c13f52f 100755 --- a/src/Images/ImageExpand.coffee +++ b/src/Images/ImageExpand.coffee @@ -1,37 +1,36 @@ ImageExpand = init: -> - return if !Conf['Image Expansion'] + return if g.VIEW is 'catalog' or !Conf['Image Expansion'] @EAI = $.el 'a', className: 'expand-all-shortcut fa fa-expand' textContent: 'EAI' title: 'Expand All Images' href: 'javascript:;' - $.on @EAI, 'click', @cb.toggleAll + $.on @EAI, 'click', ImageExpand.cb.toggleAll Header.addShortcut @EAI, 3 - $.on d, 'scroll visibilitychange', @cb.playVideos Post.callbacks.push name: 'Image Expansion' cb: @node - node: -> - return unless @file and (@file.isImage or @file.isVideo) + return unless @file?.isImage or @file?.isVideo {thumb} = @file $.on thumb.parentNode, 'click', ImageExpand.cb.toggle - if @isClone - if @file.isImage and @file.isExpanding - # If we clone a post where the image is still loading, - # make it loading in the clone too. - ImageExpand.contract @ - ImageExpand.expand @ - return - if @file.isExpanded and @file.isVideo - ImageExpand.setupVideoControls @ - return - if ImageExpand.on and !@isHidden and (Conf['Expand spoilers'] or !@file.isSpoiler) + if @isClone and $.hasClass thumb, 'expanding' + # If we clone a post where the image is still loading, + # make it loading in the clone too. + ImageExpand.contract @ ImageExpand.expand @ - + else if @isClone and @file.isExpanded and @file.isVideo + clone = @ + ImageExpand.setupVideoControls clone + unless clone.origin.file.fullImage.paused + $.queueTask -> ImageExpand.startVideo clone + else if ImageExpand.on and !@isHidden and + (Conf['Expand spoilers'] or !@file.isSpoiler) and + (Conf['Expand videos'] or !@file.isVideo) + ImageExpand.expand @, null, true cb: toggle: (e) -> return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0 @@ -42,42 +41,36 @@ ImageExpand = toggleAll: -> $.event 'CloseMenu' + toggle = (post) -> + {file} = post + return unless file and (file.isImage or file.isVideo) and doc.contains post.nodes.root + if ImageExpand.on and + (!Conf['Expand spoilers'] and file.isSpoiler or + !Conf['Expand videos'] and file.isVideo or + Conf['Expand from here'] and Header.getTopOf(file.thumb) < 0) + return + $.queueTask func, post + if ImageExpand.on = $.hasClass ImageExpand.EAI, 'expand-all-shortcut' ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress' ImageExpand.EAI.title = 'Contract All Images' - func = ImageExpand.expand + func = (post) -> ImageExpand.expand post, null, true else ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand' ImageExpand.EAI.title = 'Expand All Images' func = ImageExpand.contract g.posts.forEach (post) -> - for post in [post].concat post.clones - {file} = post - return unless file and (file.isImage or file.isVideo) and doc.contains post.nodes.root - if ImageExpand.on and ( - post.isHidden or - !Conf['Expand spoilers'] and post.file.isSpoiler or - !doc.contains(post.nodes.root) or - Conf['Expand from here'] and Header.getTopOf(post.file.thumb) < 0) - return - $.queueTask func, post + toggle post + toggle post for post in post.clones return - playVideos: (e) -> - for fullID, post of g.posts - continue unless post.file and post.file.isVideo and post.file.isExpanded - for post in [post].concat post.clones - play = !d.hidden and !post.isHidden and doc.contains(post.nodes.root) and Header.isNodeVisible post.nodes.root - if play then post.file.fullImage.play() else post.file.fullImage.pause() - return - setFitness: -> (if @checked then $.addClass else $.rmClass) doc, @name.toLowerCase().replace /\s+/g, '-' toggle: (post) -> {thumb} = post.file - unless post.file.isExpanded or post.file.isExpanding + unless post.file.isExpanded or $.hasClass thumb, 'expanding' ImageExpand.expand post return @@ -117,10 +110,9 @@ ImageExpand = delete post.file.videoControls $.rmClass post.nodes.root, 'expanded-image' $.rmClass post.file.thumb, 'expanding' - delete post.file.isExpanding post.file.isExpanded = false - expand: (post, src) -> + expand: (post, src, disableAutoplay) -> # Do not expand images of hidden/filtered replies, or already expanded pictures. {thumb, isVideo} = post.file return if post.isHidden or post.file.isExpanded or $.hasClass thumb, 'expanding' @@ -135,33 +127,34 @@ ImageExpand = $.on el, 'error', ImageExpand.error el.src = src or post.file.URL $.after thumb, el unless el is thumb.nextSibling - $.asap (-> el.videoHeight or el.naturalHeight), -> - ImageExpand.completeExpand post + $.asap (-> if isVideo then el.videoHeight else el.naturalHeight), -> + ImageExpand.completeExpand post, disableAutoplay - completeExpand: (post) -> + completeExpand: (post, disableAutoplay) -> {thumb} = post.file return unless $.hasClass thumb, 'expanding' # contracted before the image loaded - delete post.file.isExpanding - post.file.isExpanded = true - - complete = -> - $.addClass post.nodes.root, 'expanded-image' - $.rmClass post.file.thumb, 'expanding' - ImageExpand.setupVideo post if post.file.isVideo - unless post.nodes.root.parentNode # Image might start/finish loading before the post is inserted. # Don't scroll when it's expanded in a QP for example. - complete() + ImageExpand.completeExpand2 post return - - post.file.fullImage.play() if post.file.isVideo and !d.hidden and Header.isNodeVisible post.nodes.root {bottom} = post.nodes.root.getBoundingClientRect() $.queueTask -> - complete() + ImageExpand.completeExpand2 post, disableAutoplay return unless bottom <= 0 window.scrollBy 0, post.nodes.root.getBoundingClientRect().bottom - bottom + completeExpand2: (post, disableAutoplay) -> + {thumb} = post.file + $.addClass post.nodes.root, 'expanded-image' + $.rmClass post.file.thumb, 'expanding' + post.file.isExpanded = true + if post.file.isVideo + ImageExpand.setupVideoControls post + post.file.fullImage.muted = !Conf['Allow Sound'] + post.file.fullImage.controls = Conf['Show Controls'] + ImageExpand.startVideo post if Conf['Autoplay'] and not disableAutoplay + videoCB: click: (e) -> if @paused and not @controls @@ -170,9 +163,9 @@ ImageExpand = # dragging to the left contracts the video mousedown: (e) -> @dataset.mousedown = 'true' if e.button is 0 - mouseup: (e) -> @dataset.mousedown = 'false' if e.button is 0 + mouseup: (e) -> @dataset.mousedown = 'false' if e.button is 0 mouseover: (e) -> @dataset.mousedown = 'false' - mouseout: (e) -> + mouseout: (e) -> if @dataset.mousedown is 'true' and e.clientX <= @getBoundingClientRect().left ImageExpand.contract (Get.postFromNode @) @@ -200,30 +193,26 @@ ImageExpand = $.add file.videoControls, [$.tn('\u00A0'), contract] $.add file.text, file.videoControls - setupVideo: (post) -> - ImageExpand.setupVideoControls post + startVideo: (post) -> {file} = post video = file.fullImage - video.muted = !Conf['Allow Sound'] - video.controls = Conf['Show Controls'] - if Conf['Autoplay'] - video.controls = false - video.play() - # Hacky workaround for Firefox forever-loading bug for very short videos - if Conf['Show Controls'] - $.asap (-> (video.readyState >= 3 and video.currentTime <= Math.max 0.1, (video.duration - 0.5)) or !file.isExpanded), -> - video.controls = true if file.isExpanded - , 500 + {controls} = video + video.controls = false + video.play() + # Hacky workaround for Firefox forever-loading bug for very short videos + if controls + $.asap (-> (video.readyState >= 3 and video.currentTime <= Math.max 0.1, (video.duration - 0.5)) or !file.isExpanded), -> + video.controls = true if file.isExpanded + , 500 error: -> post = Get.postFromNode @ - post.file.isReady = false $.rm @ delete post.file.fullImage # Images can error: # - before the image started loading. # - after the image started loading. - unless post.file.isExpanding or post.file.isExpanded + unless $.hasClass(post.file.thumb, 'expanding') or $.hasClass post.nodes.root, 'expanded-image' # Don't try to re-expend if it was already contracted. return ImageExpand.contract post @@ -241,7 +230,7 @@ ImageExpand = timeoutID = setTimeout ImageExpand.expand, 10000, post <% if (type === 'crx') { %> - $.ajax post.file.URL, + $.ajax @src, onloadend: -> return if @status isnt 404 clearTimeout timeoutID @@ -264,7 +253,7 @@ ImageExpand = menu: init: -> - return if !Conf['Image Expansion'] + return if g.VIEW is 'catalog' or !Conf['Image Expansion'] el = $.el 'span', textContent: 'Image Expansion'