134 lines
4.5 KiB
CoffeeScript
134 lines
4.5 KiB
CoffeeScript
QR.oekaki =
|
|
init: ->
|
|
return unless Conf['Quick Reply'] and Conf['Edit Link']
|
|
|
|
a = $.el 'a',
|
|
className: 'edit-link'
|
|
href: 'javascript:;'
|
|
textContent: 'Edit image'
|
|
$.on a, 'click', @editFile
|
|
|
|
Menu.menu.addEntry
|
|
el: a
|
|
order: 95
|
|
open: ({file}) ->
|
|
!!file and (file.isImage or file.isVideo)
|
|
|
|
editFile: ->
|
|
return unless QR.postingIsEnabled
|
|
QR.quote.call @
|
|
post = Get.postFromNode @
|
|
{isVideo} = post.file
|
|
currentTime = post.file.fullImage?.currentTime or 0
|
|
CrossOrigin.file post.file.url, (blob) ->
|
|
if !blob
|
|
QR.error "Can't load file."
|
|
else if isVideo
|
|
video = $.el 'video'
|
|
$.on video, 'loadedmetadata', ->
|
|
$.on video, 'seeked', ->
|
|
canvas = $.el 'canvas',
|
|
width: video.videoWidth
|
|
height: video.videoHeight
|
|
canvas.getContext('2d').drawImage(video, 0, 0)
|
|
canvas.toBlob (snapshot) ->
|
|
snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'
|
|
QR.handleFiles [snapshot]
|
|
QR.oekaki.edit()
|
|
video.currentTime = currentTime
|
|
video.src = URL.createObjectURL blob
|
|
else
|
|
blob.name = post.file.name
|
|
QR.handleFiles [blob]
|
|
QR.oekaki.edit()
|
|
|
|
setup: ->
|
|
$.global ->
|
|
{FCX} = window
|
|
FCX.oekakiCB = ->
|
|
window.Tegaki.flatten().toBlob (file) ->
|
|
source = "oekaki-#{Date.now()}"
|
|
FCX.oekakiLatest = source
|
|
document.dispatchEvent new CustomEvent 'QRSetFile',
|
|
bubbles: true
|
|
detail: {file, name: FCX.oekakiName, source}
|
|
if window.Tegaki
|
|
document.querySelector('#qr .oekaki').hidden = false
|
|
|
|
load: (cb) ->
|
|
if $ 'script[src^="//s.4cdn.org/js/painter"]', d.head
|
|
cb()
|
|
else
|
|
style = $.el 'link',
|
|
rel: 'stylesheet'
|
|
href: "//s.4cdn.org/css/painter.#{Date.now()}.css"
|
|
script = $.el 'script',
|
|
src: "//s.4cdn.org/js/painter.min.#{Date.now()}.js"
|
|
n = 0
|
|
onload = ->
|
|
cb() if ++n is 2
|
|
$.on style, 'load', onload
|
|
$.on script, 'load', onload
|
|
$.add d.head, [style, script]
|
|
|
|
draw: ->
|
|
$.global ->
|
|
{Tegaki, FCX} = window
|
|
Tegaki.destroy() if Tegaki.bg
|
|
FCX.oekakiName = 'tegaki.png'
|
|
Tegaki.open
|
|
onDone: FCX.oekakiCB
|
|
onCancel: -> Tegaki.bgColor = '#ffffff'
|
|
width: +document.querySelector('#qr [name=oekaki-width]').value
|
|
height: +document.querySelector('#qr [name=oekaki-height]').value
|
|
bgColor:
|
|
if document.querySelector('#qr [name=oekaki-bg]').checked
|
|
document.querySelector('#qr [name=oekaki-bgcolor]').value
|
|
else
|
|
'transparent'
|
|
|
|
button: ->
|
|
if QR.selected.file
|
|
QR.oekaki.edit()
|
|
else
|
|
QR.oekaki.toggle()
|
|
|
|
edit: ->
|
|
QR.oekaki.load -> $.global ->
|
|
{Tegaki, FCX} = window
|
|
name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'
|
|
{source} = document.getElementById('file-n-submit').dataset
|
|
error = (content) ->
|
|
document.dispatchEvent new CustomEvent 'CreateNotification',
|
|
bubbles: true
|
|
detail: {type: 'warning', content, lifetime: 20}
|
|
cb = (e) ->
|
|
document.removeEventListener 'QRFile', cb, false
|
|
return error 'No file to edit.' unless e.detail
|
|
return error 'Not an image.' unless /^(image|video)\//.test e.detail.type
|
|
isVideo = /^video\//.test e.detail.type
|
|
file = document.createElement(if isVideo then 'video' else 'img')
|
|
file.addEventListener 'error', -> error 'Could not open file.', false
|
|
file.addEventListener (if isVideo then 'loadeddata' else 'load'), ->
|
|
Tegaki.destroy() if Tegaki.bg
|
|
FCX.oekakiName = name
|
|
Tegaki.open
|
|
onDone: FCX.oekakiCB
|
|
onCancel: -> Tegaki.bgColor = '#ffffff'
|
|
width: file.naturalWidth or file.videoWidth
|
|
height: file.naturalHeight or file.videoHeight
|
|
bgColor: 'transparent'
|
|
Tegaki.activeCtx.drawImage file, 0, 0
|
|
, false
|
|
file.src = URL.createObjectURL e.detail
|
|
if Tegaki.bg and Tegaki.onDoneCb is FCX.oekakiCB and source is FCX.oekakiLatest
|
|
FCX.oekakiName = name
|
|
Tegaki.resume()
|
|
else
|
|
document.addEventListener 'QRFile', cb, false
|
|
document.dispatchEvent new CustomEvent 'QRGetFile', {bubbles: true}
|
|
|
|
toggle: ->
|
|
QR.oekaki.load ->
|
|
QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden
|