Merge branch 'v3'

Conflicts:
	CHANGELOG.md
	builds/appchan-x.user.js
	builds/crx/script.js
	src/Images/ImageExpand.coffee
	src/Images/ImageHover.coffee
This commit is contained in:
Zixaphir 2014-04-04 20:28:21 -07:00
commit 453ebe7e74
15 changed files with 165 additions and 227 deletions

View File

@ -1,3 +1,6 @@
**MayhemYDG**:
- Some changes to webm code.
### v2.9.12 ### v2.9.12
*2014-04-04* *2014-04-04*
@ -21,6 +24,9 @@
### v2.9.10 ### v2.9.10
*2014-04-02* *2014-04-02*
**duckness**:
- Merge changes from Mayhem fork
**MayhemYDG**: **MayhemYDG**:
- Fix captcha submission: - Fix captcha submission:
Captchas were reloaded the instant a post was submitted to 4chan. Unfortunately, a recent change to reCAPTCHA made it so reloading captchas invalidates the ones that loaded but not yet used. This is now fixed by only unloading the captcha, and only load new ones after the post is submitted.<br> Captchas were reloaded the instant a post was submitted to 4chan. Unfortunately, a recent change to reCAPTCHA made it so reloading captchas invalidates the ones that loaded but not yet used. This is now fixed by only unloading the captcha, and only load new ones after the post is submitted.<br>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,15 +28,15 @@
}, },
"devDependencies": { "devDependencies": {
"font-awesome": "~4.0.3", "font-awesome": "~4.0.3",
"grunt": "~0.4.2", "grunt": "~0.4.4",
"grunt-bump": "~0.0.13", "grunt-bump": "~0.0.13",
"grunt-concurrent": "~0.5.0", "grunt-concurrent": "~0.5.0",
"grunt-contrib-clean": "~0.5.0", "grunt-contrib-clean": "~0.5.0",
"grunt-contrib-coffee": "~0.10.0", "grunt-contrib-coffee": "~0.10.1",
"grunt-contrib-compress": "~0.7.0", "grunt-contrib-compress": "~0.7.0",
"grunt-contrib-concat": "~0.3.0", "grunt-contrib-concat": "~0.4.0",
"grunt-contrib-copy": "~0.5.0", "grunt-contrib-copy": "~0.5.0",
"grunt-contrib-watch": "~0.6.0", "grunt-contrib-watch": "~0.6.1",
"grunt-shell": "~0.6.4", "grunt-shell": "~0.6.4",
"load-grunt-tasks": "~0.4.0" "load-grunt-tasks": "~0.4.0"
}, },

View File

@ -149,7 +149,8 @@ Filter =
return post.file.name return post.file.name
false false
dimensions: (post) -> dimensions: (post) ->
if post.file and post.file.isImage {file} = post
if file and (file.isImage or file.isVideo)
return post.file.dimensions return post.file.dimensions
false false
filesize: (post) -> filesize: (post) ->

View File

@ -7,8 +7,9 @@ Build =
# OPs have a +10 characters threshold. # OPs have a +10 characters threshold.
# The file extension is not taken into account. # The file extension is not taken into account.
threshold = if isReply then 30 else 40 threshold = if isReply then 30 else 40
if filename.length - 4 > threshold ext = filename.match(/\.[^.]+$/)[0]
"#{filename[...threshold - 5]}(...).#{filename[-3..]}" if filename.length - ext.length > threshold
"#{filename[...threshold - 5]}(...)#{ext}"
else else
filename filename
thumbRotate: do -> thumbRotate: do ->

View File

@ -361,6 +361,7 @@ Settings =
sizeInBytes: 276 * 1024 sizeInBytes: 276 * 1024
dimensions: '1280x720' dimensions: '1280x720'
isImage: true isImage: true
isVideo: false
isSpoiler: true isSpoiler: true
funk = FileInfo.createFunc @value funk = FileInfo.createFunc @value
@nextElementSibling.innerHTML = funk FileInfo, data @nextElementSibling.innerHTML = funk FileInfo, data

View File

@ -925,7 +925,7 @@ nav a,
.move { .move {
cursor: pointer; cursor: pointer;
} }
.ihover { #ihover {
position: fixed; position: fixed;
max-height: 94vh; max-height: 94vh;
max-width: 75vw; max-width: 75vw;

View File

@ -108,7 +108,7 @@ div.center:not(.ad-cnt) {
/* fixed, z-index */ /* fixed, z-index */
#overlay, #overlay,
#fourchanx-settings, #fourchanx-settings,
#qp, .ihover, #qp, #ihover,
#navlinks, .fixed #header-bar, #navlinks, .fixed #header-bar,
:root.float #updater, :root.float #updater,
:root.float #thread-stats, :root.float #thread-stats,
@ -124,7 +124,7 @@ div.center:not(.ad-cnt) {
#notifications { #notifications {
z-index: 70; z-index: 70;
} }
#qp, .ihover { #qp, #ihover {
z-index: 60; z-index: 60;
} }
#menu { #menu {
@ -840,7 +840,7 @@ span.hide-announcement {
:root.gecko.fit-width .full-image { :root.gecko.fit-width .full-image {
width: 100%; width: 100%;
} }
.ihover { #ihover {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
max-height: 100%; max-height: 100%;

View File

@ -116,7 +116,7 @@ class Post
parseFile: (that) -> parseFile: (that) ->
return unless (fileEl = $ '.file', @nodes.post) and thumb = $ 'img[data-md5]', fileEl return unless (fileEl = $ '.file', @nodes.post) and thumb = $ 'img[data-md5]', fileEl
# Supports JPG/PNG/GIF/PDF. # Supports JPG/PNG/GIF/WEBM/PDF.
# Flash files are not supported. # Flash files are not supported.
anchor = thumb.parentNode anchor = thumb.parentNode
fileText = fileEl.firstElementChild fileText = fileEl.firstElementChild

View File

@ -32,4 +32,3 @@ AutoGIF =
else else
thumb.src = URL thumb.src = URL
gif.src = URL gif.src = URL

View File

@ -17,7 +17,7 @@ ImageExpand =
cb: @node cb: @node
node: -> node: ->
return unless @file?.isImage or @file?.isVideo return unless @file and (@file.isImage or @file.isVideo)
{thumb} = @file {thumb} = @file
$.on thumb.parentNode, 'click', ImageExpand.cb.toggle $.on thumb.parentNode, 'click', ImageExpand.cb.toggle
if @isClone and $.hasClass thumb, 'expanding' if @isClone and $.hasClass thumb, 'expanding'
@ -49,7 +49,7 @@ ImageExpand =
for post in [post].concat post.clones for post in [post].concat post.clones
{file} = post {file} = post
return unless file and (file.isImage or file.isVideo) and doc.contains post.nodes.root return unless file and (file.isImage or file.isVideo) and doc.contains post.nodes.root
if ImageExpand.on and if ImageExpand.on and !post.isHidden and
(!Conf['Expand spoilers'] and file.isSpoiler or (!Conf['Expand spoilers'] and file.isSpoiler or
Conf['Expand from here'] and Header.getTopOf(file.thumb) < 0) Conf['Expand from here'] and Header.getTopOf(file.thumb) < 0)
return return
@ -90,10 +90,10 @@ ImageExpand =
ImageExpand.contract post ImageExpand.contract post
contract: (post) -> contract: (post) ->
post.file.fullImage?.pause() if post.file.isVideo
$.rmClass post.nodes.root, 'expanded-image' $.rmClass post.nodes.root, 'expanded-image'
$.rmClass post.file.thumb, 'expanding' $.rmClass post.file.thumb, 'expanding'
post.file.isExpanded = false post.file.isExpanded = false
post.file.fullImage.pause() if post.file.isVideo
post.file.videoControls?.map($.rm) post.file.videoControls?.map($.rm)
delete post.file.videoControls delete post.file.videoControls
@ -102,44 +102,41 @@ ImageExpand =
{thumb, isVideo} = post.file {thumb, isVideo} = post.file
return if post.isHidden or post.file.isExpanded or $.hasClass thumb, 'expanding' return if post.isHidden or post.file.isExpanded or $.hasClass thumb, 'expanding'
$.addClass thumb, 'expanding' $.addClass thumb, 'expanding'
naturalHeight = if isVideo then 'videoHeight' else 'naturalHeight' if post.file.fullImage
if img = post.file.fullImage
# Expand already-loaded/ing picture. # Expand already-loaded/ing picture.
$.addClass img, 'full-image' $.asap (-> post.file.isVideo or post.file.fullImage.naturalHeight), ->
img.controls = (img.parentNode isnt thumb.parentNode)
$.asap (-> img[naturalHeight]), ->
ImageExpand.completeExpand post ImageExpand.completeExpand post
return return
post.file.fullImage = img = $.el (if isVideo then 'video' else 'img'), file =
className: 'full-image' $.el (if post.file.isImage then 'img' else 'video'),
src: src or post.file.URL className: 'full-image'
src: src or post.file.URL
post.file.fullImage = file
if isVideo if isVideo
img.loop = true file.loop = true
img.controls = Conf['Show Controls'] file.controls = Conf['Show Controls']
$.on img, 'error', ImageExpand.error $.on file, 'error', ImageExpand.error
$.asap (-> post.file.fullImage[naturalHeight]), -> $.asap (-> post.file.isVideo or post.file.fullImage.naturalHeight), ->
if isVideo if isVideo
# XXX Firefox doesn't seem to size videos correctly? # XXX Firefox doesn't seem to size videos correctly?
img.style.maxHeight = img[naturalHeight] + "px" img.style.maxHeight = img[naturalHeight] + "px"
img.style.maxWidth = img['videoWidth'] + "px" img.style.maxWidth = img['videoWidth'] + "px"
ImageExpand.completeExpand post ImageExpand.completeExpand post
$.after (if img.controls then thumb.parentNode else thumb), img $.after (if file.controls then thumb.parentNode else thumb), file
completeExpand: (post) -> completeExpand: (post) ->
{thumb} = post.file {thumb} = post.file
return unless $.hasClass thumb, 'expanding' # contracted before the image loaded return unless $.hasClass thumb, 'expanding' # contracted before the image loaded
post.file.isExpanded = true post.file.isExpanded = true
ImageExpand.setupVideo post if post.file.isVideo ImageExpand.setupVideo post if post.file.isVideo
$.addClass post.nodes.root, 'expanded-image'
$.rmClass post.file.thumb, 'expanding'
unless post.nodes.root.parentNode unless post.nodes.root.parentNode
# Image might start/finish loading before the post is inserted. # Image might start/finish loading before the post is inserted.
# Don't scroll when it's expanded in a QP for example. # Don't scroll when it's expanded in a QP for example.
$.addClass post.nodes.root, 'expanded-image'
$.rmClass post.file.thumb, 'expanding'
return return
{bottom} = post.nodes.root.getBoundingClientRect() {bottom} = post.nodes.root.getBoundingClientRect()
$.queueTask -> $.queueTask ->
$.addClass post.nodes.root, 'expanded-image'
$.rmClass post.file.thumb, 'expanding'
return unless bottom <= 0 return unless bottom <= 0
window.scrollBy 0, post.nodes.root.getBoundingClientRect().bottom - bottom window.scrollBy 0, post.nodes.root.getBoundingClientRect().bottom - bottom
@ -159,9 +156,9 @@ ImageExpand =
# drag left to contract # drag left to contract
file.mousedown = false file.mousedown = false
$.on video, 'mousedown', (e) -> file.mousedown = true if e.button is 0 $.on video, 'mousedown', (e) -> file.mousedown = true if e.button is 0
$.on video, 'mouseup', (e) -> file.mousedown = false if e.button is 0 $.on video, 'mouseup', (e) -> file.mousedown = false if e.button is 0
$.on video, 'mouseover', (e) -> file.mousedown = false $.on video, 'mouseover', (e) -> file.mousedown = false
$.on video, 'mouseout', (e) -> $.on video, 'mouseout', (e) ->
if file.mousedown and e.clientX <= video.getBoundingClientRect().left if file.mousedown and e.clientX <= video.getBoundingClientRect().left
ImageExpand.contract post ImageExpand.contract post
if Conf['Autoplay'] if Conf['Autoplay']

View File

@ -9,37 +9,36 @@ ImageHover =
name: 'Image Hover' name: 'Image Hover'
cb: @catalogNode cb: @catalogNode
node: -> node: ->
return unless @file?.isImage or @file?.isVideo return unless @file and (@file.isImage or @file.isVideo)
$.on @file.thumb, 'mouseover', ImageHover.mouseover $.on @file.thumb, 'mouseover', ImageHover.mouseover
catalogNode: -> catalogNode: ->
return unless @thread.OP.file?.isImage return unless @thread.OP.file and (@thread.OP.file.isImage or @thread.OP.file.isVideo)
$.on @nodes.thumb, 'mouseover', ImageHover.mouseover $.on @nodes.thumb, 'mouseover', ImageHover.mouseover
mouseover: (e) -> mouseover: (e) ->
post = if $.hasClass @, 'thumb' post = if $.hasClass @, 'thumb'
g.posts[@parentNode.dataset.fullID] g.posts[@parentNode.dataset.fullID]
else else
Get.postFromNode @ Get.postFromNode @
{isVideo} = post.file el = if post.file.isImage
el = $.el (if isVideo then 'video' else 'img'), $.el 'img',
className: 'ihover' id: 'ihover'
src: post.file.URL src: post.file.URL
{thumb} = post.file else
$.el 'video',
controls: false
id: 'ihover'
src: post.file.URL
autoplay: Conf['Autoplay']
muted: !Conf['Allow Sound']
loop: true
$.add Header.hover, el $.add Header.hover, el
el.dataset.fullID = post.fullID el.dataset.fullID = post.fullID
if isVideo
el.loop = true
el.controls = false
el.muted = not Conf['Allow Sound']
el.play() if Conf['Autoplay']
naturalHeight = if post.file.isVideo then 'videoHeight' else 'naturalHeight'
UI.hover UI.hover
root: @ root: @
el: el el: el
latestEvent: e latestEvent: e
endEvents: 'mouseout click' endEvents: 'mouseout click'
asapTest: -> el[naturalHeight] asapTest: -> post.file.isVideo or el.naturalHeight
cb: ->
el.pause() if isVideo
$.on el, 'error', ImageHover.error $.on el, 'error', ImageHover.error
error: -> error: ->
return unless doc.contains @ return unless doc.contains @

View File

@ -47,4 +47,4 @@ FileInfo =
B: -> FileInfo.convertUnit @file.sizeInBytes, 'B' B: -> FileInfo.convertUnit @file.sizeInBytes, 'B'
K: -> FileInfo.convertUnit @file.sizeInBytes, 'KB' K: -> FileInfo.convertUnit @file.sizeInBytes, 'KB'
M: -> FileInfo.convertUnit @file.sizeInBytes, 'MB' M: -> FileInfo.convertUnit @file.sizeInBytes, 'MB'
r: -> if @file.isImage or @file.isVideo then @file.dimensions else 'PDF' r: -> @file.dimensions or 'PDF'

View File

@ -1,7 +1,4 @@
QR = QR =
# Add empty mimeType to avoid errors with URLs selected in Window's file dialog.
mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/x-shockwave-flash', 'video/webm', '']
init: -> init: ->
@db = new DataBoard 'yourPosts' @db = new DataBoard 'yourPosts'
@posts = [] @posts = []
@ -386,23 +383,15 @@ QR =
if file.size > max if file.size > max
QR.error "#{file.name}: File too large (file: #{$.bytesToString file.size}, max: #{$.bytesToString max})." QR.error "#{file.name}: File too large (file: #{$.bytesToString file.size}, max: #{$.bytesToString max})."
return return
else unless file.type in QR.mimeTypes
unless /^text/.test file.type
QR.error "#{file.name}: Unsupported file type."
return
if isSingle
post = QR.selected
else if (post = QR.posts[QR.posts.length - 1]).com
post = new QR.post()
post.pasteText file
return
if isSingle if isSingle
post = QR.selected post = QR.selected
else if (post = QR.posts[QR.posts.length - 1]).file else if (post = QR.posts[QR.posts.length - 1]).file
post = new QR.post() post = new QR.post()
post.setFile file if /^text/.test file.type
post.pasteText file
openFileInput: (e) -> else
post.setFile file
openFileInput: ->
e.stopPropagation() e.stopPropagation()
if e.shiftKey and e.type is 'click' if e.shiftKey and e.type is 'click'
return QR.selected.rmFile() return QR.selected.rmFile()
@ -412,7 +401,6 @@ QR =
return return
return if e.target.nodeName is 'INPUT' or (e.keyCode and e.keyCode not in [32, 13]) or e.ctrlKey return if e.target.nodeName is 'INPUT' or (e.keyCode and e.keyCode not in [32, 13]) or e.ctrlKey
e.preventDefault() e.preventDefault()
QR.nodes.fileInput.click()
generatePostableThreadsList: -> generatePostableThreadsList: ->
return unless QR.nodes return unless QR.nodes