Open ngdangtu-vn opened 11 months ago
The GM_getResourceText
doesn't work as well.
@run-at document-body
document-body
is not supported in FM|GM|VM. It will default to document-idle
in FireMonkey.
It wasn't like this in Tampermonkey.
Does it work in Violentmonkey?
document-body is not supported in FM|GM|VM. It will default to document-idle in FireMonkey.
Yeah I also found after submit the issue, still, the unsafeWindow
is not available even after I set document-end
to meta @run-at
.
Does it work in Violentmonkey?
Yes, it works ok.
More info: Because unsafeWindow
didn't work, I switched to window.wrappedJSObject
, so it runs now. However, GM_getResourceText
is the next undefined value. One funny thing is I still got the error Failed to insert unsafeWindow is not defined
when I tried to wrap it inside another variable for compatibility with tampermonkey:
const uw = unsafeWindow ?? window.wrappedJSObject // Fail with same error
const uw = unsafeWindow || window.wrappedJSObject // Fail with same error
It like the unsafeWindow
is treated as function and demand to executed immediately :? Funny right?
Also, the @require
doesn't seems to work as well. Like this is the userscript before compiled:
// ==UserScript==
// @name Dynasty Scans Chapter Caching
// @version 0.0.1
// @description Caching chapters so you don't have to reload it everytime you want to read it again.
// @author ngdangtu
// @namespace https://userscript.ngdangtu.dev/dynasty-scans.com
// @icon https://icons.duckduckgo.com/i/dynasty-scans.com.ico
// @supportURL https://gitlab.com/ndt-browserkit/userscript/-/issues/new
// @updateURL https://gitlab.com/ndt-browserkit/userscript/-/raw/main/dynasty-scans.com/chapter.js
// @match *://dynasty-scans.com/chapters/*
// @run-at document-end
// @resource style https://gitlab.com/ndt-browserkit/userscript/-/raw/main/dynasty-scans.com/style/chapter.css
// @grant unsafeWindow
// @grant GM_getResourceText
// @require https://gitlab.com/ndt-browserkit/userscript/-/raw/main/lib/utility.js
// @require https://gitlab.com/ndt-browserkit/userscript/-/raw/main/lib/cache.js
// @require https://gitlab.com/ndt-browserkit/userscript/-/raw/main/lib/dom.js
// @require https://gitlab.com/ndt-browserkit/userscript/-/raw/main/dynasty-scans.com/lib/cache.js
// ==/UserScript==
/**
* @TODO remove this when I have better solution.
*
* Require cache.js in here as a temporary solution
* as FireMonkey doesn't support nesting meta require yet.
*/
/** ⦿ Predefined Global Variables */
const uw = window.wrappedJSObject
window.is_load = false // true if all chapter's images are loaded.
window.no_offline_cache = true // true if user decides to keep cache
const doc = uw.document
/** ⦿ Setup Style */
doc.head.innerHTML += `<style>${"GM_getResourceText('style')"}</style>`
/** ⦿ Preparation */
const is_mobile = matchMedia('(max-width: 767px)')
const dc = DsCache.chapter(window.location.pathname.split('/').pop())
const reader =
{
pg_ls: new Map(),
el_self: doc.querySelector('#reader'),
el_display: doc.querySelector('#image'),
get_pad: (up_scale) => (is_mobile.matches ? 10 : 120) * up_scale, // responsive #reader{padding-inline}
get_width: function () { return this.el_self.offsetWidth - this.get_pad(2) },
save_pg: async function (inx, req)
{
const blob = req instanceof Response
? req.blob()
: await dc.get_blob(req)
if (!blob) return false
this.pg_ls.set('pg-' + inx, {
blob: URL.createObjectURL(blob),
sz: await get_imgsz(blob),
})
return true
}
}
/** ⦿ Setup New Components */
const tpml_btn = tmpl_el('a', null, {
'class': ['btn', 'btn-mini'],
'href': 'javascript:void 0'
})
const { el_toolbar, el_btn_preload, el_btn_cache, el_btn_clear } = emt(
'menu', 'el_toolbar', { 'class': 'btn-toolbar' },
emt('li', 'el_btn_grp', { 'class': 'btn-group' }, {
'el_btn_preload': tpml_btn(null, `<i class='icon-download'></i> Preload`),
'el_btn_cache': tpml_btn(null, `<i class='icon-download-alt'></i> Cache NOW`),
// 'el_btn_reload': tpml_btn(null, `<i class='icon-refresh'></i> Force Reload`),
'el_btn_clear': tpml_btn({ 'disabled': true }, `<i class='icon-trash'></i> Clear Cache`),
})
)
reader.el_self.prepend(el_toolbar)
/** ⦿ Helper Functions */
const set_btn_on = (btn) => btn.setAttribute('disabled', false)
const set_btn_off = (btn) => btn.setAttribute('disabled', true)
function get_id(inx = null)
{
if (['number', 'string'].includes(typeof inx)) return 'pg-' + inx
const { hash } = doc.location
if (!hash) return 'pg-1'
return hash.toLowerCase() === '#last'
? 'pg-' + uw.pages.length
: hash.replace(/^\#/, 'pg-')
}
/** ⦿ Action Functions */
function resize_img({ width: w, height: h })
{
const max_width = reader.get_width()
const max_height = 1200
if (is_mobile.matches) return {
w: max_width,
h: Math.floor(max_width * h / w)
}
const xw = Math.min(w, max_width)
const xh = Math.min(h, max_height)
const is_portrait = h > w
return is_portrait
? { h: xh, w: Math.floor(xh * w / h) }
: { w: xw, h: Math.floor(xw * h / w) }
}
async function show_img(inx = null)
{
const pg = reader.pg_ls.get(get_id(inx))
if (!pg) return void 0
window.is_load && uw.stop()
reader.el_display.querySelector('img')?.remove()
const { w, h } = resize_img(pg.sz)
set_el_attr(reader.el_display, {
'--w': w + 'px',
'--h': h + 'px',
'--xw': pg.sz.width + 'px',
'--xh': pg.sz.height + 'px',
'--img': `url(${pg.blob})`,
})
}
async function show_thumb(i, data)
{
if (!i || !data) return void 0
const query = `.pages-list a:nth-of-type(${i + 1})`// Index must start from 1 + 1 next nav_item (not .page)
const el = reader.el_display.querySelector(query)
el.style.backgroundImage = `url(${data.blob})`
el.style.paddingBlockStart = `${el.clientWidth * data.sz.height / data.sz.width}px`
}
async function prepare_img(check_only = false)
{
const ls = uw.pages
const dl_ls_status = []
for (let i = 0; i < ls.length; i++)
{
const url = window.location.origin + ls[i].image
const load_or_reuse = check_only ? await dc.match(url) : url
const result = await reader.save_pg(i + 1, load_or_reuse)
const status = typeof result === 'object'
if (status) show_thumb(i + 1, result)
dl_ls_status.push(status)
}
window.is_load = dl_ls_status.reduce((prv, cur) => prv && cur, true)
if (window.is_load || check_only) reader
.el_display.querySelector('.pages-list')
.classList.add('loaded')
console.log(check_only ? 'Checking Complete :3' : 'Load Complete :D')
}
/** ⦿ Window Events */
uw.addEventListener(
'beforeunload',
_ => window.no_offline_cache && dc.drop_current_cache()
)
/** ⦿ Component Events */
el_btn_preload.addEventListener('click', e =>
{
set_btn_off(e.currentTarget)
window.no_offline_cache = true
prepare_img()
})
el_btn_cache.addEventListener('click', async e =>
{
set_btn_off(e.currentTarget)
set_btn_off(el_btn_preload)
window.no_offline_cache = false
await prepare_img()
set_btn_on(el_btn_clear)
})
el_btn_clear.addEventListener('click', async e =>
{
set_btn_off(e.currentTarget)
const is_done = await dc.drop_current_cache()
if (is_done) set_btn_on(el_btn_cache)
})
/** ⦿ MAIN */
prepare_img(true).then(show_img)
uw.addEventListener('hashchange', show_img)
It failed to fetch file cache.js from https://gitlab.com/ndt-browserkit/userscript/-/raw/main/dynasty-scans.com/lib/cache.js
Btw, I update my pc spec in case you need.
@erosman For now, I've moved on this issue by changing the @run-at
to document-end
and @inject-into page
(I don't know how this works tbh). However, the behaviou is nothing like in the doc. I think document-start
will favor window.wrappedJSObject
and document-end
favors unsafeWindow
. By favouring, I mean window.wrappedJSObject
can't be used in document-end
and vice versa.
unsafeWindow
is simply the page window.wrappedJSObject
in normal injection and window
in page
context.
There is no need to swap them.
At document-start
, page window may have not loaded so it can fail in any userscript script manager.
document-end
& document-idle
doesn't affect unsafeWindow
.
@inject-into page
In this option, there will be no GM API support (except GM info). See also: FireMonkey Help: inject-into
In this option, there will be no GM API support (except GM info).
But without that option, I will not be able to use unsafeWindow
.
unsafeWindow
is designed to give the userscripts access to the window
of the webpage, when userscript is running in OTHER contexts such as conteScripts
or userScripts
context.
If there script is injected into the page
context i.e. webpage, there is no real need for it since the window
in page
context is directly accessible by the userscript.
If you post a minimal test script, I can test what you are trying to achieve.
In the document:
But my script couldn't use it. Here is my code:
It wasn't like this in Tampermonkey. What should I fix?
UPDATE: pc spec