mirror of
https://github.com/LalleSX/4chan-XZ.git
synced 2026-03-20 01:37:47 +01:00
types
This commit is contained in:
parent
f869225c41
commit
55dd58b8c6
@ -38,7 +38,7 @@ const Get = {
|
|||||||
if (index) { return post.clones[+index] } else { return post }
|
if (index) { return post.clones[+index] } else { return post }
|
||||||
},
|
},
|
||||||
postFromNode(root): Post {
|
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)) as Post
|
||||||
},
|
},
|
||||||
postDataFromLink(link) {
|
postDataFromLink(link) {
|
||||||
let boardID, postID, threadID
|
let boardID, postID, threadID
|
||||||
|
|||||||
@ -3,11 +3,7 @@ import { Conf, doc } from "../globals/globals"
|
|||||||
import $ from "../platform/$"
|
import $ from "../platform/$"
|
||||||
import $$ from "../platform/$$"
|
import $$ from "../platform/$$"
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
const AntiAutoplay = {
|
const AntiAutoplay = {
|
||||||
init() {
|
init() {
|
||||||
if (!Conf['Disable Autoplaying Sounds']) { return }
|
if (!Conf['Disable Autoplaying Sounds']) { return }
|
||||||
@ -31,10 +27,10 @@ const AntiAutoplay = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
node() {
|
node() {
|
||||||
return AntiAutoplay.process(this.nodes.comment)
|
return AntiAutoplay.process(this.node())
|
||||||
},
|
},
|
||||||
|
|
||||||
process(root) {
|
process(root: HTMLElement) {
|
||||||
for (const iframe of $$('iframe[src*="youtube"][src*="autoplay=1"]', root)) {
|
for (const iframe of $$('iframe[src*="youtube"][src*="autoplay=1"]', root)) {
|
||||||
AntiAutoplay.processVideo(iframe, 'src')
|
AntiAutoplay.processVideo(iframe, 'src')
|
||||||
}
|
}
|
||||||
@ -43,7 +39,7 @@ const AntiAutoplay = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
processVideo(el, attr) {
|
processVideo(el: HTMLIFrameElement | HTMLObjectElement, attr: 'src' | 'data') {
|
||||||
el[attr] = el[attr].replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', '')
|
el[attr] = el[attr].replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', '')
|
||||||
if (window.getComputedStyle(el).display === 'none') { el.style.display = 'block' }
|
if (window.getComputedStyle(el).display === 'none') { el.style.display = 'block' }
|
||||||
return $.addClass(el, 'autoplay-removed')
|
return $.addClass(el, 'autoplay-removed')
|
||||||
|
|||||||
@ -6,13 +6,7 @@ import $ from "../platform/$"
|
|||||||
import $$ from "../platform/$$"
|
import $$ from "../platform/$$"
|
||||||
import { dict } from "../platform/helpers"
|
import { dict } from "../platform/helpers"
|
||||||
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS101: Remove unnecessary use of Array.from
|
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
|
||||||
* DS207: Consider shorter variations of null checks
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
const Banner = {
|
const Banner = {
|
||||||
init() {
|
init() {
|
||||||
if (Conf['Custom Board Titles']) {
|
if (Conf['Custom Board Titles']) {
|
||||||
|
|||||||
@ -81,7 +81,7 @@ const CatalogLinks = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
$.event('CloseMenu')
|
$.event('CloseMenu', { menu: Header.menu })
|
||||||
$.set('Header catalog links', this.checked)
|
$.set('Header catalog links', this.checked)
|
||||||
return CatalogLinks.set(this.checked)
|
return CatalogLinks.set(this.checked)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export default class Board {
|
|||||||
config: any
|
config: any
|
||||||
toString() { return this.ID }
|
toString() { return this.ID }
|
||||||
|
|
||||||
constructor(ID) {
|
constructor(ID: string) {
|
||||||
this.ID = ID
|
this.ID = ID
|
||||||
this.boardID = this.ID
|
this.boardID = this.ID
|
||||||
this.siteID = g.SITE.ID
|
this.siteID = g.SITE.ID
|
||||||
@ -22,7 +22,7 @@ export default class Board {
|
|||||||
this.posts = new SimpleDict()
|
this.posts = new SimpleDict()
|
||||||
this.config = BoardConfig.boards?.[this.ID] || {}
|
this.config = BoardConfig.boards?.[this.ID] || {}
|
||||||
|
|
||||||
g.boards[this] = this
|
g.boards[this.ID] = this
|
||||||
}
|
}
|
||||||
|
|
||||||
cooldowns() {
|
cooldowns() {
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export default class Callbacks {
|
|||||||
return this[name] = cb
|
return this[name] = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(node, keys = this.keys, force = false) {
|
execute(node: Post, keys = this.keys, force = false) {
|
||||||
let errors
|
let errors
|
||||||
if (node.callbacksExecuted && !force) { return }
|
if (node.callbacksExecuted && !force) { return }
|
||||||
node.callbacksExecuted = true
|
node.callbacksExecuted = true
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import Callbacks from "./Callbacks"
|
|||||||
|
|
||||||
|
|
||||||
export default class Connection {
|
export default class Connection {
|
||||||
target: any
|
target: Window | HTMLIFrameElement
|
||||||
origin: any
|
origin: string
|
||||||
cb: Callbacks
|
cb: Callbacks
|
||||||
constructor(target: Window, origin: string, cb: Callbacks) {
|
constructor(target: Window, origin: string, cb: Callbacks) {
|
||||||
this.send = this.send.bind(this)
|
this.send = this.send.bind(this)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Conf, d, g } from "../globals/globals"
|
import { Conf, d, g } from "../globals/globals"
|
||||||
import $ from "../platform/$"
|
import $ from "../platform/$"
|
||||||
import { dict, HOUR } from "../platform/helpers"
|
import { dict, HOUR } from "../platform/helpers"
|
||||||
|
import { CacheOptions } from "../types/globals"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* decaffeinate suggestions:
|
* decaffeinate suggestions:
|
||||||
@ -20,7 +21,6 @@ export default class DataBoard {
|
|||||||
static keys: string[]
|
static keys: string[]
|
||||||
static changes: string[]
|
static changes: string[]
|
||||||
key: string
|
key: string
|
||||||
sync: VoidFunction
|
|
||||||
data: any
|
data: any
|
||||||
static initClass() {
|
static initClass() {
|
||||||
this.keys = ['hiddenThreads', 'hiddenPosts', 'lastReadPosts', 'yourPosts', 'watchedThreads', 'watcherLastModified', 'customTitles']
|
this.keys = ['hiddenThreads', 'hiddenPosts', 'lastReadPosts', 'yourPosts', 'watchedThreads', 'watcherLastModified', 'customTitles']
|
||||||
@ -98,7 +98,7 @@ export default class DataBoard {
|
|||||||
} else if (threadID) {
|
} else if (threadID) {
|
||||||
if (!this.data[siteID].boards[boardID]) { return }
|
if (!this.data[siteID].boards[boardID]) { return }
|
||||||
delete this.data[siteID].boards[boardID][threadID]
|
delete this.data[siteID].boards[boardID][threadID]
|
||||||
return this.deleteIfEmpty({ siteID, boardID })
|
return this.deleteIfEmpty({ siteID, boardID, threadID: null })
|
||||||
} else {
|
} else {
|
||||||
return delete this.data[siteID].boards[boardID]
|
return delete this.data[siteID].boards[boardID]
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ export default class DataBoard {
|
|||||||
if (threadID) {
|
if (threadID) {
|
||||||
if (!Object.keys(this.data[siteID].boards[boardID][threadID]).length) {
|
if (!Object.keys(this.data[siteID].boards[boardID][threadID]).length) {
|
||||||
delete this.data[siteID].boards[boardID][threadID]
|
delete this.data[siteID].boards[boardID][threadID]
|
||||||
return this.deleteIfEmpty({ siteID, boardID })
|
return this.deleteIfEmpty({ siteID, boardID, threadID: null })
|
||||||
}
|
}
|
||||||
} else if (!Object.keys(this.data[siteID].boards[boardID]).length) {
|
} else if (!Object.keys(this.data[siteID].boards[boardID]).length) {
|
||||||
return delete this.data[siteID].boards[boardID]
|
return delete this.data[siteID].boards[boardID]
|
||||||
@ -157,7 +157,10 @@ export default class DataBoard {
|
|||||||
setLastChecked(key = 'lastChecked') {
|
setLastChecked(key = 'lastChecked') {
|
||||||
return this.save(() => {
|
return this.save(() => {
|
||||||
return this.data[key] = Date.now()
|
return this.data[key] = Date.now()
|
||||||
})
|
}, () => {
|
||||||
|
return this.sync?.()
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
get({ siteID, boardID, threadID, postID, defaultValue }) {
|
get({ siteID, boardID, threadID, postID, defaultValue }) {
|
||||||
@ -203,21 +206,21 @@ export default class DataBoard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ajaxClean(boardID) {
|
ajaxClean(boardID: string) {
|
||||||
const that = this
|
const that = this
|
||||||
const siteID = g.SITE.ID
|
const siteID = g.SITE.ID
|
||||||
const threadsList = g.SITE.urls.threadsListJSON?.({ siteID, boardID })
|
const threadsList = g.SITE.urls.threadsListJSON?.({ siteID, boardID })
|
||||||
if (!threadsList) { return }
|
if (!threadsList) { return }
|
||||||
return $.cache(threadsList, function () {
|
return $.cache(threadsList, () => {
|
||||||
if (this.status !== 200) { return }
|
if (this.status !== 200) { return }
|
||||||
const archiveList = g.SITE.urls.archiveListJSON?.({ siteID, boardID })
|
const archiveList = g.SITE.urls.archiveListJSON?.({ siteID, boardID })
|
||||||
if (!archiveList) { return that.ajaxCleanParse(boardID, this.response) }
|
if (!archiveList) { return that.ajaxCleanParse(boardID, this.response) }
|
||||||
const response1 = this.response
|
const response1 = this.response
|
||||||
return $.cache(archiveList, function () {
|
return $.cache(archiveList, () => {
|
||||||
if ((this.status !== 200) && (!!g.SITE.archivedBoardsKnown || (this.status !== 404))) { return }
|
if ((this.status !== 200) && (!!g.SITE.archivedBoardsKnown || (this.status !== 404))) { return }
|
||||||
return that.ajaxCleanParse(boardID, response1, this.response)
|
return that.ajaxCleanParse(boardID, response1, this.response)
|
||||||
})
|
}, { type: 'json' }) as CacheOptions
|
||||||
})
|
}, { type: 'json' }) as CacheOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
ajaxCleanParse(boardID, response1, response2) {
|
ajaxCleanParse(boardID, response1, response2) {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import Callbacks from "./Callbacks"
|
|||||||
import type Thread from "./Thread"
|
import type Thread from "./Thread"
|
||||||
|
|
||||||
export default class Post {
|
export default class Post {
|
||||||
|
callbacksExecuted: boolean
|
||||||
declare root: HTMLElement
|
declare root: HTMLElement
|
||||||
declare thread: Thread
|
declare thread: Thread
|
||||||
declare board: Board
|
declare board: Board
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
import $ from '../platform/$'
|
|
||||||
class ShimSet {
|
class ShimSet {
|
||||||
elements: any
|
elements: Element
|
||||||
size: number
|
size: number
|
||||||
constructor() {
|
constructor() {
|
||||||
this.elements = $.dict()
|
this.elements
|
||||||
this.size = 0
|
this.size = 0
|
||||||
}
|
}
|
||||||
has(value) {
|
has(value) {
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import $ from "../platform/$"
|
|
||||||
|
|
||||||
export default class SimpleDict<T> {
|
export default class SimpleDict<T> {
|
||||||
keys: string[]
|
keys: string[]
|
||||||
|
|
||||||
@ -9,17 +7,15 @@ export default class SimpleDict<T> {
|
|||||||
|
|
||||||
push(key: string, data: T): T {
|
push(key: string, data: T): T {
|
||||||
key = `${key}`
|
key = `${key}`
|
||||||
if (!this[key]) { this.keys.push(key) }
|
this[key] = data
|
||||||
return this[key] = data
|
this.keys.push(key)
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
rm(key: string) {
|
rm(key: string) {
|
||||||
let i: number
|
|
||||||
key = `${key}`
|
key = `${key}`
|
||||||
if ((i = this.keys.indexOf(key)) !== -1) {
|
delete this[key]
|
||||||
this.keys.splice(i, 1)
|
this.keys = this.keys.filter(k => k !== key)
|
||||||
return delete this[key]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
forEach(fn: (value: T) => void): void {
|
forEach(fn: (value: T) => void): void {
|
||||||
@ -27,10 +23,6 @@ export default class SimpleDict<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(key: string): T {
|
get(key: string): T {
|
||||||
if (key === 'keys') {
|
return this[key]
|
||||||
return undefined
|
|
||||||
} else {
|
|
||||||
return $.getOwn(this, key)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import SimpleDict from "./SimpleDict"
|
|||||||
|
|
||||||
export default class Thread {
|
export default class Thread {
|
||||||
catalogViewNative: CatalogThreadNative
|
catalogViewNative: CatalogThreadNative
|
||||||
ID: number | string
|
ID: string | number
|
||||||
OP: Post
|
OP: Post
|
||||||
isArchived: boolean
|
isArchived: boolean
|
||||||
isClosed: boolean
|
isClosed: boolean
|
||||||
@ -16,7 +16,7 @@ export default class Thread {
|
|||||||
board: Board
|
board: Board
|
||||||
threadID: number
|
threadID: number
|
||||||
boardID: number | string
|
boardID: number | string
|
||||||
siteID: number
|
siteID: number | string
|
||||||
fullID: string
|
fullID: string
|
||||||
isDead: boolean
|
isDead: boolean
|
||||||
isHidden: boolean
|
isHidden: boolean
|
||||||
@ -52,7 +52,7 @@ export default class Thread {
|
|||||||
|
|
||||||
this.nodes = { root: null }
|
this.nodes = { root: null }
|
||||||
|
|
||||||
this.board.threads.push(this.ID, this)
|
this.board.threads.push(this.ID.toString(), this)
|
||||||
g.threads.push(this.fullID, this)
|
g.threads.push(this.fullID, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -763,7 +763,7 @@ const Config = {
|
|||||||
|
|
||||||
comment: `\
|
comment: `\
|
||||||
# Filter Stallman copypasta on /g/:
|
# Filter Stallman copypasta on /g/:
|
||||||
#/what you\'re refer+ing to as linux/i;boards:g
|
#/what you're refer+ing to as linux/i;boards:g
|
||||||
# Filter posts with 20 or more quote links:
|
# Filter posts with 20 or more quote links:
|
||||||
#/(?:>>\\d(?:(?!>>\\d)[^])*){20}/
|
#/(?:>>\\d(?:(?!>>\\d)[^])*){20}/
|
||||||
# Filter posts like T H I S / H / I / S:
|
# Filter posts like T H I S / H / I / S:
|
||||||
@ -817,7 +817,7 @@ http://eye.swfchan.com/search/?q=%name;types:swf
|
|||||||
`,
|
`,
|
||||||
|
|
||||||
FappeT: {
|
FappeT: {
|
||||||
werk: false
|
werk: false
|
||||||
},
|
},
|
||||||
|
|
||||||
'Custom CSS': true,
|
'Custom CSS': true,
|
||||||
@ -826,29 +826,29 @@ http://eye.swfchan.com/search/?q=%name;types:swf
|
|||||||
'Index Mode': 'paged',
|
'Index Mode': 'paged',
|
||||||
'Previous Index Mode': 'paged',
|
'Previous Index Mode': 'paged',
|
||||||
'Index Size': 'small',
|
'Index Size': 'small',
|
||||||
'Show Replies': [true, 'Show replies in the index, and also in the catalog if "Catalog hover expand" is checked.'],
|
'Show Replies': [true, 'Show replies in the index, and also in the catalog if "Catalog hover expand" is checked.'],
|
||||||
'Catalog Hover Expand': [false, 'Expand the comment and show more details when you hover over a thread in the catalog.'],
|
'Catalog Hover Expand': [false, 'Expand the comment and show more details when you hover over a thread in the catalog.'],
|
||||||
'Catalog Hover Toggle': [true, 'Turn "Catalog hover expand" on and off by clicking in the catalog.'],
|
'Catalog Hover Toggle': [true, 'Turn "Catalog hover expand" on and off by clicking in the catalog.'],
|
||||||
'Pin Watched Threads': [false, 'Move watched threads to the start of the index.'],
|
'Pin Watched Threads': [false, 'Move watched threads to the start of the index.'],
|
||||||
'Anchor Hidden Threads': [true, 'Move hidden threads to the end of the index.'],
|
'Anchor Hidden Threads': [true, 'Move hidden threads to the end of the index.'],
|
||||||
'Refreshed Navigation': [false, 'Refresh index when navigating through pages.']
|
'Refreshed Navigation': [false, 'Refresh index when navigating through pages.']
|
||||||
},
|
},
|
||||||
|
|
||||||
Header: {
|
Header: {
|
||||||
'Fixed Header': true,
|
'Fixed Header': true,
|
||||||
'Header auto-hide': false,
|
'Header auto-hide': false,
|
||||||
'Header auto-hide on scroll': false,
|
'Header auto-hide on scroll': false,
|
||||||
'Bottom Header': false,
|
'Bottom Header': false,
|
||||||
'Centered links': false,
|
'Centered links': false,
|
||||||
'Header catalog links': false,
|
'Header catalog links': false,
|
||||||
'Bottom Board List': true,
|
'Bottom Board List': true,
|
||||||
'Shortcut Icons': true,
|
'Shortcut Icons': true,
|
||||||
'Custom Board Navigation': true
|
'Custom Board Navigation': true
|
||||||
},
|
},
|
||||||
|
|
||||||
archives: {
|
archives: {
|
||||||
archiveLists: 'https://4chenz.github.io/archives.json/archives.json',
|
archiveLists: 'https://4chenz.github.io/archives.json/archives.json',
|
||||||
lastarchivecheck: 0,
|
lastarchivecheck: 0,
|
||||||
archiveAutoUpdate: true
|
archiveAutoUpdate: true
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -937,7 +937,7 @@ https://*.hcaptcha.com
|
|||||||
'Alt+c',
|
'Alt+c',
|
||||||
'Insert code tags.'
|
'Insert code tags.'
|
||||||
],
|
],
|
||||||
'Eqn tags': [
|
'Eqn tags': [
|
||||||
'Alt+e',
|
'Alt+e',
|
||||||
'Insert eqn tags.'
|
'Insert eqn tags.'
|
||||||
],
|
],
|
||||||
@ -1184,11 +1184,11 @@ https://*.hcaptcha.com
|
|||||||
'Autohiding Scrollbar': false,
|
'Autohiding Scrollbar': false,
|
||||||
|
|
||||||
position: {
|
position: {
|
||||||
'embedding.position': 'top: 50px; right: 0px;',
|
'embedding.position': 'top: 50px; right: 0px;',
|
||||||
'thread-stats.position': 'bottom: 0px; right: 0px;',
|
'thread-stats.position': 'bottom: 0px; right: 0px;',
|
||||||
'updater.position': 'bottom: 0px; left: 0px;',
|
'updater.position': 'bottom: 0px; left: 0px;',
|
||||||
'thread-watcher.position': 'top: 50px; left: 0px;',
|
'thread-watcher.position': 'top: 50px; left: 0px;',
|
||||||
'qr.position': 'top: 50px; right: 0px;'
|
'qr.position': 'top: 50px; right: 0px;'
|
||||||
},
|
},
|
||||||
|
|
||||||
fourchanImageHost: 'i.4cdn.org',
|
fourchanImageHost: 'i.4cdn.org',
|
||||||
|
|||||||
@ -61,7 +61,7 @@ export const g: {
|
|||||||
VERSION: string,
|
VERSION: string,
|
||||||
NAMESPACE: string,
|
NAMESPACE: string,
|
||||||
sites: (typeof SWTinyboard)[],
|
sites: (typeof SWTinyboard)[],
|
||||||
boards: Board[],
|
boards: SimpleDict<Board>,
|
||||||
posts?: SimpleDict<Post>,
|
posts?: SimpleDict<Post>,
|
||||||
threads?: SimpleDict<Thread>
|
threads?: SimpleDict<Thread>
|
||||||
THREADID?: number,
|
THREADID?: number,
|
||||||
@ -90,7 +90,7 @@ export const E = (function () {
|
|||||||
const output = function (text: string) {
|
const output = function (text: string) {
|
||||||
return text.toString().replace(regex, fn)
|
return text.toString().replace(regex, fn)
|
||||||
}
|
}
|
||||||
output.cat = function (templates) {
|
output.cat = function (templates: HTMLCollectionOf<Element>) {
|
||||||
let html = ''
|
let html = ''
|
||||||
for (let i = 0; i < templates.length; i++) {
|
for (let i = 0; i < templates.length; i++) {
|
||||||
html += templates[i].innerHTML
|
html += templates[i].innerHTML
|
||||||
|
|||||||
@ -62,6 +62,97 @@ $.setValue = function (key: string, value: string, cb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface AjaxDetail {
|
||||||
|
url: string;
|
||||||
|
timeout: number;
|
||||||
|
responseType: XMLHttpRequestResponseType;
|
||||||
|
withCredentials: boolean;
|
||||||
|
type: string;
|
||||||
|
onprogress?: (e: ProgressEvent) => void;
|
||||||
|
form?: [string, string][];
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajaxPageInit = function (): void {
|
||||||
|
$.global(function (): void {
|
||||||
|
const r = new XMLHttpRequest()
|
||||||
|
window.FCX.requests = Object.create(null)
|
||||||
|
document.addEventListener('4chanXAjax', function (e): void {
|
||||||
|
let fd: FormData | null
|
||||||
|
const { url, timeout, responseType, withCredentials, type, onprogress, form, headers, id } = e.detail
|
||||||
|
window.FCX.requests[id] = (r = new XMLHttpRequest())
|
||||||
|
r.open(type, url, true)
|
||||||
|
const object = headers || {}
|
||||||
|
for (const key in object) {
|
||||||
|
const value = object[key]
|
||||||
|
r.setRequestHeader(key, value)
|
||||||
|
}
|
||||||
|
r.responseType = responseType === 'document' ? 'text' : responseType
|
||||||
|
r.timeout = timeout
|
||||||
|
r.withCredentials = withCredentials
|
||||||
|
if (onprogress) {
|
||||||
|
r.upload.onprogress = function (e: ProgressEvent) {
|
||||||
|
const { loaded, total } = e
|
||||||
|
const detail = { loaded, total, id }
|
||||||
|
return document.dispatchEvent(new CustomEvent('4chanXAjaxProgress', { bubbles: true, detail }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.onloadend = function (): void {
|
||||||
|
delete window.FCX.requests[id]
|
||||||
|
const { status, statusText, response } = this
|
||||||
|
const responseHeaderString = this.getAllResponseHeaders()
|
||||||
|
const detail = { status, statusText, response, responseHeaderString, id }
|
||||||
|
return document.dispatchEvent(new CustomEvent('4chanXAjaxLoadend', { bubbles: true, detail })) as any
|
||||||
|
}
|
||||||
|
// connection error or content blocker
|
||||||
|
r.onerror = function (): void {
|
||||||
|
if (!r.status) { return console.warn(`4chan X failed to load: ${url}`) }
|
||||||
|
}
|
||||||
|
if (form) {
|
||||||
|
fd = new FormData()
|
||||||
|
for (const entry of form) {
|
||||||
|
fd.append(entry[0], entry[1])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fd = null
|
||||||
|
}
|
||||||
|
return r.send(fd)
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
return document.addEventListener('4chanXAbort', function (e): void {
|
||||||
|
const { id } = e.detail
|
||||||
|
if (window.FCX.requests[id]) {
|
||||||
|
window.FCX.requests[id].abort()
|
||||||
|
return delete window.FCX.requests[id]
|
||||||
|
}
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
}, '4chanXAjax')
|
||||||
|
|
||||||
|
$.on(d, '4chanXAjaxProgress', function (e: CustomEvent<{ id: string; loaded: number; total: number }>): void {
|
||||||
|
let req: XMLHttpRequest
|
||||||
|
if (!(req = requests[e.detail.id])) { return }
|
||||||
|
return req.upload.onprogress.call(req.upload, e.detail)
|
||||||
|
})
|
||||||
|
|
||||||
|
return $.on(d, '4chanXAjaxLoadend', function (e: CustomEvent<AjaxDetail & { status: number; statusText: string; response: string; responseHeaderString: string }>): void {
|
||||||
|
let req: XMLHttpRequest
|
||||||
|
if (!(req = Request[e.detail.id])) { return }
|
||||||
|
delete Request[e.detail.id]
|
||||||
|
if (e.detail.status) {
|
||||||
|
for (const key of ['status', 'statusText', 'response', 'responseHeaderString']) {
|
||||||
|
req[key] = e.detail[key]
|
||||||
|
}
|
||||||
|
if (req.responseType === 'document') {
|
||||||
|
req.response = new DOMParser().parseFromString
|
||||||
|
(req.response, 'text/html')
|
||||||
|
}
|
||||||
|
return req.onloadend.call(req)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
$.ajaxPage = function (url: string, options: AjaxPageOptions) {
|
$.ajaxPage = function (url: string, options: AjaxPageOptions) {
|
||||||
const {
|
const {
|
||||||
responseType = 'json',
|
responseType = 'json',
|
||||||
@ -192,84 +283,7 @@ $.ajax = (function () {
|
|||||||
// # XXX https://bugs.chromium.org/p/chromium/issues/detail?id=920638
|
// # XXX https://bugs.chromium.org/p/chromium/issues/detail?id=920638
|
||||||
let requestID = 0
|
let requestID = 0
|
||||||
const requests = dict()
|
const requests = dict()
|
||||||
|
$.ajaxPageInit()
|
||||||
$.ajaxPageInit = function () {
|
|
||||||
$.global(function () {
|
|
||||||
window.FCX.requests = Object.create(null)
|
|
||||||
|
|
||||||
document.addEventListener('4chanXAjax', function (e: CustomEvent) {
|
|
||||||
let fd, r
|
|
||||||
const { url, timeout, responseType, withCredentials, type, onprogress, form, headers, id } = e.detail
|
|
||||||
window.FCX.requests[id] = (r = new XMLHttpRequest())
|
|
||||||
r.open(type, url, true)
|
|
||||||
const object = headers || {}
|
|
||||||
for (const key in object) {
|
|
||||||
const value = object[key]
|
|
||||||
r.setRequestHeader(key, value)
|
|
||||||
}
|
|
||||||
r.responseType = responseType === 'document' ? 'text' : responseType
|
|
||||||
r.timeout = timeout
|
|
||||||
r.withCredentials = withCredentials
|
|
||||||
if (onprogress) {
|
|
||||||
r.upload.onprogress = function (e) {
|
|
||||||
const { loaded, total } = e
|
|
||||||
const detail = { loaded, total, id }
|
|
||||||
return document.dispatchEvent(new CustomEvent('4chanXAjaxProgress', { bubbles: true, detail }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.onloadend = function () {
|
|
||||||
delete window.FCX.requests[id]
|
|
||||||
const { status, statusText, response } = this
|
|
||||||
const responseHeaderString = this.getAllResponseHeaders()
|
|
||||||
const detail = { status, statusText, response, responseHeaderString, id }
|
|
||||||
return document.dispatchEvent(new CustomEvent('4chanXAjaxLoadend', { bubbles: true, detail }))
|
|
||||||
}
|
|
||||||
// connection error or content blocker
|
|
||||||
r.onerror = function () {
|
|
||||||
if (!r.status) { return console.warn(`4chan X failed to load: ${url}`) }
|
|
||||||
}
|
|
||||||
if (form) {
|
|
||||||
fd = new FormData()
|
|
||||||
for (const entry of form) {
|
|
||||||
fd.append(entry[0], entry[1])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fd = null
|
|
||||||
}
|
|
||||||
return r.send(fd)
|
|
||||||
}
|
|
||||||
, false)
|
|
||||||
|
|
||||||
return document.addEventListener('4chanXAjaxAbort', function (e) {
|
|
||||||
let r
|
|
||||||
if (!(r = window.FCX.requests[e.detail.id])) { return }
|
|
||||||
return r.abort()
|
|
||||||
}
|
|
||||||
, false)
|
|
||||||
}, '4chanXAjax')
|
|
||||||
|
|
||||||
$.on(d, '4chanXAjaxProgress', function (e) {
|
|
||||||
let req
|
|
||||||
if (!(req = requests[e.detail.id])) { return }
|
|
||||||
return req.upload.onprogress.call(req.upload, e.detail)
|
|
||||||
})
|
|
||||||
|
|
||||||
return $.on(d, '4chanXAjaxLoadend', function (e) {
|
|
||||||
let req
|
|
||||||
if (!(req = requests[e.detail.id])) { return }
|
|
||||||
delete requests[e.detail.id]
|
|
||||||
if (e.detail.status) {
|
|
||||||
for (const key of ['status', 'statusText', 'response', 'responseHeaderString']) {
|
|
||||||
req[key] = e.detail[key]
|
|
||||||
}
|
|
||||||
if (req.responseType === 'document') {
|
|
||||||
req.response = new DOMParser().parseFromString(e.detail.response, 'text/html')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return req.onloadend()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return $.ajaxPage = function (url, options = {}) {
|
return $.ajaxPage = function (url, options = {}) {
|
||||||
let req: XMLHttpRequest
|
let req: XMLHttpRequest
|
||||||
const { onloadend, timeout, responseType, withCredentials, type, onprogress, headers } = options
|
const { onloadend, timeout, responseType, withCredentials, type, onprogress, headers } = options
|
||||||
@ -314,7 +328,7 @@ $.whenModified = function (url, bucket, cb, options = {}) {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
$.cache = function (url, cb, options = {}) {
|
$.cache = function (url, cb, options) {
|
||||||
const reqs = dict()
|
const reqs = dict()
|
||||||
let req
|
let req
|
||||||
const { ajax } = options
|
const { ajax } = options
|
||||||
@ -350,18 +364,9 @@ $.cleanCache = function (testf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$.cb = {
|
$.cb = function (cb: VoidCallback) {
|
||||||
checked() {
|
if (cb) {
|
||||||
if ($.hasOwn(Conf, this.name)) {
|
return cb()
|
||||||
$.set(this.name, this.checked, this.type)
|
|
||||||
return Conf[this.name] = this.checked
|
|
||||||
}
|
|
||||||
},
|
|
||||||
value() {
|
|
||||||
if ($.hasOwn(Conf, this.name)) {
|
|
||||||
$.set(this.name, this.value.trim(), this.type)
|
|
||||||
return Conf[this.name] = this.value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,7 +497,7 @@ $.one = function (el, events, handler) {
|
|||||||
return $.on(el, events, cb)
|
return $.on(el, events, cb)
|
||||||
}
|
}
|
||||||
let cloneInto: (obj: object, win: Window) => object
|
let cloneInto: (obj: object, win: Window) => object
|
||||||
$.event = function (event: Event, detail: object, root = d) {
|
$.event = function (event: string, detail: object, root = d) {
|
||||||
if (!globalThis.chrome?.extension) {
|
if (!globalThis.chrome?.extension) {
|
||||||
if ((detail != null) && (typeof cloneInto === 'function')) {
|
if ((detail != null) && (typeof cloneInto === 'function')) {
|
||||||
detail = cloneInto(detail, d.defaultView)
|
detail = cloneInto(detail, d.defaultView)
|
||||||
@ -978,7 +983,7 @@ if (platform === 'crx') {
|
|||||||
})
|
})
|
||||||
$.forceSync = function () {/* empty */ }
|
$.forceSync = function () {/* empty */ }
|
||||||
} else if ((typeof GM_deleteValue !== 'undefined' && GM_deleteValue !== null) || $.hasStorage) {
|
} else if ((typeof GM_deleteValue !== 'undefined' && GM_deleteValue !== null) || $.hasStorage) {
|
||||||
$.sync = function (key, cb) {
|
$.sync = function (key: string, cb: (newValue: any, key: string) => void) {
|
||||||
key = g.NAMESPACE + key
|
key = g.NAMESPACE + key
|
||||||
$.syncing[key] = cb
|
$.syncing[key] = cb
|
||||||
return $.oldValue[key] = $.getValue(key, cb)
|
return $.oldValue[key] = $.getValue(key, cb)
|
||||||
@ -1000,10 +1005,7 @@ if (platform === 'crx') {
|
|||||||
}
|
}
|
||||||
$.on(window, 'storage', onChange)
|
$.on(window, 'storage', onChange)
|
||||||
|
|
||||||
return $.forceSync = function (key, cb) {
|
return $.forceSync = function (key: string, cb: (newValue: any, key: string) => void) {
|
||||||
// Storage events don't work across origins
|
|
||||||
// e.g. http://boards.4chan.org and https://boards.4chan.org
|
|
||||||
// so force a check for changes to avoid lost data.
|
|
||||||
key = g.NAMESPACE + key
|
key = g.NAMESPACE + key
|
||||||
return onChange({ key, newValue: $.getValue(key, cb) })
|
return onChange({ key, newValue: $.getValue(key, cb) })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ const SWTinyboard = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ID: 'sw-tinyboard',
|
||||||
name: 'Tinyboard',
|
name: 'Tinyboard',
|
||||||
software: 'Tinyboard',
|
software: 'Tinyboard',
|
||||||
isOPContainerThread: true,
|
isOPContainerThread: true,
|
||||||
|
|||||||
5
src/types/globals.d.ts
vendored
5
src/types/globals.d.ts
vendored
@ -16,4 +16,9 @@ export interface File {
|
|||||||
sizeInBytes: number
|
sizeInBytes: number
|
||||||
isDead: boolean
|
isDead: boolean
|
||||||
docIndex: number
|
docIndex: number
|
||||||
|
}
|
||||||
|
export interface CacheOptions {
|
||||||
|
dataType: string
|
||||||
|
sync: boolean
|
||||||
|
dontClean: boolean
|
||||||
}
|
}
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
//TODO: Flip this to true
|
//TODO: Flip this to true
|
||||||
"strict": false,
|
"strict": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"jsxFactory": "h",
|
"jsxFactory": "h",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user