mirror of
https://github.com/LalleSX/4chan-XZ.git
synced 2025-10-07 07:22:37 +02:00
types and optimizeation
This commit is contained in:
parent
cdc878e1f2
commit
d8d36ef5dc
@ -35,7 +35,7 @@ const Get = {
|
|||||||
const index = root.dataset.clone
|
const index = root.dataset.clone
|
||||||
if (index) { return post.clones[+index] } else { return post }
|
if (index) { return post.clones[+index] } else { return post }
|
||||||
},
|
},
|
||||||
postFromNode(root) {
|
postFromNode(root): Post {
|
||||||
return Get.postFromRoot($.x(`ancestor-or-self::${g.SITE.xpath.postContainer}[1]`, root))
|
return Get.postFromRoot($.x(`ancestor-or-self::${g.SITE.xpath.postContainer}[1]`, root))
|
||||||
},
|
},
|
||||||
postDataFromLink(link) {
|
postDataFromLink(link) {
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import CaptchaT from "./Captcha.t"
|
|||||||
import QR from "./QR"
|
import QR from "./QR"
|
||||||
|
|
||||||
const Captcha = {
|
const Captcha = {
|
||||||
Cache: {
|
cache: {
|
||||||
init() {
|
init() {
|
||||||
$.on(d, 'SaveCaptcha', e => {
|
$.on(d, 'SaveCaptcha', e => {
|
||||||
return this.saveAPI(e.detail)
|
return this.saveAPI(e.detail)
|
||||||
@ -159,7 +159,8 @@ const Captcha = {
|
|||||||
updateCount() {
|
updateCount() {
|
||||||
return $.event('CaptchaCount', this.captchas.length)
|
return $.event('CaptchaCount', this.captchas.length)
|
||||||
}
|
}
|
||||||
}, Replace: CaptchaReplace, t: CaptchaT, v2: {
|
},
|
||||||
|
Replace: CaptchaReplace, t: CaptchaT, v2: {
|
||||||
lifetime: 2 * MINUTE,
|
lifetime: 2 * MINUTE,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import meta from '../../package.json'
|
import meta from '../../package.json'
|
||||||
import Callbacks from '../classes/Callbacks'
|
import Callbacks from '../classes/Callbacks'
|
||||||
import Notice from '../classes/Notice'
|
import Notice from '../classes/Notice'
|
||||||
|
import Thread from '../classes/Thread'
|
||||||
import BoardConfig from '../General/BoardConfig'
|
import BoardConfig from '../General/BoardConfig'
|
||||||
import Get from '../General/Get'
|
import Get from '../General/Get'
|
||||||
import Header from '../General/Header'
|
import Header from '../General/Header'
|
||||||
@ -75,7 +76,28 @@ const QR = {
|
|||||||
|
|
||||||
return Header.addShortcut('qr', sc, 540)
|
return Header.addShortcut('qr', sc, 540)
|
||||||
},
|
},
|
||||||
|
captcha: null,
|
||||||
|
postingIsEnabled: false,
|
||||||
|
nodes: null,
|
||||||
|
posts: null,
|
||||||
|
shortcut: null,
|
||||||
|
link: '',
|
||||||
|
min_width: 0,
|
||||||
|
min_height: 0,
|
||||||
|
max_width: 0,
|
||||||
|
max_height: 0,
|
||||||
|
max_size: 0,
|
||||||
|
max_size_video: null,
|
||||||
|
max_comment: null,
|
||||||
|
max_width_video: null,
|
||||||
|
max_height_video: null,
|
||||||
|
max_duration_video: null,
|
||||||
|
forcedAnon: null,
|
||||||
|
spoiler: null,
|
||||||
|
hasFocus: false,
|
||||||
|
req: null,
|
||||||
|
currentCaptcha: null,
|
||||||
|
errorCount: 0,
|
||||||
initReady() {
|
initReady() {
|
||||||
let origToggle
|
let origToggle
|
||||||
const captchaVersion = $('#g-recaptcha, #captcha-forced-noscript') ? 'v2' : 't'
|
const captchaVersion = $('#g-recaptcha, #captcha-forced-noscript') ? 'v2' : 't'
|
||||||
@ -378,7 +400,7 @@ const QR = {
|
|||||||
let text = post.board.ID === g.BOARD.ID ? `>>${post}\n` : `>>>/${post.board}/${post}\n`
|
let text = post.board.ID === g.BOARD.ID ? `>>${post}\n` : `>>>/${post.board}/${post}\n`
|
||||||
for (let i = 0, end = sel.rangeCount, asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) {
|
for (let i = 0, end = sel.rangeCount, asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) {
|
||||||
try {
|
try {
|
||||||
var insideCode, node
|
let insideCode, node
|
||||||
range = sel.getRangeAt(i)
|
range = sel.getRangeAt(i)
|
||||||
// Trim range to be fully inside post
|
// Trim range to be fully inside post
|
||||||
if (range.compareBoundaryPoints(Range.START_TO_START, postRange) < 0) {
|
if (range.compareBoundaryPoints(Range.START_TO_START, postRange) < 0) {
|
||||||
@ -407,7 +429,7 @@ const QR = {
|
|||||||
for (node of $$('br', frag)) {
|
for (node of $$('br', frag)) {
|
||||||
if (node !== frag.lastChild) { $.replace(node, $.tn('\n>')) }
|
if (node !== frag.lastChild) { $.replace(node, $.tn('\n>')) }
|
||||||
}
|
}
|
||||||
g.SITE.insertTags?.(frag)
|
g.SITE.insertTags?.()
|
||||||
for (node of $$('.linkify[data-original]', frag)) {
|
for (node of $$('.linkify[data-original]', frag)) {
|
||||||
$.replace(node, $.tn(node.dataset.original))
|
$.replace(node, $.tn(node.dataset.original))
|
||||||
}
|
}
|
||||||
@ -416,7 +438,7 @@ const QR = {
|
|||||||
$.rm(node)
|
$.rm(node)
|
||||||
}
|
}
|
||||||
text += `>${frag.textContent.trim()}\n`
|
text += `>${frag.textContent.trim()}\n`
|
||||||
} catch (error) { }
|
} catch (error) { /* empty */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
QR.openPost()
|
QR.openPost()
|
||||||
@ -456,7 +478,7 @@ const QR = {
|
|||||||
const file = QR.selected?.file
|
const file = QR.selected?.file
|
||||||
if (!file || !/^(image|video)\//.test(file.type)) { return }
|
if (!file || !/^(image|video)\//.test(file.type)) { return }
|
||||||
const isVideo = /^video\//.test(file)
|
const isVideo = /^video\//.test(file)
|
||||||
const el = $.el((isVideo ? 'video' : 'img'))
|
const el = $.el((isVideo ? 'video' : 'img'), { src: '' })
|
||||||
$.on(el, 'error', () => QR.openError())
|
$.on(el, 'error', () => QR.openError())
|
||||||
$.on(el, (isVideo ? 'loadeddata' : 'load'), function () {
|
$.on(el, (isVideo ? 'loadeddata' : 'load'), function () {
|
||||||
e.target.getContext('2d').drawImage(el, 0, 0)
|
e.target.getContext('2d').drawImage(el, 0, 0)
|
||||||
@ -467,12 +489,12 @@ const QR = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
openError() {
|
openError() {
|
||||||
const div = $.el('div')
|
const div = $.el('div', { className: 'error' })
|
||||||
$.extend(div, {
|
$.extend(div, {
|
||||||
innerHTML:
|
innerHTML:
|
||||||
'Could not open file. [<a href="' + E(meta.faq) + '#error-reading-metadata" target="_blank">More info</a>]'
|
'Could not open file. [<a href="' + E(meta.faq) + '#error-reading-metadata" target="_blank">More info</a>]'
|
||||||
})
|
})
|
||||||
return QR.error(div)
|
return QR.error(div, 5000)
|
||||||
},
|
},
|
||||||
|
|
||||||
setFile(e) {
|
setFile(e) {
|
||||||
@ -508,9 +530,9 @@ const QR = {
|
|||||||
let file = null
|
let file = null
|
||||||
let score = -1
|
let score = -1
|
||||||
for (const item of e.clipboardData.items) {
|
for (const item of e.clipboardData.items) {
|
||||||
var file2
|
let file2
|
||||||
if ((item.kind === 'file') && (file2 = item.getAsFile())) {
|
if ((item.kind === 'file') && (file2 = item.getAsFile())) {
|
||||||
const score2 = (2 * (file2.size <= QR.max_size)) + (file2.type === 'image/png')
|
const score2 = (file2.size * 100) / (d.body.clientWidth * d.body.clientHeight)
|
||||||
if (score2 > score) {
|
if (score2 > score) {
|
||||||
file = file2
|
file = file2
|
||||||
score = score2
|
score = score2
|
||||||
@ -533,7 +555,7 @@ const QR = {
|
|||||||
const images = $$('img', pasteArea)
|
const images = $$('img', pasteArea)
|
||||||
$.rmAll(pasteArea)
|
$.rmAll(pasteArea)
|
||||||
for (const img of images) {
|
for (const img of images) {
|
||||||
var m
|
let m
|
||||||
const { src } = img
|
const { src } = img
|
||||||
if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) {
|
if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) {
|
||||||
const bstr = atob(m[3])
|
const bstr = atob(m[3])
|
||||||
@ -561,10 +583,10 @@ const QR = {
|
|||||||
if (blob && !/^text\//.test(blob.type)) {
|
if (blob && !/^text\//.test(blob.type)) {
|
||||||
return QR.handleFiles([blob])
|
return QR.handleFiles([blob])
|
||||||
} else {
|
} else {
|
||||||
return QR.error("Can't load file.")
|
return QR.error("Can't load file.", 5000)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
}, urlDefault, true)
|
||||||
},
|
},
|
||||||
|
|
||||||
handleFiles(files) {
|
handleFiles(files) {
|
||||||
@ -727,7 +749,7 @@ const QR = {
|
|||||||
let i = 0
|
let i = 0
|
||||||
const save = function () { return QR.selected.save(this) }
|
const save = function () { return QR.selected.save(this) }
|
||||||
while ((name = items[i++])) {
|
while ((name = items[i++])) {
|
||||||
var node
|
let node
|
||||||
if (!(node = nodes[name])) { continue }
|
if (!(node = nodes[name])) { continue }
|
||||||
event = node.nodeName === 'SELECT' ? 'change' : 'input'
|
event = node.nodeName === 'SELECT' ? 'change' : 'input'
|
||||||
$.on(nodes[name], event, save)
|
$.on(nodes[name], event, save)
|
||||||
@ -793,7 +815,7 @@ const QR = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
submit(e) {
|
submit(e?: KeyboardEvent) {
|
||||||
let captcha, err, filetag
|
let captcha, err, filetag
|
||||||
e?.preventDefault()
|
e?.preventDefault()
|
||||||
const force = e?.shiftKey
|
const force = e?.shiftKey
|
||||||
@ -803,7 +825,7 @@ const QR = {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$.forceSync('cooldowns')
|
$.forceSync('cooldowns', QR.cooldown.sync)
|
||||||
if (QR.cooldown.seconds) {
|
if (QR.cooldown.seconds) {
|
||||||
if (force) {
|
if (force) {
|
||||||
QR.cooldown.clear()
|
QR.cooldown.clear()
|
||||||
@ -859,7 +881,7 @@ const QR = {
|
|||||||
// stop auto-posting
|
// stop auto-posting
|
||||||
QR.cooldown.auto = false
|
QR.cooldown.auto = false
|
||||||
QR.status()
|
QR.status()
|
||||||
QR.error(err)
|
QR.error(err, 1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -905,6 +927,7 @@ const QR = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let cb = function (response) {
|
let cb = function (response) {
|
||||||
|
const cb = null
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
QR.currentCaptcha = response
|
QR.currentCaptcha = response
|
||||||
if (QR.captcha === Captcha.v2) {
|
if (QR.captcha === Captcha.v2) {
|
||||||
@ -921,7 +944,7 @@ const QR = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QR.req = $.ajax(`https://sys.${location.hostname.split('.')[1]}.org/${g.BOARD}/post`, options)
|
QR.req = $.ajax(`https://sys.${location.hostname.split('.')[1]}.org/${g.BOARD}/post`, options, cb)
|
||||||
return QR.req.progress = '...'
|
return QR.req.progress = '...'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,7 +961,7 @@ const QR = {
|
|||||||
}
|
}
|
||||||
captcha(function (response) {
|
captcha(function (response) {
|
||||||
if ((QR.captcha === Captcha.v2) && Captcha.cache.haveCookie()) {
|
if ((QR.captcha === Captcha.v2) && Captcha.cache.haveCookie()) {
|
||||||
cb?.()
|
cb(response)
|
||||||
if (response) { return Captcha.cache.save(response) }
|
if (response) { return Captcha.cache.save(response) }
|
||||||
} else if (response) {
|
} else if (response) {
|
||||||
return cb?.(response)
|
return cb?.(response)
|
||||||
@ -1017,7 +1040,7 @@ const QR = {
|
|||||||
}
|
}
|
||||||
QR.captcha.setup(QR.cooldown.auto && [QR.nodes.status, d.body].includes(d.activeElement))
|
QR.captcha.setup(QR.cooldown.auto && [QR.nodes.status, d.body].includes(d.activeElement))
|
||||||
QR.status()
|
QR.status()
|
||||||
QR.error(err)
|
QR.error(err, post)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1103,8 +1126,7 @@ const QR = {
|
|||||||
},
|
},
|
||||||
responseType: 'text',
|
responseType: 'text',
|
||||||
type: 'HEAD'
|
type: 'HEAD'
|
||||||
}
|
}, cb)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return check()
|
return check()
|
||||||
},
|
},
|
||||||
@ -1124,7 +1146,16 @@ const QR = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
cooldown: {
|
cooldown: {
|
||||||
|
timeout: null,
|
||||||
|
isCounting: true || false,
|
||||||
seconds: 0,
|
seconds: 0,
|
||||||
|
isSetup: false,
|
||||||
|
auto: false,
|
||||||
|
maxDelay: 0,
|
||||||
|
data: null,
|
||||||
|
changes: null,
|
||||||
|
customCooldown: null,
|
||||||
|
|
||||||
delays: {
|
delays: {
|
||||||
deletion: 60
|
deletion: 60
|
||||||
}, // cooldown for deleting posts/files
|
}, // cooldown for deleting posts/files
|
||||||
@ -1368,6 +1399,7 @@ const QR = {
|
|||||||
|
|
||||||
oekaki: {
|
oekaki: {
|
||||||
menu: {
|
menu: {
|
||||||
|
post: null,
|
||||||
init() {
|
init() {
|
||||||
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Menu'] || !Conf['Edit Link'] || !Conf['Quick Reply']) { return }
|
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Menu'] || !Conf['Edit Link'] || !Conf['Quick Reply']) { return }
|
||||||
|
|
||||||
@ -1397,9 +1429,14 @@ const QR = {
|
|||||||
const currentTime = post.file.fullImage?.currentTime || 0
|
const currentTime = post.file.fullImage?.currentTime || 0
|
||||||
return CrossOrigin.file(post.file.url, function (blob) {
|
return CrossOrigin.file(post.file.url, function (blob) {
|
||||||
if (!blob) {
|
if (!blob) {
|
||||||
return QR.error("Can't load file.")
|
return QR.error("Can't load file.", 'oekaki')
|
||||||
} else if (isVideo) {
|
} else if (isVideo) {
|
||||||
const video = $.el('video')
|
const video = $.el('video', {
|
||||||
|
src: URL.createObjectURL(blob),
|
||||||
|
autoplay: true,
|
||||||
|
loop: true,
|
||||||
|
muted: true
|
||||||
|
})
|
||||||
$.on(video, 'loadedmetadata', function () {
|
$.on(video, 'loadedmetadata', function () {
|
||||||
$.on(video, 'seeked', function () {
|
$.on(video, 'seeked', function () {
|
||||||
const canvas = $.el('canvas', {
|
const canvas = $.el('canvas', {
|
||||||
@ -1464,22 +1501,31 @@ const QR = {
|
|||||||
return $.add(d.head, [style, script])
|
return $.add(d.head, [style, script])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
return $.global(function () {
|
return $.global(() => {
|
||||||
const { Tegaki, FCX } = window
|
const { Tegaki, FCX } = window
|
||||||
if (Tegaki.bg) { Tegaki.destroy() }
|
|
||||||
|
if (Tegaki.bg) {
|
||||||
|
Tegaki.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
FCX.oekakiName = 'tegaki.png'
|
FCX.oekakiName = 'tegaki.png'
|
||||||
|
|
||||||
|
const getWidth = (): number => +(document.querySelector('#qr [name=oekaki-width]') as HTMLInputElement).clientWidth
|
||||||
|
const getHeight = (): number => +(document.querySelector('#qr [name=oekaki-height]') as HTMLInputElement).clientHeight
|
||||||
|
const getBgColor = (): string => {
|
||||||
|
const bgColorCheckbox = document.querySelector('#qr [name=oekaki-bg]') as HTMLInputElement
|
||||||
|
const bgColorInput = document.querySelector('#qr [name=oekaki-bgcolor]') as HTMLInputElement
|
||||||
|
|
||||||
|
return bgColorCheckbox.checked ? bgColorInput.value : 'transparent'
|
||||||
|
}
|
||||||
|
|
||||||
return Tegaki.open({
|
return Tegaki.open({
|
||||||
onDone: FCX.oekakiCB,
|
onDone: FCX.oekakiCB,
|
||||||
onCancel() { return Tegaki.bgColor = '#ffffff' },
|
onCancel: () => { Tegaki.bgColor = '#ffffff' },
|
||||||
width: +document.querySelector('#qr [name=oekaki-width]').value,
|
width: getWidth(),
|
||||||
height: +document.querySelector('#qr [name=oekaki-height]').value,
|
height: getHeight(),
|
||||||
bgColor:
|
bgColor: getBgColor(),
|
||||||
document.querySelector('#qr [name=oekaki-bg]').checked ?
|
|
||||||
document.querySelector('#qr [name=oekaki-bgcolor]').value
|
|
||||||
:
|
|
||||||
'transparent'
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -1536,7 +1582,7 @@ const QR = {
|
|||||||
FCX.oekakiName = name
|
FCX.oekakiName = name
|
||||||
return Tegaki.resume()
|
return Tegaki.resume()
|
||||||
} else {
|
} else {
|
||||||
return cb()
|
return cb(E)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
@ -1545,13 +1591,15 @@ const QR = {
|
|||||||
return QR.oekaki.load(() => QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden)
|
return QR.oekaki.load(() => QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
email: null,
|
||||||
|
|
||||||
persona: {
|
persona: {
|
||||||
always: {},
|
pwd: '',
|
||||||
|
always: false,
|
||||||
types: {
|
types: {
|
||||||
name: [],
|
name: [""],
|
||||||
email: [],
|
email: [""],
|
||||||
sub: []
|
sub: [""]
|
||||||
},
|
},
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@ -1565,6 +1613,7 @@ const QR = {
|
|||||||
let match, needle, type, val
|
let match, needle, type, val
|
||||||
if (item[0] === '#') { return }
|
if (item[0] === '#') { return }
|
||||||
if (!(match = item.match(/(name|options|email|subject|password):"(.*)"/i))) { return }
|
if (!(match = item.match(/(name|options|email|subject|password):"(.*)"/i))) { return }
|
||||||
|
// eslint-disable-next-line prefer-const
|
||||||
[match, type, val] = Array.from(match)
|
[match, type, val] = Array.from(match)
|
||||||
|
|
||||||
// Don't mix up item settings with val.
|
// Don't mix up item settings with val.
|
||||||
@ -1630,8 +1679,23 @@ const QR = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
post: class {
|
post: class {
|
||||||
|
thread: Thread
|
||||||
|
flag: string
|
||||||
|
sub: string
|
||||||
|
com: string
|
||||||
|
spoiler: boolean
|
||||||
|
name: string
|
||||||
|
email: string
|
||||||
|
fileUrl: string
|
||||||
|
fileThumb: string
|
||||||
|
nodes: { el: HTMLElement; rm: HTMLElement; spoiler: HTMLInputElement; span: HTMLElement }
|
||||||
|
draggable: boolean
|
||||||
|
parentNode: HTMLElement
|
||||||
|
filesize: string
|
||||||
|
filename: string
|
||||||
|
pasting: boolean
|
||||||
|
URL: string
|
||||||
constructor(select) {
|
constructor(select) {
|
||||||
this.select = this.select.bind(this)
|
this.select = this.select.bind(this)
|
||||||
const el = $.el('a', {
|
const el = $.el('a', {
|
||||||
@ -1734,7 +1798,7 @@ const QR = {
|
|||||||
this.isLocked = lock
|
this.isLocked = lock
|
||||||
if (this !== QR.selected) { return }
|
if (this !== QR.selected) { return }
|
||||||
for (const name of ['thread', 'name', 'email', 'sub', 'com', 'fileButton', 'filename', 'spoiler', 'flag']) {
|
for (const name of ['thread', 'name', 'email', 'sub', 'com', 'fileButton', 'filename', 'spoiler', 'flag']) {
|
||||||
var node
|
let node
|
||||||
if ((node = QR.nodes[name])) {
|
if ((node = QR.nodes[name])) {
|
||||||
node.disabled = lock
|
node.disabled = lock
|
||||||
}
|
}
|
||||||
@ -1767,7 +1831,7 @@ const QR = {
|
|||||||
// Load this post's values.
|
// Load this post's values.
|
||||||
|
|
||||||
for (const name of ['thread', 'name', 'email', 'sub', 'com', 'filename', 'flag']) {
|
for (const name of ['thread', 'name', 'email', 'sub', 'com', 'filename', 'flag']) {
|
||||||
var node
|
let node
|
||||||
if (!(node = QR.nodes[name])) { continue }
|
if (!(node = QR.nodes[name])) { continue }
|
||||||
node.value = this[name] || node.dataset.default || ''
|
node.value = this[name] || node.dataset.default || ''
|
||||||
}
|
}
|
||||||
@ -1815,7 +1879,7 @@ const QR = {
|
|||||||
// Do this in case people use extensions
|
// Do this in case people use extensions
|
||||||
// that do not trigger the `input` event.
|
// that do not trigger the `input` event.
|
||||||
for (const name of ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler', 'flag']) {
|
for (const name of ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler', 'flag']) {
|
||||||
var node
|
let node
|
||||||
if (!(node = QR.nodes[name])) { continue }
|
if (!(node = QR.nodes[name])) { continue }
|
||||||
this.save(node, true)
|
this.save(node, true)
|
||||||
}
|
}
|
||||||
@ -1856,7 +1920,7 @@ const QR = {
|
|||||||
static rmErrored(e) {
|
static rmErrored(e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
for (let i = QR.posts.length - 1; i >= 0; i--) {
|
for (let i = QR.posts.length - 1; i >= 0; i--) {
|
||||||
var errors
|
let errors
|
||||||
const post = QR.posts[i]
|
const post = QR.posts[i]
|
||||||
if ((errors = post.errors)) {
|
if ((errors = post.errors)) {
|
||||||
for (const error of errors) {
|
for (const error of errors) {
|
||||||
@ -1926,7 +1990,7 @@ const QR = {
|
|||||||
this.nodes.el.dataset.type = this.file.type
|
this.nodes.el.dataset.type = this.file.type
|
||||||
this.nodes.el.style.backgroundImage = ''
|
this.nodes.el.style.backgroundImage = ''
|
||||||
if (!QR.mimeTypes.includes(this.file.type)) {
|
if (!QR.mimeTypes.includes(this.file.type)) {
|
||||||
this.fileError('Unsupported file type.')
|
this.fileError('Unsupported file type.', meta.faq + '#supported-file-types')
|
||||||
} else if (/^(image|video)\//.test(this.file.type)) {
|
} else if (/^(image|video)\//.test(this.file.type)) {
|
||||||
this.readFile()
|
this.readFile()
|
||||||
}
|
}
|
||||||
@ -1937,13 +2001,13 @@ const QR = {
|
|||||||
let max = QR.max_size
|
let max = QR.max_size
|
||||||
if (/^video\//.test(this.file.type)) { max = Math.min(max, QR.max_size_video) }
|
if (/^video\//.test(this.file.type)) { max = Math.min(max, QR.max_size_video) }
|
||||||
if (this.file.size > max) {
|
if (this.file.size > max) {
|
||||||
return this.fileError(`File too large (file: ${this.filesize}, max: ${$.bytesToString(max)}).`)
|
return this.fileError(`File too large (file: ${this.filesize}, max: ${$.bytesToString(max)}).`, meta.faq + '#file-too-large')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readFile() {
|
readFile() {
|
||||||
const isVideo = /^video\//.test(this.file.type)
|
const isVideo = /^video\//.test(this.file.type)
|
||||||
const el = $.el(isVideo ? 'video' : 'img')
|
const el = $.el(isVideo ? 'video' : 'img', { src: this.URL, style: 'display: none' })
|
||||||
if (isVideo && !el.canPlayType(this.file.type)) { return }
|
if (isVideo && !el.canPlayType(this.file.type)) { return }
|
||||||
|
|
||||||
const event = isVideo ? 'loadeddata' : 'load'
|
const event = isVideo ? 'loadeddata' : 'load'
|
||||||
@ -1954,7 +2018,7 @@ const QR = {
|
|||||||
this.setThumbnail(el)
|
this.setThumbnail(el)
|
||||||
return $.event('QRMetadata', null, this.nodes.el)
|
return $.event('QRMetadata', null, this.nodes.el)
|
||||||
}
|
}
|
||||||
var onerror = () => {
|
const onerror = () => {
|
||||||
$.off(el, event, onload)
|
$.off(el, event, onload)
|
||||||
$.off(el, 'error', onerror)
|
$.off(el, 'error', onerror)
|
||||||
this.fileError(`Corrupt ${isVideo ? 'video' : 'image'} or error reading metadata.`, meta.faq + '#error-reading-metadata')
|
this.fileError(`Corrupt ${isVideo ? 'video' : 'image'} or error reading metadata.`, meta.faq + '#error-reading-metadata')
|
||||||
@ -1968,7 +2032,6 @@ const QR = {
|
|||||||
$.on(el, 'error', onerror)
|
$.on(el, 'error', onerror)
|
||||||
return el.src = URL.createObjectURL(this.file)
|
return el.src = URL.createObjectURL(this.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDimensions(el) {
|
checkDimensions(el) {
|
||||||
let height, width
|
let height, width
|
||||||
if (el.tagName === 'IMG') {
|
if (el.tagName === 'IMG') {
|
||||||
@ -1976,10 +2039,10 @@ const QR = {
|
|||||||
this.nodes.el.dataset.height = height
|
this.nodes.el.dataset.height = height
|
||||||
this.nodes.el.dataset.width = width
|
this.nodes.el.dataset.width = width
|
||||||
if ((height > QR.max_height) || (width > QR.max_width)) {
|
if ((height > QR.max_height) || (width > QR.max_width)) {
|
||||||
this.fileError(`Image too large (image: ${height}x${width}px, max: ${QR.max_height}x${QR.max_width}px)`)
|
this.fileError(`Image too large (image: ${height}x${width}px, max: ${QR.max_height}x${QR.max_width}px)`, meta.faq + '#image-too-large')
|
||||||
}
|
}
|
||||||
if ((height < QR.min_height) || (width < QR.min_width)) {
|
if ((height < QR.min_height) || (width < QR.min_width)) {
|
||||||
return this.fileError(`Image too small (image: ${height}x${width}px, min: ${QR.min_height}x${QR.min_width}px)`)
|
return this.fileError(`Image too small (image: ${height}x${width}px, min: ${QR.min_height}x${QR.min_width}px)`, meta.faq + '#image-too-small')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const { videoHeight, videoWidth, duration } = el
|
const { videoHeight, videoWidth, duration } = el
|
||||||
@ -1989,18 +2052,18 @@ const QR = {
|
|||||||
const max_height = Math.min(QR.max_height, QR.max_height_video)
|
const max_height = Math.min(QR.max_height, QR.max_height_video)
|
||||||
const max_width = Math.min(QR.max_width, QR.max_width_video)
|
const max_width = Math.min(QR.max_width, QR.max_width_video)
|
||||||
if ((videoHeight > max_height) || (videoWidth > max_width)) {
|
if ((videoHeight > max_height) || (videoWidth > max_width)) {
|
||||||
this.fileError(`Video too large (video: ${videoHeight}x${videoWidth}px, max: ${max_height}x${max_width}px)`)
|
this.fileError(`Video too large (video: ${videoHeight}x${videoWidth}px, max: ${max_height}x${max_width}px)`, meta.faq + '#video-too-large')
|
||||||
}
|
}
|
||||||
if ((videoHeight < QR.min_height) || (videoWidth < QR.min_width)) {
|
if ((videoHeight < QR.min_height) || (videoWidth < QR.min_width)) {
|
||||||
this.fileError(`Video too small (video: ${videoHeight}x${videoWidth}px, min: ${QR.min_height}x${QR.min_width}px)`)
|
this.fileError(`Video too small (video: ${videoHeight}x${videoWidth}px, min: ${QR.min_height}x${QR.min_width}px)`, meta.faq + '#video-too-small')
|
||||||
}
|
}
|
||||||
if (!isFinite(duration)) {
|
if (!isFinite(duration)) {
|
||||||
this.fileError('Video lacks duration metadata (try remuxing)')
|
this.fileError('Video lacks duration metadata (try remuxing)', meta.faq + '#video-lacks-duration-metadata')
|
||||||
} else if (duration > QR.max_duration_video) {
|
} else if (duration > QR.max_duration_video) {
|
||||||
this.fileError(`Video too long (video: ${duration}s, max: ${QR.max_duration_video}s)`)
|
this.fileError(`Video too long (video: ${duration}s, max: ${QR.max_duration_video}s)`, meta.faq + '#video-too-long')
|
||||||
}
|
}
|
||||||
if (BoardConfig.noAudio(g.BOARD.ID) && $.hasAudio(el)) {
|
if (BoardConfig.noAudio(g.BOARD.ID) && $.hasAudio(el)) {
|
||||||
return this.fileError('Audio not allowed')
|
return this.fileError('Audio not allowed', meta.faq + '#audio-not-allowed')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2035,7 +2098,7 @@ const QR = {
|
|||||||
height = (s / width) * height
|
height = (s / width) * height
|
||||||
width = s
|
width = s
|
||||||
}
|
}
|
||||||
const cv = $.el('canvas')
|
const cv = $.el('canvas', null)
|
||||||
cv.height = height
|
cv.height = height
|
||||||
cv.width = width
|
cv.width = width
|
||||||
cv.getContext('2d').drawImage(el, 0, 0, width, height)
|
cv.getContext('2d').drawImage(el, 0, 0, width, height)
|
||||||
|
|||||||
@ -14,6 +14,13 @@ declare global {
|
|||||||
}
|
}
|
||||||
// interfaces might be incomplete
|
// interfaces might be incomplete
|
||||||
export interface BoardConfig {
|
export interface BoardConfig {
|
||||||
|
sjis_tags: string,
|
||||||
|
math_tags: string,
|
||||||
|
forced_anon: boolean,
|
||||||
|
board_flags: string[],
|
||||||
|
require_subject: boolean,
|
||||||
|
text_only: boolean
|
||||||
|
country_flags: 1 | 0,
|
||||||
board: string
|
board: string
|
||||||
bump_limit: number
|
bump_limit: number
|
||||||
cooldowns: {
|
cooldowns: {
|
||||||
@ -37,6 +44,8 @@ export interface BoardConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Board {
|
export interface Board {
|
||||||
|
cooldowns(): object
|
||||||
|
forced_anon: 1 | 0,
|
||||||
ID: string,
|
ID: string,
|
||||||
boardID: string,
|
boardID: string,
|
||||||
siteID: string,
|
siteID: string,
|
||||||
|
|||||||
@ -592,19 +592,25 @@ $.queueTask = (() => {
|
|||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
|
||||||
$.global = function (fn, data) {
|
$.global = function (fn: Function, data?: any) {
|
||||||
if (doc) {
|
const d = document
|
||||||
const script = $.el('script',
|
if (d) {
|
||||||
{ textContent: `(${fn}).call(document.currentScript.dataset);` })
|
const script = $.el('script', {
|
||||||
if (data) { $.extend(script.dataset, data) }
|
textContent: `(${fn}).call(document.currentScript.dataset);`,
|
||||||
$.add((d.head || doc), script)
|
})
|
||||||
|
if (data) {
|
||||||
|
$.extend(script.dataset, data)
|
||||||
|
}
|
||||||
|
const target = d.head || d
|
||||||
|
$.add(target, script)
|
||||||
$.rm(script)
|
$.rm(script)
|
||||||
return script.dataset
|
return script.dataset
|
||||||
} else {
|
} else {
|
||||||
// XXX dwb
|
|
||||||
try {
|
try {
|
||||||
fn.call(data)
|
fn.call(data)
|
||||||
} catch (error) { }
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -666,13 +672,10 @@ $.item = function (key: string, val: string | JSON) {
|
|||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
$.oneItemSugar = (fn: Function) => (function (key: string, val: JSON | string, cb) {
|
$.oneItemSugar = (fn: (item: any, cb?) => any) => (key: string | any, val?: JSON | string, cb?) => {
|
||||||
if (typeof key === 'string') {
|
const item = typeof key === 'string' ? $.item(key, val) : key
|
||||||
return fn($.item(key, val), cb)
|
return fn(item, cb)
|
||||||
} else {
|
|
||||||
return fn(key, val)
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
$.syncing = dict()
|
$.syncing = dict()
|
||||||
|
|
||||||
@ -701,7 +704,12 @@ if (platform === 'crx') {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
$.sync = (key: string, cb) => $.syncing[key] = cb
|
$.sync = (key: string, cb) => $.syncing[key] = cb
|
||||||
$.forceSync = function () {/* emptey */ }
|
$.forceSync = (key: string, cb) => {
|
||||||
|
$.syncing[key] = cb
|
||||||
|
chrome.storage.local.get(key, function (data) {
|
||||||
|
cb(data[key], key)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
$.crxWorking = function () {
|
$.crxWorking = function () {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -6,6 +6,19 @@ import { dict } from "../platform/helpers"
|
|||||||
|
|
||||||
|
|
||||||
const SWTinyboard = {
|
const SWTinyboard = {
|
||||||
|
insertTags() {
|
||||||
|
const { config } = Conf['boardConfig']
|
||||||
|
const { markup_tags } = config
|
||||||
|
const { markup_tags_top } = config
|
||||||
|
const { markup_tags_bottom } = config
|
||||||
|
const tags = markup_tags_top + markup_tags + markup_tags_bottom
|
||||||
|
if (tags) {
|
||||||
|
const textarea = $('#body')
|
||||||
|
if (textarea) {
|
||||||
|
textarea.insertAdjacentHTML('beforebegin', tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
name: 'Tinyboard',
|
name: 'Tinyboard',
|
||||||
isOPContainerThread: true,
|
isOPContainerThread: true,
|
||||||
mayLackJSON: true,
|
mayLackJSON: true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user