6.2.0 - 重新设计及编写项目文档; 新增多语言适配; 丰富控件选择器功能; 优化夜间模式适配等
This commit is contained in:
197
app/src/main/assets/modules/__Arrayx__.js
Normal file
197
app/src/main/assets/modules/__Arrayx__.js
Normal file
@@ -0,0 +1,197 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { util, plugins } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Arrayx}
|
||||
*/
|
||||
module.exports = (scriptRuntime, scope) => {
|
||||
let _ = {
|
||||
ArrayxCtor: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Arrayx
|
||||
*/
|
||||
const ArrayxCtor = function () {
|
||||
return Object.assign(Array.bind(Array), ArrayxCtor.prototype);
|
||||
};
|
||||
|
||||
ArrayxCtor.prototype = {
|
||||
constructor: ArrayxCtor,
|
||||
// assureArray(o) {
|
||||
// if (Array.isArray(o)) {
|
||||
// return o;
|
||||
// }
|
||||
// if (isObjectSpecies(o) && typeof o.length === 'number' && o.length >= 0) {
|
||||
// return Array.from(o);
|
||||
// }
|
||||
// return [ o ];
|
||||
// },
|
||||
ensureArray() {
|
||||
Array.from(arguments).forEach(o => util.ensureArrayType(o));
|
||||
},
|
||||
distinct(arr) {
|
||||
Arrayx.ensureArray(arr);
|
||||
return Array.from(new Set(arr));
|
||||
},
|
||||
distinctBy(arr, selector) {
|
||||
Arrayx.ensureArray(arr);
|
||||
let res = [];
|
||||
let cache = [];
|
||||
arr.forEach(e => {
|
||||
let selected = selector(e);
|
||||
if (!cache.includes(selected)) {
|
||||
cache.push(selected);
|
||||
res.push(e);
|
||||
}
|
||||
});
|
||||
return res;
|
||||
},
|
||||
/**
|
||||
* TODO by SuperMonster003 on Jan 21, 2023.
|
||||
* ! Better performance.
|
||||
*/
|
||||
union(arr, others) {
|
||||
Arrayx.ensureArray(arr);
|
||||
let res = Array.from(arguments).slice(1).reduce((a, b) => {
|
||||
return Array.isArray(b) ? a.concat(b) : a.concat([ b ]);
|
||||
}, arr);
|
||||
return Arrayx.distinct(res);
|
||||
},
|
||||
/**
|
||||
* TODO by SuperMonster003 on Jan 21, 2023.
|
||||
* ! Better performance.
|
||||
*/
|
||||
intersect(arr, others) {
|
||||
Arrayx.ensureArray(arr);
|
||||
if (arr.length === 0 || arguments.length <= 1) {
|
||||
return [];
|
||||
}
|
||||
return Arrayx.distinct(arr).filter((o) => {
|
||||
return Array.from(arguments).slice(1).every((e) => {
|
||||
return Array.isArray(e) ? Arrayx.distinct(e).includes(o) : e === o;
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* TODO by SuperMonster003 on Jan 21, 2023.
|
||||
* ! Necessary or not ?
|
||||
*/
|
||||
different() {
|
||||
throw Error('TODO');
|
||||
},
|
||||
sortBy(arr, selector) {
|
||||
Arrayx.ensureArray(arr);
|
||||
if (arr.length < 2) {
|
||||
return arr;
|
||||
}
|
||||
return arr.sort((a, b) => {
|
||||
let sA = selector(a);
|
||||
let sB = selector(b);
|
||||
return sA === sB ? 0 : sA > sB ? 1 : -1;
|
||||
});
|
||||
},
|
||||
sortDescending(arr) {
|
||||
Arrayx.ensureArray(arr);
|
||||
if (arr.length < 2) {
|
||||
return arr;
|
||||
}
|
||||
return arr.sort(_.bySimpleCompare).reverse();
|
||||
},
|
||||
sortByDescending(arr, selector) {
|
||||
Arrayx.ensureArray(arr);
|
||||
if (arr.length < 2) {
|
||||
return arr;
|
||||
}
|
||||
return arr.sort((a, b) => {
|
||||
let sA = selector(a);
|
||||
let sB = selector(b);
|
||||
return sA === sB ? 0 : sA > sB ? -1 : 1;
|
||||
});
|
||||
},
|
||||
sorted(arr) {
|
||||
Arrayx.ensureArray(arr);
|
||||
return arr.slice().sort(_.bySimpleCompare);
|
||||
},
|
||||
sortedBy(arr, selector) {
|
||||
Arrayx.ensureArray(arr);
|
||||
let copy = arr.slice();
|
||||
if (copy.length < 2) {
|
||||
return copy;
|
||||
}
|
||||
return this.sortBy(copy, selector);
|
||||
},
|
||||
sortedDescending(arr) {
|
||||
Arrayx.ensureArray(arr);
|
||||
let copy = arr.slice();
|
||||
if (copy.length < 2) {
|
||||
return copy;
|
||||
}
|
||||
return this.sortDescending(copy);
|
||||
},
|
||||
sortedByDescending(arr, selector) {
|
||||
Arrayx.ensureArray(arr);
|
||||
let copy = arr.slice();
|
||||
if (copy.length < 2) {
|
||||
return copy;
|
||||
}
|
||||
return this.sortByDescending(arr, selector);
|
||||
},
|
||||
shuffle(arr) {
|
||||
return arr.sort(() => Math.random() >= 0.5 ? 1 : -1);
|
||||
},
|
||||
};
|
||||
|
||||
return ArrayxCtor;
|
||||
})(),
|
||||
bySimpleCompare: (a, b) => a === b ? 0 : a > b ? 1 : -1,
|
||||
registerPluginModule() {
|
||||
plugins.extend.registerModule({
|
||||
Arrayx: {
|
||||
protoKeys: {
|
||||
intersect: 0,
|
||||
union: 0,
|
||||
distinct: 0,
|
||||
distinctBy: 0,
|
||||
sortBy: 0,
|
||||
sortDescending: 0,
|
||||
sortByDescending: 0,
|
||||
sorted: 0,
|
||||
sortedBy: 0,
|
||||
sortedDescending: 0,
|
||||
sortedByDescending: 0,
|
||||
shuffle: 0,
|
||||
},
|
||||
extendJsBuildInObjects() {
|
||||
let that = this;
|
||||
Object.keys(_.ArrayxCtor.prototype).forEach((key) => {
|
||||
if (!(key in that.protoKeys)) {
|
||||
Array[key] = Arrayx[key];
|
||||
return;
|
||||
}
|
||||
if (typeof that.protoKeys[key] !== 'number') {
|
||||
Array.prototype[key] = Arrayx[key];
|
||||
return;
|
||||
}
|
||||
Array.prototype[key] = function () {
|
||||
const args = Array.from(arguments);
|
||||
args.splice(that.protoKeys[key], 0, this.valueOf());
|
||||
return Arrayx[key].apply(Arrayx, args);
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Arrayx}
|
||||
*/
|
||||
const Arrayx = new _.ArrayxCtor();
|
||||
|
||||
_.registerPluginModule();
|
||||
|
||||
return Arrayx;
|
||||
};
|
||||
223
app/src/main/assets/modules/__Mathx__.js
Normal file
223
app/src/main/assets/modules/__Mathx__.js
Normal file
@@ -0,0 +1,223 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { plugins, Arrayx, Numberx } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Mathx}
|
||||
*/
|
||||
module.exports = (scriptRuntime, scope) => {
|
||||
let _ = {
|
||||
MathxCtor: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Mathx
|
||||
*/
|
||||
const MathxCtor = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
MathxCtor.prototype = {
|
||||
constructor: MathxCtor,
|
||||
randInt(range) {
|
||||
let args = Array.from(arguments);
|
||||
if (args.length === 0) {
|
||||
return Mathx.randInt(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
||||
}
|
||||
if (args.length === 1) {
|
||||
if (Array.isArray(args[0])) {
|
||||
return Mathx.randInt.apply(Mathx, args.flat(Infinity));
|
||||
}
|
||||
util.ensureNumberType(args[0]);
|
||||
return args[0] > 0
|
||||
? Mathx.randInt(0, args[0])
|
||||
: Mathx.randInt(args[0], 0);
|
||||
}
|
||||
let ranges = Arrayx.distinct(Arrayx.sorted(args.flat(Infinity).map(o => Number(o)).filter(o => !isNaN(o))));
|
||||
let min, max;
|
||||
util.ensureNumberType(min = Math.ceil(ranges.at(0)));
|
||||
util.ensureNumberType(max = Math.floor(ranges.at(-1)));
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
},
|
||||
sum(num, fraction) {
|
||||
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
|
||||
if (!nums.length || nums.includes(NaN)) {
|
||||
return NaN;
|
||||
}
|
||||
let sum = nums.reduce((x, y) => Number(x) + Number(y));
|
||||
let fracInt = parseInt(frac);
|
||||
return isNaN(fracInt) ? sum : Numberx.toFixedNum(sum, fracInt);
|
||||
},
|
||||
avg(num, fraction) {
|
||||
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
|
||||
if (!nums.length || nums.includes(NaN)) {
|
||||
return NaN;
|
||||
}
|
||||
let sum = Mathx.sum(nums);
|
||||
let avg = sum / nums.length;
|
||||
let fracInt = parseInt(frac);
|
||||
return isNaN(fracInt) ? avg : Numberx.toFixedNum(avg, fracInt);
|
||||
},
|
||||
median(num, fraction) {
|
||||
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
|
||||
Arrayx.sortBy(nums, Number);
|
||||
let len = nums.length;
|
||||
if (!len || nums.includes(NaN)) {
|
||||
return NaN;
|
||||
}
|
||||
let med = len % 2
|
||||
? nums[Math.floor(len / 2)]
|
||||
: (nums[len / 2 - 1] + nums[len / 2]) / 2;
|
||||
let fracInt = parseInt(frac);
|
||||
return isNaN(fracInt) ? med : Numberx.toFixedNum(med, fracInt);
|
||||
},
|
||||
var(num, fraction) {
|
||||
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
|
||||
let avg = Mathx.avg(nums);
|
||||
let len = nums.length;
|
||||
if (!len || nums.includes(NaN)) {
|
||||
return NaN;
|
||||
}
|
||||
let acc = 0;
|
||||
for (let i = 0; i < len; i += 1) {
|
||||
acc += (nums[i] - avg) ** 2;
|
||||
}
|
||||
let res = acc / len;
|
||||
let fracInt = parseInt(frac);
|
||||
return isNaN(fracInt) ? res : Numberx.toFixedNum(res, fracInt);
|
||||
},
|
||||
std(num, fraction) {
|
||||
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
|
||||
if (!nums.length || nums.includes(NaN)) {
|
||||
return NaN;
|
||||
}
|
||||
let std = Math.sqrt(Mathx.var(nums));
|
||||
let fracInt = parseInt(frac);
|
||||
return isNaN(fracInt) ? std : Numberx.toFixedNum(std, fracInt);
|
||||
},
|
||||
cv(num, fraction) {
|
||||
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
|
||||
let len = nums.length;
|
||||
if (len < 2 || nums.includes(NaN)) {
|
||||
return NaN;
|
||||
}
|
||||
|
||||
let avg = Mathx.avg(nums);
|
||||
let acc = 0;
|
||||
for (let i = 0; i < len; i += 1) {
|
||||
acc += (nums[i] - avg) ** 2;
|
||||
}
|
||||
/**
|
||||
* Sample Standard Deviation (zh-CN: 样本标准差)
|
||||
*/
|
||||
let ssd = Math.pow(acc / (len - 1), 0.5);
|
||||
let cv = ssd / avg;
|
||||
let fracInt = parseInt(frac);
|
||||
return isNaN(fracInt) ? cv : Numberx.toFixedNum(cv, fracInt);
|
||||
},
|
||||
max(num, fraction) {
|
||||
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
|
||||
let max = Math.max.apply(null, nums);
|
||||
let fracInt = parseInt(frac);
|
||||
return isNaN(fracInt) ? max : Numberx.toFixedNum(max, fracInt);
|
||||
},
|
||||
min(num, fraction) {
|
||||
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
|
||||
let max = Math.min.apply(null, nums);
|
||||
let fracInt = parseInt(frac);
|
||||
return isNaN(fracInt) ? max : Numberx.toFixedNum(max, fracInt);
|
||||
},
|
||||
dist(pointA, pointB, fraction) {
|
||||
if (pointA instanceof android.graphics.Rect) {
|
||||
if (arguments.length === 1) {
|
||||
return Mathx.dist({ x: pointA.left, y: pointA.top }, { x: pointA.right, y: pointA.bottom });
|
||||
}
|
||||
if (arguments.length === 2 && typeof arguments[1] === 'number') {
|
||||
return Mathx.dist({ x: pointA.left, y: pointA.top }, { x: pointA.right, y: pointA.bottom }, /* fraction = */ arguments[1]);
|
||||
}
|
||||
}
|
||||
let a = _.toPoint(pointA);
|
||||
let b = _.toPoint(pointB);
|
||||
let fracInt = Math.trunc(fraction);
|
||||
let res = Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);
|
||||
return isNaN(fracInt) ? res : Numberx.toFixedNum(res, fracInt);
|
||||
},
|
||||
logMn(base, antilogarithm, fraction) {
|
||||
let _frac = typeof fraction === 'number' ? fraction : 13;
|
||||
let _result = Math.log(antilogarithm) / Math.log(base);
|
||||
if (isNaN(_result) || !isFinite(_result) || _frac !== -1) {
|
||||
return _result;
|
||||
}
|
||||
return Number(_result.toFixed(_frac));
|
||||
},
|
||||
floorLog(base, antilogarithm) {
|
||||
return Math.floor(Mathx.logMn(base, antilogarithm));
|
||||
},
|
||||
ceilLog(base, antilogarithm) {
|
||||
return Math.ceil(Mathx.logMn(base, antilogarithm));
|
||||
},
|
||||
roundLog(base, antilogarithm) {
|
||||
return Math.round(Mathx.logMn(base, antilogarithm));
|
||||
},
|
||||
floorPow(base, power) {
|
||||
return Math.pow(base, Mathx.floorLog(base, power));
|
||||
},
|
||||
ceilPow(base, power) {
|
||||
return Math.pow(base, Mathx.ceilLog(base, power));
|
||||
},
|
||||
roundPow(base, power) {
|
||||
return Math.pow(base, Mathx.roundLog(base, power));
|
||||
},
|
||||
};
|
||||
|
||||
return MathxCtor;
|
||||
})(),
|
||||
parseArgs(nums, fraction) {
|
||||
if (Array.isArray(nums)) {
|
||||
return [ nums.flat(Infinity), fraction ];
|
||||
}
|
||||
return [ Array.from(arguments).flat(Infinity) ];
|
||||
},
|
||||
toPoint(o) {
|
||||
if (Array.isArray(o)) {
|
||||
if (o.length !== 2) {
|
||||
throw Error('Points array must be length of 2');
|
||||
}
|
||||
return { x: Number(o[0]), y: Number(o[1]) };
|
||||
}
|
||||
if (o instanceof android.graphics.Rect) {
|
||||
// @Hint by SuperMonster003 on Oct 28, 2022.
|
||||
// ! centerX or centerY will lose the precision.
|
||||
return { x: o.exactCenterX(), y: o.exactCenterY() };
|
||||
}
|
||||
if (o instanceof org.opencv.core.Point) {
|
||||
return { x: o.x, y: o.y };
|
||||
}
|
||||
return isObjectSpecies(o) ? o : {};
|
||||
},
|
||||
registerPluginModule() {
|
||||
plugins.extend.registerModule({
|
||||
Mathx: {
|
||||
extendJsBuildInObjects() {
|
||||
let mapper = {
|
||||
max: 'maxi',
|
||||
min: 'mini',
|
||||
};
|
||||
Object.keys(_.MathxCtor.prototype).forEach((key) => {
|
||||
Math[key in mapper ? mapper[key] : key] = Mathx[key];
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Mathx}
|
||||
*/
|
||||
const Mathx = new _.MathxCtor();
|
||||
|
||||
_.registerPluginModule();
|
||||
|
||||
return Mathx;
|
||||
};
|
||||
227
app/src/main/assets/modules/__Numberx__.js
Normal file
227
app/src/main/assets/modules/__Numberx__.js
Normal file
@@ -0,0 +1,227 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { util, plugins } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Numberx}
|
||||
*/
|
||||
module.exports = (scriptRuntime, scope) => {
|
||||
let _ = {
|
||||
compareOperators: {
|
||||
'<': (a, b) => a < b,
|
||||
'<=': (a, b) => a <= b,
|
||||
'>': (a, b) => a > b,
|
||||
'>=': (a, b) => a >= b,
|
||||
'=': (a, b) => a === b,
|
||||
},
|
||||
NumberxCtor: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Numberx
|
||||
*/
|
||||
const NumberxCtor = function () {
|
||||
return Object.assign(Number.bind(Number), NumberxCtor.prototype);
|
||||
};
|
||||
|
||||
NumberxCtor.prototype = {
|
||||
constructor: NumberxCtor,
|
||||
ICU: ( /* @IIFE */ () => {
|
||||
const workdays = 5;
|
||||
const weekends = 2;
|
||||
const health = 'Your health';
|
||||
const evil = 'Hard working only';
|
||||
|
||||
return Math.round(evil
|
||||
.split(new RegExp(`[${health.toLowerCase()}]`))
|
||||
.map(x => x ? x.codePointAt(0) : 996 / workdays / weekends - weekends)
|
||||
.reduce((x, y) => x + y));
|
||||
})(),
|
||||
prototype: Number.prototype,
|
||||
ensureNumber() {
|
||||
Array.from(arguments).forEach(o => util.ensureNumberType(o));
|
||||
},
|
||||
check() {
|
||||
if (arguments.length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (arguments.length === 1) {
|
||||
return typeof arguments[0] === 'number';
|
||||
}
|
||||
if (arguments.length === 2) {
|
||||
let numA = arguments[0];
|
||||
let numB = arguments[1];
|
||||
return this.check(numA) && this.check(numB) && numA === numB;
|
||||
}
|
||||
for (let i = 1; i < arguments.length; i += 2) {
|
||||
let opr = arguments[i]; // operator string
|
||||
if (typeof opr !== 'string' || !(opr in _.compareOperators)) {
|
||||
throw Error(`arguments[${i}] for Numberx.check must be an operator rather than ${typeof opr === 'string' ? `"${opr}"` : opr}`);
|
||||
}
|
||||
let b = arguments[i + 1];
|
||||
if (typeof b !== 'number') {
|
||||
throw Error(`arguments[${i + 1}] for Numberx.check must be a number rather than ${typeof b === 'string' ? `"${b}"` : b}`);
|
||||
}
|
||||
let a = arguments[i - 1];
|
||||
if (!_.compareOperators[opr](a, b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
clamp(num, clamps) {
|
||||
Numberx.ensureNumber(num);
|
||||
if (!Array.isArray(clamps)) {
|
||||
clamps = Array.from(arguments).slice(1) || [];
|
||||
}
|
||||
let sortedClamps = clamps
|
||||
.flat()
|
||||
.filter(x => !isNaN(Number(x)))
|
||||
.sort((x, y) => x - y);
|
||||
if (sortedClamps.length > 0) {
|
||||
let min = sortedClamps.at(0);
|
||||
let max = sortedClamps.at(-1);
|
||||
if (num < min) return min;
|
||||
if (num > max) return max;
|
||||
}
|
||||
return num;
|
||||
},
|
||||
clampTo(num, range, cycle) {
|
||||
let sortedClamps = range
|
||||
.flat()
|
||||
.filter(x => !isNaN(Number(x)))
|
||||
.sort((x, y) => x - y);
|
||||
if (sortedClamps.length > 0) {
|
||||
let min = sortedClamps.at(0);
|
||||
let max = sortedClamps.at(-1);
|
||||
let t = typeof cycle === 'number' ? cycle : max - min;
|
||||
if (t <= 0) {
|
||||
throw RangeError(`Cycle must be a positive number`);
|
||||
}
|
||||
if (num < min) {
|
||||
num += Math.ceil((min - num) / t) * t;
|
||||
} else if (num > max) {
|
||||
num -= Math.ceil((num - max) / t) * t;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
},
|
||||
toFixedNum(num, fraction) {
|
||||
Numberx.ensureNumber(num);
|
||||
return Number(num.toFixed(fraction));
|
||||
},
|
||||
padStart(num, targetLength, pad) {
|
||||
Numberx.ensureNumber(num);
|
||||
let s = num.toString();
|
||||
return s.padStart.call(s, targetLength, pad || 0);
|
||||
},
|
||||
padEnd(num, targetLength, pad) {
|
||||
Numberx.ensureNumber(num);
|
||||
let s = num.toString();
|
||||
return s.padEnd.call(s, targetLength, pad || 0);
|
||||
},
|
||||
parseFloat(string, radix) {
|
||||
if (radix === undefined) {
|
||||
return _.oriParseFloat(string);
|
||||
}
|
||||
if (typeof string !== 'string') {
|
||||
if ('toString' in string && typeof string.toString === 'function') {
|
||||
string = string.toString();
|
||||
} else {
|
||||
string = String(string);
|
||||
}
|
||||
}
|
||||
// @Reference by SuperMonster003 on Nov 1, 2022.
|
||||
// ! to https://stackoverflow.com/questions/37109968/how-to-convert-binary-fraction-to-decimal
|
||||
return Number.parseInt(string.replace('.', ''), radix) / radix ** (string.split('.')[1] || '').length;
|
||||
},
|
||||
/**
|
||||
* @example
|
||||
* Numberx.parsePercent('1%'); // 0.01
|
||||
* Numberx.parsePercent('1%%'); // 0.0001
|
||||
*/
|
||||
parsePercent(percent) {
|
||||
if (typeof percent === 'number') {
|
||||
return percent;
|
||||
}
|
||||
let matchArray = String(percent).replace(/\s*/g, '').match(/^([+-]?\d+(?:\.\d+)?)(%*)$/);
|
||||
return matchArray ? matchArray[1] / 100 ** matchArray[2].length : NaN;
|
||||
},
|
||||
/**
|
||||
* @example
|
||||
* Numberx.parseRatio('3:2'); // 1.5
|
||||
*/
|
||||
parseRatio(ratio) {
|
||||
let [ x, y ] = String(ratio).split(':').map(s => s.trim());
|
||||
return parseFloat(x) / parseFloat(y);
|
||||
},
|
||||
parseAny(s) {
|
||||
if (typeof s === 'number') {
|
||||
return s;
|
||||
}
|
||||
if (typeof s !== 'string') {
|
||||
s = String(s);
|
||||
}
|
||||
s = s.trim();
|
||||
if (s.includes(':')) {
|
||||
return this.parseRatio(s);
|
||||
}
|
||||
if (s.includes('%')) {
|
||||
return this.parsePercent(s);
|
||||
}
|
||||
return Number(s);
|
||||
},
|
||||
};
|
||||
|
||||
return NumberxCtor;
|
||||
})(),
|
||||
oriParseFloat: Number.parseFloat.bind(Number),
|
||||
registerPluginModule() {
|
||||
plugins.extend.registerModule({
|
||||
Numberx: {
|
||||
protoKeys: {
|
||||
clamp: 0,
|
||||
clampTo: 0,
|
||||
toFixedNum: 0,
|
||||
padStart: 0,
|
||||
padEnd: 0,
|
||||
parseFloat() {
|
||||
global.parseFloat = Number.parseFloat = Numberx.parseFloat;
|
||||
},
|
||||
},
|
||||
extendJsBuildInObjects() {
|
||||
let that = this;
|
||||
Object.keys(_.NumberxCtor.prototype).forEach((key) => {
|
||||
if (!(key in that.protoKeys)) {
|
||||
Number[key] = Numberx[key];
|
||||
return;
|
||||
}
|
||||
if (typeof that.protoKeys[key] === 'function') {
|
||||
that.protoKeys[key].call(that.protoKeys);
|
||||
return;
|
||||
}
|
||||
if (typeof that.protoKeys[key] === 'number') {
|
||||
Number.prototype[key] = function () {
|
||||
const args = Array.from(arguments);
|
||||
args.splice(that.protoKeys[key], 0, this.valueOf());
|
||||
return Numberx[key].apply(Numberx, args);
|
||||
};
|
||||
return;
|
||||
}
|
||||
Number.prototype[key] = Numberx[key];
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Numberx}
|
||||
*/
|
||||
const Numberx = new _.NumberxCtor();
|
||||
|
||||
_.registerPluginModule();
|
||||
|
||||
return Numberx;
|
||||
};
|
||||
40
app/src/main/assets/modules/__RootAutomator__.js
Normal file
40
app/src/main/assets/modules/__RootAutomator__.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { autojs } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.RootAutomator}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const RootAutomator = org.autojs.autojs.core.inputevent.RootAutomator;
|
||||
|
||||
let _ = {
|
||||
/**
|
||||
* @extends Internal.RootAutomator
|
||||
*/
|
||||
RootAutomator(waitForReady) {
|
||||
if (!autojs.isRootAvailable()) {
|
||||
throw Error('RootAutomator must be instantiated with root access');
|
||||
}
|
||||
|
||||
this.__ra__ = Object.create(new RootAutomator(scope.context, ( /* @IIFE */ () => {
|
||||
if (typeof waitForReady === 'number') {
|
||||
return waitForReady;
|
||||
}
|
||||
return Boolean(waitForReady);
|
||||
})()));
|
||||
|
||||
[
|
||||
'sendEvent', 'touch', 'setScreenMetrics',
|
||||
'touchX', 'touchY', 'sendSync', 'sendMtSync',
|
||||
'tap', 'swipe', 'press', 'longPress',
|
||||
'touchDown', 'touchUp', 'touchMove',
|
||||
'getDefaultId', 'setDefaultId', 'exit',
|
||||
].forEach(key => this[key] = this.__ra__[key].bind(this.__ra__));
|
||||
},
|
||||
};
|
||||
|
||||
return _.RootAutomator;
|
||||
};
|
||||
517
app/src/main/assets/modules/__app__.js
Normal file
517
app/src/main/assets/modules/__app__.js
Normal file
@@ -0,0 +1,517 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { autojs, shell, files, util } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.App}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const File = java.io.File;
|
||||
const Uri = android.net.Uri;
|
||||
const JavaInteger = java.lang.Integer;
|
||||
const FileProvider = androidx.core.content.FileProvider;
|
||||
|
||||
/**
|
||||
* @type {org.autojs.autojs.runtime.api.AppUtils}
|
||||
*/
|
||||
const rtApp = scriptRuntime.app;
|
||||
|
||||
const packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||
|
||||
// noinspection SpellCheckingInspection
|
||||
let _ = {
|
||||
App: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.App
|
||||
*/
|
||||
const App = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
App.prototype = {
|
||||
constructor: App,
|
||||
autojs,
|
||||
versionCode: packageInfo.versionCode,
|
||||
versionName: packageInfo.versionName,
|
||||
/**
|
||||
* @param {App.Intent.Preset.AppAlias | App.PackageName} app
|
||||
* @returns {boolean}
|
||||
*/
|
||||
launch(app) {
|
||||
return this.launchPackage(app);
|
||||
},
|
||||
/**
|
||||
* @param {App.Intent.Common} o
|
||||
* @return {Intent}
|
||||
*/
|
||||
intent(o) {
|
||||
let intent = new Intent();
|
||||
|
||||
if (o.url) {
|
||||
o.data = _.parseIntentUrl(o);
|
||||
}
|
||||
if (o.package) {
|
||||
o.packageName = o.packageName || o.package;
|
||||
} else if (o.packageName) {
|
||||
o.package = o.packageName;
|
||||
}
|
||||
if (o.packageName) {
|
||||
let k = String(o.packageName);
|
||||
let presets = _.getPresetPackageNames();
|
||||
if (k in presets) {
|
||||
o.packageName = presets[k];
|
||||
}
|
||||
if (o.className) {
|
||||
intent.setClassName(o.packageName, _.parseClassName(o));
|
||||
} else {
|
||||
// @Hint by SuperMonster003 on Jun 23, 2020.
|
||||
// ! the Intent can only match the components
|
||||
// ! in the given application package with setPackage().
|
||||
// ! Otherwise, if there's more than one app that can handle the intent,
|
||||
// ! the system presents the user with a dialog to pick which app to use.
|
||||
intent.setPackage(o.packageName);
|
||||
}
|
||||
}
|
||||
if (o.extras) {
|
||||
Object.entries(o.extras).forEach((pairs) => {
|
||||
let [ key, value ] = pairs;
|
||||
intent.putExtra(key, value);
|
||||
});
|
||||
}
|
||||
if (o.category) {
|
||||
if (Array.isArray(o.category)) {
|
||||
o.category.forEach(cat => intent.addCategory(o.category[cat]));
|
||||
} else {
|
||||
intent.addCategory(o.category);
|
||||
}
|
||||
}
|
||||
if (o.action) {
|
||||
intent.setAction(_.parseIntentAction(o.action));
|
||||
}
|
||||
if (o.flags) {
|
||||
intent.setFlags(_.parseIntentFlags(o.flags));
|
||||
}
|
||||
if (o.type) {
|
||||
if (o.data) {
|
||||
intent.setDataAndType(this.parseUri(o.data), o.type);
|
||||
} else {
|
||||
intent.setType(o.type);
|
||||
}
|
||||
} else if (o.data) {
|
||||
intent.setData(Uri.parse(o.data));
|
||||
}
|
||||
|
||||
return intent;
|
||||
},
|
||||
/**
|
||||
* @param {App.Intent.Common} i
|
||||
* @return {string}
|
||||
*/
|
||||
intentToShell(i) {
|
||||
let __ = {
|
||||
init() {
|
||||
this.cmd = '';
|
||||
},
|
||||
/**
|
||||
* @typedef {{ body: string, isQuote?: boolean }} CmdBody
|
||||
* @typedef {CmdBody | CmdBody[] | string} CmdBodies
|
||||
*/
|
||||
/**
|
||||
* @param {string} cmdOptions
|
||||
* @param {CmdBodies} cmdBodies
|
||||
*/
|
||||
append(cmdOptions, cmdBodies) {
|
||||
this.cmd += ` -${cmdOptions} ${this.parseCmdBodies(cmdBodies)}`;
|
||||
},
|
||||
quote(str) {
|
||||
return `'${str.replace('\'', '\\\'')}'`;
|
||||
},
|
||||
isInt(x) {
|
||||
return Number.isInteger(x) && x <= JavaInteger.MAX_VALUE && x >= JavaInteger.MIN_VALUE;
|
||||
},
|
||||
parseType(type) {
|
||||
if (typeof type === 'boolean') {
|
||||
return 'z';
|
||||
}
|
||||
if (typeof type === 'number') {
|
||||
return !Number.isInteger(type) ? 'f' : this.isInt(type) ? 'i' : 'l';
|
||||
}
|
||||
throw TypeError(`Unknown type: ${type}`);
|
||||
},
|
||||
/**
|
||||
* @param {CmdBodies} o
|
||||
* @return {string}
|
||||
*/
|
||||
parseCmdBodies(o) {
|
||||
if (Array.isArray(o)) {
|
||||
return o.map((p) => {
|
||||
return p.isQuote ? this.quote(p.body) : p.body;
|
||||
}).join('\x20');
|
||||
}
|
||||
let body = isObjectSpecies(o) ? o.body : o;
|
||||
return o.isQuote ? this.quote(body) : body;
|
||||
},
|
||||
};
|
||||
|
||||
let $$ = {
|
||||
getResult() {
|
||||
this.init()
|
||||
.parseNames()
|
||||
.parseExtras()
|
||||
.parseCategory()
|
||||
.parseAction()
|
||||
.parseFlags()
|
||||
.parseType()
|
||||
.parseData();
|
||||
|
||||
return this.cmd;
|
||||
},
|
||||
init() {
|
||||
__.init();
|
||||
|
||||
Object.defineProperty(this, 'cmd', { get: () => __.cmd });
|
||||
|
||||
return this;
|
||||
},
|
||||
parseNames() {
|
||||
if (i.className && i.packageName) {
|
||||
let body = `${i.packageName}/${i.className}`;
|
||||
__.append('n', { body, isQuote: true });
|
||||
}
|
||||
return this;
|
||||
},
|
||||
parseExtras() {
|
||||
if (i.extras) {
|
||||
Object.entries(i.extras).forEach((pairs) => {
|
||||
let [ key, value ] = pairs;
|
||||
if (typeof value === 'string') {
|
||||
return __.append('-es', [
|
||||
{ body: key, isQuote: true },
|
||||
{ body: value, isQuote: true },
|
||||
]);
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
if (value.length === 0) {
|
||||
throw Error(`Empty array: ${key}`);
|
||||
}
|
||||
let [ element ] = value;
|
||||
return typeof element === 'string'
|
||||
? __.append('-esa', [
|
||||
{ body: key, isQuote: true },
|
||||
{ body: value.map(__.quote).join() },
|
||||
])
|
||||
: __.append(`-e${__.parseType(element)}a`, [
|
||||
{ body: key, isQuote: true },
|
||||
{ body: value },
|
||||
]);
|
||||
}
|
||||
return __.append(`-e${__.parseType(value)}`, [
|
||||
{ body: key, isQuote: true },
|
||||
{ body: value },
|
||||
]);
|
||||
});
|
||||
}
|
||||
return this;
|
||||
},
|
||||
parseCategory() {
|
||||
if (i.category) {
|
||||
if (Array.isArray(i.category)) {
|
||||
i.category.forEach(cat => __.append('c', cat));
|
||||
} else {
|
||||
__.append('c', i.category);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
parseAction() {
|
||||
if (i.action) {
|
||||
__.append('a', {
|
||||
body: _.parseIntentAction(i.action),
|
||||
isQuote: true,
|
||||
});
|
||||
}
|
||||
return this;
|
||||
},
|
||||
parseFlags() {
|
||||
if (i.flags) {
|
||||
__.append('f', _.parseIntentFlags(i.flags));
|
||||
}
|
||||
return this;
|
||||
},
|
||||
parseType() {
|
||||
if (i.type) {
|
||||
__.append('t', i.type);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
parseData() {
|
||||
if (i.data) {
|
||||
__.append('d', i.data);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
};
|
||||
|
||||
return $$.getResult();
|
||||
},
|
||||
startActivity(o) {
|
||||
if (o instanceof Intent) {
|
||||
return context.startActivity(o.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
if (typeof o === 'string') {
|
||||
let prop = runtime.getProperty(`class.${o}`);
|
||||
if (!prop) {
|
||||
throw Error(`Class ${o} not found`);
|
||||
}
|
||||
let intent = new Intent(context, prop).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
return context.startActivity(intent);
|
||||
}
|
||||
if (isObjectSpecies(o) && o.root) {
|
||||
shell(`am start ${this.intentToShell(o)}`, true);
|
||||
} else {
|
||||
context.startActivity(this.intent(o).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
},
|
||||
startService(i) {
|
||||
if (isObjectSpecies(i) && i.root) {
|
||||
// noinspection SpellCheckingInspection
|
||||
shell(`am startservice ${this.intentToShell(i)}`, true);
|
||||
} else {
|
||||
context.startService(this.intent(i));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @param {App.Intent.Email} [options]
|
||||
*/
|
||||
sendEmail(options) {
|
||||
let i = new Intent(Intent.ACTION_SEND);
|
||||
let opt = options || {};
|
||||
|
||||
if (opt.email) {
|
||||
i.putExtra(Intent.EXTRA_EMAIL, _.toArray(opt.email));
|
||||
}
|
||||
if (opt.cc) {
|
||||
i.putExtra(Intent.EXTRA_CC, _.toArray(opt.cc));
|
||||
}
|
||||
if (opt.bcc) {
|
||||
i.putExtra(Intent.EXTRA_BCC, _.toArray(opt.bcc));
|
||||
}
|
||||
if (opt.subject) {
|
||||
i.putExtra(Intent.EXTRA_SUBJECT, opt.subject);
|
||||
}
|
||||
if (opt.text) {
|
||||
i.putExtra(Intent.EXTRA_TEXT, opt.text);
|
||||
}
|
||||
if (opt.attachment) {
|
||||
i.putExtra(Intent.EXTRA_STREAM, this.parseUri(opt.attachment));
|
||||
}
|
||||
i.setType('message/rfc822');
|
||||
|
||||
this.startActivity(Intent.createChooser(i, 'Send Email'));
|
||||
},
|
||||
sendBroadcast(i) {
|
||||
if (typeof i === 'string') {
|
||||
let property = runtime.getProperty(`broadcast.${i}`);
|
||||
if (property) {
|
||||
this.sendLocalBroadcastSync(this.intent({ action: property }));
|
||||
}
|
||||
} else {
|
||||
if (isObjectSpecies(i) && i.root) {
|
||||
shell(`am broadcast ${this.intentToShell(i)}`, true);
|
||||
} else {
|
||||
context.sendBroadcast(this.intent(i));
|
||||
}
|
||||
}
|
||||
},
|
||||
parseUri(uri) {
|
||||
return uri.startsWith(_.protocol.file) ? this.getUriForFile(uri) : Uri.parse(uri);
|
||||
},
|
||||
getUriForFile(path) {
|
||||
if (path.startsWith(_.protocol.file)) {
|
||||
path = path.slice(_.protocol.file.length);
|
||||
}
|
||||
let file = new File(files.path(path));
|
||||
return this.fileProviderAuthority === null
|
||||
? Uri.fromFile(file)
|
||||
: FileProvider.getUriForFile(context, this.fileProviderAuthority, file);
|
||||
},
|
||||
getAppByAlias(alias) {
|
||||
return _.getAppByAlias(alias);
|
||||
},
|
||||
launchPackage(app) {
|
||||
if (app instanceof App) {
|
||||
app = app.getPackageName();
|
||||
}
|
||||
let preset = _.getAppByAlias(app);
|
||||
return rtApp.launchPackage(preset ? preset.getPackageName() : app);
|
||||
},
|
||||
launchApp(app) {
|
||||
if (app instanceof App) {
|
||||
app = app.getAppName();
|
||||
}
|
||||
let preset = _.getAppByAlias(app);
|
||||
return rtApp.launchApp(preset ? preset.getAppName() : app);
|
||||
},
|
||||
getAppName(app) {
|
||||
if (app instanceof App) {
|
||||
return app.getAppName();
|
||||
}
|
||||
let preset = _.getAppByAlias(app);
|
||||
return preset ? preset.getAppName() : rtApp.getAppName(String(app));
|
||||
},
|
||||
getPackageName(app) {
|
||||
if (app instanceof App) {
|
||||
app = app.getPackageName();
|
||||
}
|
||||
let preset = _.getAppByAlias(app);
|
||||
return preset ? preset.getPackageName() : rtApp.getPackageName(String(app));
|
||||
},
|
||||
openAppSetting(app) {
|
||||
return this.openAppSettings(app);
|
||||
},
|
||||
openAppSettings(app) {
|
||||
if (app instanceof App) {
|
||||
app = app.getPackageName();
|
||||
}
|
||||
let preset = _.getAppByAlias(app);
|
||||
return rtApp.openAppSettings(preset ? preset.getPackageName() : app);
|
||||
},
|
||||
uninstall(app) {
|
||||
if (app instanceof App) {
|
||||
app = app.getPackageName();
|
||||
}
|
||||
let preset = _.getAppByAlias(app);
|
||||
return rtApp.uninstall(preset ? preset.getPackageName() : app);
|
||||
},
|
||||
isVersionNewer(name, version) {
|
||||
//// -=-= PENDING =-=- ////
|
||||
},
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(App.prototype, rtApp);
|
||||
|
||||
return App;
|
||||
})(),
|
||||
protocol: {
|
||||
file: 'file://',
|
||||
},
|
||||
/**
|
||||
* @returns {Object.<App.Intent.Preset.AppAlias, string>}
|
||||
*/
|
||||
getPresetPackageNames() {
|
||||
if (_._presetPackageNames === undefined) {
|
||||
_._presetPackageNames = {};
|
||||
App.values().forEach((o) => {
|
||||
_._presetPackageNames[o.getAlias()] = o.getPackageName();
|
||||
});
|
||||
}
|
||||
return _._presetPackageNames;
|
||||
},
|
||||
/**
|
||||
* @param {string} alias
|
||||
* @returns {org.autojs.autojs.util.App}
|
||||
*/
|
||||
getAppByAlias(alias) {
|
||||
return App.getAppByAlias(String(alias));
|
||||
},
|
||||
toArray(arg) {
|
||||
if (!Array.isArray(arg)) {
|
||||
arg = [ arg ];
|
||||
}
|
||||
let arr = util.java.array('string', arg.length);
|
||||
arg.forEach((o, i) => arr[i] = o);
|
||||
return arr;
|
||||
},
|
||||
parseIntentFlags(flags) {
|
||||
let parse = (o) => {
|
||||
if (typeof o === 'string') {
|
||||
return Intent[`FLAG_${o.toUpperCase()}`];
|
||||
}
|
||||
if (typeof o === 'number') {
|
||||
return o;
|
||||
}
|
||||
throw TypeError(`Invalid flags: ${o}`);
|
||||
};
|
||||
let result = 0x0;
|
||||
if (Array.isArray(flags)) {
|
||||
flags.forEach(flag => result |= parse(flag));
|
||||
} else {
|
||||
result = parse(flags);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
parseIntentAction(action) {
|
||||
if (typeof action === 'string' && !action.includes('.')) {
|
||||
action = `android.intent.action.${action}`;
|
||||
}
|
||||
return action;
|
||||
},
|
||||
parseIntentUrl(o) {
|
||||
let __ = {
|
||||
/**
|
||||
* @param {Appx.Intent.URI} uri
|
||||
* @return {string}
|
||||
*/
|
||||
parseUrlObject(uri) {
|
||||
let { src, query, exclude } = uri;
|
||||
if (!src || !query) {
|
||||
return src;
|
||||
}
|
||||
let separator = src.match(/\?/) ? '&' : '?';
|
||||
return src + separator + (function parse(query) {
|
||||
exclude = exclude || [];
|
||||
if (!Array.isArray(exclude)) {
|
||||
exclude = [ exclude ];
|
||||
}
|
||||
return Object.keys(query).map((key) => {
|
||||
let val = query[key];
|
||||
if (isObjectSpecies(val)) {
|
||||
val = key === 'url' ? __.parseUrlObject(val) : parse(val);
|
||||
val = (key === '__webview_options__' ? '&' : '') + val;
|
||||
}
|
||||
if (!exclude.includes(key)) {
|
||||
val = encodeURI(val);
|
||||
}
|
||||
return key + '=' + val;
|
||||
}).join('&');
|
||||
})(query);
|
||||
},
|
||||
};
|
||||
let { url } = o;
|
||||
return typeof url === 'object' ? __.parseUrlObject(url) : url;
|
||||
},
|
||||
/**
|
||||
* @param {App.Intent.Common} intent
|
||||
* @returns {string}
|
||||
*/
|
||||
parseClassName(intent) {
|
||||
return intent.className.replace(/@\{(\w+?)}|@(\w+)/g, ($, $1, $2) => {
|
||||
let key = $1 || $2;
|
||||
if (key in intent) {
|
||||
return intent[$1 || $2];
|
||||
}
|
||||
throw ReferenceError(`Intent object doesn't have a key named ${key}`);
|
||||
});
|
||||
},
|
||||
scopeAugment() {
|
||||
/**
|
||||
* @type {(keyof Internal.App)[]}
|
||||
*/
|
||||
let methods = [ 'launchPackage', 'launch', 'launchApp', 'getPackageName', 'getAppName', 'openAppSetting', 'openAppSettings' ];
|
||||
__asGlobal__(app, methods, scope);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.App}
|
||||
*/
|
||||
const app = new _.App();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return app;
|
||||
};
|
||||
115
app/src/main/assets/modules/__autojs__.js
Normal file
115
app/src/main/assets/modules/__autojs__.js
Normal file
@@ -0,0 +1,115 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { util } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Autojs}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const Manifest = android.Manifest;
|
||||
const BuildConfig = org.autojs.autojs6.BuildConfig;
|
||||
const PackageManager = android.content.pm.PackageManager;
|
||||
const RootUtils = org.autojs.autojs.util.RootUtils;
|
||||
const RootMode = RootUtils.RootMode;
|
||||
const Settings = android.provider.Settings;
|
||||
const System = Settings.System;
|
||||
|
||||
let _ = {
|
||||
Autojs: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Autojs
|
||||
*/
|
||||
const Autojs = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Autojs.prototype = {
|
||||
constructor: Autojs,
|
||||
versionCode: BuildConfig.VERSION_CODE,
|
||||
versionName: BuildConfig.VERSION_NAME,
|
||||
versionDate: BuildConfig.VERSION_DATE,
|
||||
version: {
|
||||
code: BuildConfig.VERSION_CODE,
|
||||
name: BuildConfig.VERSION_NAME,
|
||||
date: BuildConfig.VERSION_DATE,
|
||||
isHigherThan(otherVersion) {
|
||||
return new Version(this.name).isHigherThan(otherVersion);
|
||||
},
|
||||
isLowerThan(otherVersion) {
|
||||
return new Version(this.name).isLowerThan(otherVersion);
|
||||
},
|
||||
isEqual(otherVersion) {
|
||||
return new Version(this.name).isEqual(otherVersion);
|
||||
},
|
||||
isAtLeast(otherVersion, ignoreSuffix) {
|
||||
if (typeof ignoreSuffix === 'undefined') {
|
||||
return new Version(this.name).isAtLeast(otherVersion);
|
||||
}
|
||||
return new Version(this.name).isAtLeast(otherVersion, Boolean(ignoreSuffix));
|
||||
},
|
||||
},
|
||||
R: global.R,
|
||||
name: context.getString(R.strings.app_name),
|
||||
isRootAvailable() {
|
||||
return RootUtils.isRootAvailable();
|
||||
},
|
||||
getRootMode() {
|
||||
return RootUtils.getRootMode();
|
||||
},
|
||||
setRootMode(mode, isWriteIntoPreference) {
|
||||
let isWriteIntoPref = ( /* @IIFE */ () => {
|
||||
if (typeof isWriteIntoPreference === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
if (typeof isWriteIntoPreference === 'boolean') {
|
||||
return isWriteIntoPreference;
|
||||
}
|
||||
return util.checkStringParam(isWriteIntoPreference, 'write_into_pref');
|
||||
})();
|
||||
if (mode === 1 || mode === true || util.checkStringParam(mode, 'root')) {
|
||||
RootUtils.setRootMode(RootMode.FORCE_ROOT, isWriteIntoPref);
|
||||
} else if (mode === 0 || mode === false || util.checkStringParam(mode, 'non-root')) {
|
||||
RootUtils.setRootMode(RootMode.FORCE_NON_ROOT, isWriteIntoPref);
|
||||
} else if (mode === -1 || util.checkStringParam(mode, 'auto')) {
|
||||
RootUtils.setRootMode(RootMode.AUTO_DETECT, isWriteIntoPref);
|
||||
} else {
|
||||
let errPrefix = `Unknown mode (${mode}) for setRootMode()`;
|
||||
if (!mode) {
|
||||
throw Error(`${errPrefix}. Did you mean to use false or 0 or 'non-root' to forcibly set non-root mode?`);
|
||||
} else {
|
||||
throw Error(`${errPrefix}. Did you mean to use true or 1 or 'root' to forcibly set root mode?`);
|
||||
}
|
||||
}
|
||||
},
|
||||
canModifySystemSettings() {
|
||||
return System.canWrite(context);
|
||||
},
|
||||
canWriteSecureSettings() {
|
||||
return context.checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) === PackageManager.PERMISSION_GRANTED;
|
||||
},
|
||||
canDisplayOverOtherApps() {
|
||||
return Settings.canDrawOverlays(context);
|
||||
},
|
||||
getLanguage() {
|
||||
return org.autojs.autojs.pref.Language.getPrefLanguage().getLocale();
|
||||
},
|
||||
getLanguageTag() {
|
||||
return this.getLanguage().toLanguageTag();
|
||||
},
|
||||
};
|
||||
|
||||
return Autojs;
|
||||
})(),
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Autojs}
|
||||
*/
|
||||
const autojs = new _.Autojs();
|
||||
|
||||
return autojs;
|
||||
};
|
||||
362
app/src/main/assets/modules/__automator__.js
Normal file
362
app/src/main/assets/modules/__automator__.js
Normal file
@@ -0,0 +1,362 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { util } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Automator}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const ResultAdapter = require('result-adapter');
|
||||
|
||||
const Path = android.graphics.Path;
|
||||
const Rect = android.graphics.Rect;
|
||||
const GestureDescription = android.accessibilityservice.GestureDescription;
|
||||
const AccessibilityBridge = org.autojs.autojs.core.accessibility.AccessibilityBridge;
|
||||
|
||||
/**
|
||||
* @type {org.autojs.autojs.core.accessibility.SimpleActionAutomator}
|
||||
*/
|
||||
const rtAutomator = scriptRuntime.automator;
|
||||
|
||||
/**
|
||||
* @type {org.autojs.autojs.core.accessibility.AccessibilityBridge}
|
||||
*/
|
||||
const a11yBridge = scriptRuntime.accessibilityBridge;
|
||||
|
||||
let _ = {
|
||||
Auto: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Auto
|
||||
*/
|
||||
const Auto = function () {
|
||||
return Object.assign(function (mode) {
|
||||
if (typeof mode === 'string') {
|
||||
auto.setMode(mode);
|
||||
}
|
||||
a11yBridge.ensureServiceEnabled();
|
||||
}, Auto.prototype);
|
||||
};
|
||||
|
||||
Auto.prototype = {
|
||||
constructor: Auto,
|
||||
get service() {
|
||||
return a11yBridge.getService();
|
||||
},
|
||||
get windows() {
|
||||
return this.service === null ? [] : util.java.toJsArray(this.service.getWindows(), true);
|
||||
},
|
||||
get root() {
|
||||
let root = a11yBridge.getRootInCurrentWindow();
|
||||
return root ? UiObject.createRoot(root) : null;
|
||||
},
|
||||
get rootInActiveWindow() {
|
||||
let root = a11yBridge.getRootInActiveWindow();
|
||||
return root ? UiObject.createRoot(root) : null;
|
||||
},
|
||||
get windowRoots() {
|
||||
return util.java.toJsArray(a11yBridge.windowRoots(), false)
|
||||
.map(root => UiObject.createRoot(root));
|
||||
},
|
||||
waitFor(timeout) {
|
||||
automator.waitForService(timeout);
|
||||
},
|
||||
setMode(modeStr) {
|
||||
if (typeof modeStr !== 'string') {
|
||||
throw TypeError('Mode should be a string for auto.setMode()');
|
||||
}
|
||||
let mode = _.modes[modeStr];
|
||||
if (mode === undefined) {
|
||||
throw Error(`Unknown mode for auto.setMode(): ${modeStr}`);
|
||||
}
|
||||
a11yBridge.setMode(mode);
|
||||
},
|
||||
setFlags(flags) {
|
||||
let flagStrings;
|
||||
if (Array.isArray(flags)) {
|
||||
flagStrings = flags;
|
||||
} else if (typeof flags === 'string') {
|
||||
flagStrings = [ flags ];
|
||||
} else {
|
||||
throw TypeError(`Unknown flags: ${flags}`);
|
||||
}
|
||||
let flagsInt = 0;
|
||||
flagStrings.forEach((s) => {
|
||||
let flag = _.flagsMap[s];
|
||||
if (flag === undefined) {
|
||||
throw Error(`Unknown flag for auto.setFlags(): ${flag}`);
|
||||
}
|
||||
flagsInt |= flag;
|
||||
});
|
||||
a11yBridge.setFlags(flagsInt);
|
||||
},
|
||||
setWindowFilter(filter) {
|
||||
a11yBridge.setWindowFilter(new AccessibilityBridge.WindowFilter({ filter }));
|
||||
},
|
||||
};
|
||||
|
||||
return Auto;
|
||||
})(),
|
||||
Automator: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Automator
|
||||
*/
|
||||
const Automator = function () {
|
||||
|
||||
};
|
||||
|
||||
Automator.prototype = {
|
||||
constructor: Automator,
|
||||
press(x, y, delay) {
|
||||
return rtAutomator.press(x, y, delay);
|
||||
},
|
||||
gesture(duration, points) {
|
||||
return rtAutomator.gesture.apply(rtAutomator, [ 0 ].concat(Array.from(arguments)));
|
||||
},
|
||||
gestureAsync(duration, points) {
|
||||
return rtAutomator.gestureAsync.apply(rtAutomator, [ 0 ].concat(Array.from(arguments)));
|
||||
},
|
||||
swipe(x1, y1, x2, y2, delay) {
|
||||
return rtAutomator.swipe(x1, y1, x2, y2, delay);
|
||||
},
|
||||
isServiceRunning() {
|
||||
return rtAutomator.isServiceRunning();
|
||||
},
|
||||
ensureService() {
|
||||
rtAutomator.ensureService();
|
||||
},
|
||||
waitForService(timeout) {
|
||||
a11yBridge.waitForServiceEnabled(_.parseNumber(timeout, -1));
|
||||
},
|
||||
click() {
|
||||
if (arguments.length === 2) {
|
||||
let [ x, y ] = arguments;
|
||||
if (typeof x === 'number' && typeof y === 'number') {
|
||||
return rtAutomator.click(x, y);
|
||||
}
|
||||
}
|
||||
let target = arguments[0];
|
||||
if (target instanceof Rect) {
|
||||
return this.click(target.centerX(), target.centerY());
|
||||
}
|
||||
if (target instanceof UiObject) {
|
||||
return target.clickable() ? target.click() : this.click(target.bounds());
|
||||
}
|
||||
return _.performAction(function (target) {
|
||||
return rtAutomator.click(target);
|
||||
}, arguments);
|
||||
},
|
||||
longClick() {
|
||||
if (arguments.length === 2) {
|
||||
let [ x, y ] = arguments;
|
||||
if (typeof x === 'number' && typeof y === 'number') {
|
||||
return rtAutomator.longClick(x, y);
|
||||
}
|
||||
}
|
||||
return _.performAction(function (target) {
|
||||
return rtAutomator.longClick(target);
|
||||
}, arguments);
|
||||
},
|
||||
input() {
|
||||
if (arguments.length === 2) {
|
||||
let [ index, text ] = arguments;
|
||||
return rtAutomator.appendText(rtAutomator.editable(index), text);
|
||||
} else {
|
||||
let [ text ] = arguments;
|
||||
return rtAutomator.appendText(rtAutomator.editable(-1), text);
|
||||
}
|
||||
},
|
||||
gestures() {
|
||||
return rtAutomator.gestures(_.toStrokes(arguments));
|
||||
},
|
||||
gesturesAsync() {
|
||||
rtAutomator.gesturesAsync(_.toStrokes(arguments));
|
||||
},
|
||||
scrollDown(index) {
|
||||
if (typeof index === 'number') {
|
||||
return rtAutomator.scrollForward(index);
|
||||
}
|
||||
if (arguments.length === 0) {
|
||||
return rtAutomator.scrollMaxForward();
|
||||
}
|
||||
|
||||
// @Comment by SuperMonster003 on Apr 20, 2022.
|
||||
// ! Method runtime.automator.scrollForward() should be invoked with number rather than ActionTarget.
|
||||
// ! Thus, there is a strong possibility that performAction() won't work properly as expected.
|
||||
|
||||
// return _.performAction(function (target) {
|
||||
// return runtime.automator.scrollForward(target);
|
||||
// }, arguments);
|
||||
},
|
||||
scrollUp(index) {
|
||||
if (typeof index === 'number') {
|
||||
return rtAutomator.scrollBackward(index);
|
||||
}
|
||||
if (arguments.length === 0) {
|
||||
return rtAutomator.scrollMaxBackward();
|
||||
}
|
||||
|
||||
// @Comment by SuperMonster003 on Apr 20, 2022.
|
||||
// ! Method runtime.automator.scrollBackward() should be invoked with number rather than ActionTarget.
|
||||
// ! Thus, there is a strong possibility that performAction() won't work properly as expected.
|
||||
|
||||
// return _.performAction(function (target) {
|
||||
// return runtime.automator.scrollBackward(target);
|
||||
// }, arguments);
|
||||
},
|
||||
setText() {
|
||||
if (arguments.length === 2) {
|
||||
let [ index, text ] = arguments;
|
||||
return rtAutomator.setText(rtAutomator.editable(index), text);
|
||||
} else {
|
||||
let [ text ] = arguments;
|
||||
return rtAutomator.setText(rtAutomator.editable(-1), text);
|
||||
}
|
||||
},
|
||||
captureScreen() {
|
||||
return ResultAdapter.wait(rtAutomator.captureScreen());
|
||||
},
|
||||
lockScreen() {
|
||||
return rtAutomator.lockScreen();
|
||||
},
|
||||
takeScreenshot() {
|
||||
return rtAutomator.takeScreenshot();
|
||||
},
|
||||
headsethook() {
|
||||
return rtAutomator.headsethook();
|
||||
},
|
||||
accessibilityButton() {
|
||||
return rtAutomator.accessibilityButton();
|
||||
},
|
||||
accessibilityButtonChooser() {
|
||||
return rtAutomator.accessibilityButtonChooser();
|
||||
},
|
||||
accessibilityShortcut() {
|
||||
return rtAutomator.accessibilityShortcut();
|
||||
},
|
||||
accessibilityAllApps() {
|
||||
return rtAutomator.accessibilityAllApps();
|
||||
},
|
||||
dismissNotificationShade() {
|
||||
return rtAutomator.dismissNotificationShade();
|
||||
},
|
||||
};
|
||||
|
||||
return Automator;
|
||||
})(),
|
||||
modes: {
|
||||
normal: AccessibilityBridge.MODE_NORMAL,
|
||||
fast: AccessibilityBridge.MODE_FAST,
|
||||
},
|
||||
flagsMap: {
|
||||
findOnUiThread: AccessibilityBridge.FLAG_FIND_ON_UI_THREAD,
|
||||
useUsageStats: AccessibilityBridge.FLAG_USE_USAGE_STATS,
|
||||
useShell: AccessibilityBridge.FLAG_USE_SHELL,
|
||||
},
|
||||
/**
|
||||
* @template {boolean} T
|
||||
* @param {(target: org.autojs.autojs.core.automator.action.ActionTarget) => T} action
|
||||
* @param {IArguments} args
|
||||
* @return {T}
|
||||
*/
|
||||
performAction(action, args) {
|
||||
if (args.length === 4) {
|
||||
let [ left, top, right, bottom ] = args;
|
||||
return action(rtAutomator.bounds(left, top, right, bottom));
|
||||
}
|
||||
if (args.length === 2) {
|
||||
let [ text, index ] = args;
|
||||
return action(rtAutomator.text(text, index));
|
||||
}
|
||||
let [ text ] = args;
|
||||
return action(rtAutomator.text(text, -1));
|
||||
},
|
||||
toStrokes(argsList) {
|
||||
let screenMetrics = scriptRuntime.getScreenMetrics();
|
||||
let strokes = java.lang.reflect.Array.newInstance(GestureDescription.StrokeDescription, argsList.length);
|
||||
|
||||
for (let i = 0; i < argsList.length; i += 1) {
|
||||
let args = argsList[i];
|
||||
let startTime, durationIndex, pointsIndex;
|
||||
if (typeof args[1] /* duration */ === 'number') {
|
||||
/* arguments: [startTime, duration, points[]] */
|
||||
startTime = args[0];
|
||||
durationIndex = 1;
|
||||
pointsIndex = 2;
|
||||
} else {
|
||||
/* arguments: [duration, points[]] */
|
||||
startTime = 0; // default value
|
||||
durationIndex = 0;
|
||||
pointsIndex = 1;
|
||||
}
|
||||
let path = new Path();
|
||||
let [ x, y ] = args[pointsIndex];
|
||||
path.moveTo(screenMetrics.scaleX(x), screenMetrics.scaleY(y));
|
||||
for (let j = pointsIndex + 1; j < args.length; j += 1) {
|
||||
let [ x, y ] = args[j];
|
||||
path.lineTo(screenMetrics.scaleX(x), screenMetrics.scaleY(y));
|
||||
}
|
||||
strokes[i] = new GestureDescription.StrokeDescription(path, startTime, args[durationIndex]);
|
||||
}
|
||||
|
||||
return strokes;
|
||||
},
|
||||
/**
|
||||
* @param {any} num
|
||||
* @param {number|function():number} [def=0]
|
||||
* @returns {number}
|
||||
*/
|
||||
parseNumber(num, def) {
|
||||
return typeof num === 'number' ? num : typeof def === 'function' ? def() : def || 0;
|
||||
},
|
||||
scopeAugment() {
|
||||
/**
|
||||
* @type {(keyof Internal.Automator)[]}
|
||||
*/
|
||||
let methods = [
|
||||
'click', 'longClick', 'press', 'swipe',
|
||||
'gesture', 'gestures', 'gestureAsync', 'gesturesAsync',
|
||||
'scrollDown', 'scrollUp', 'input', 'setText',
|
||||
];
|
||||
__asGlobal__(automator, methods, scope);
|
||||
|
||||
/**
|
||||
* @type {(keyof org.autojs.autojs.core.accessibility.SimpleActionAutomator)[]}
|
||||
*/
|
||||
let methodsRt = [
|
||||
'back', 'home', 'powerDialog', 'notifications',
|
||||
'quickSettings', 'recents', 'splitScreen',
|
||||
];
|
||||
__asGlobal__(rtAutomator, methodsRt);
|
||||
|
||||
/**
|
||||
* @Caution by SuperMonster003 on Apr 23, 2022.
|
||||
* Use 'bind' or 'assign' will lose appended properties.
|
||||
*
|
||||
* @example
|
||||
* let f = function () {}; f.code = 1;
|
||||
* let g = f; console.log(g.code); // 1
|
||||
* let h = f.bind({}); console.log(h.code); // undefined
|
||||
* let o = {}; Object.assign(o, {f}); console.log(o.code); // undefined
|
||||
*/
|
||||
scope.auto = auto;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Auto}
|
||||
*/
|
||||
const auto = new _.Auto();
|
||||
|
||||
/**
|
||||
* @type {Internal.Automator}
|
||||
*/
|
||||
const automator = new _.Automator();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return automator;
|
||||
};
|
||||
65
app/src/main/assets/modules/__base64__.js
Normal file
65
app/src/main/assets/modules/__base64__.js
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Base64}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const Base64 = android.util.Base64;
|
||||
const JavaString = java.lang.String;
|
||||
const StandardCharsets = java.nio.charset.StandardCharsets;
|
||||
|
||||
let _ = {
|
||||
Base64Ctor: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Base64
|
||||
*/
|
||||
const Base64Ctor = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Base64Ctor.prototype = {
|
||||
constructor: Base64Ctor,
|
||||
/**
|
||||
* @param str
|
||||
* @param {string} encoding
|
||||
* @return {string}
|
||||
*/
|
||||
encode(str, encoding) {
|
||||
// noinspection JSValidateTypes
|
||||
/**
|
||||
* @type {java.lang.String}
|
||||
*/
|
||||
let string = new JavaString(str);
|
||||
return _.isValidEncoding(encoding)
|
||||
? Base64.encodeToString(string.getBytes(encoding), Base64.NO_WRAP)
|
||||
: Base64.encodeToString(string.getBytes(), Base64.NO_WRAP);
|
||||
},
|
||||
decode(str, encoding) {
|
||||
// noinspection JSValidateTypes
|
||||
return _.isValidEncoding(encoding)
|
||||
? String(new JavaString(Base64.decode(str, Base64.NO_WRAP), encoding))
|
||||
: String(new JavaString(Base64.decode(str, Base64.NO_WRAP)));
|
||||
},
|
||||
};
|
||||
|
||||
return Base64Ctor;
|
||||
})(),
|
||||
isValidEncoding: (encode) => [
|
||||
StandardCharsets.US_ASCII,
|
||||
StandardCharsets.ISO_8859_1,
|
||||
StandardCharsets.UTF_8,
|
||||
StandardCharsets.UTF_16BE,
|
||||
StandardCharsets.UTF_16LE,
|
||||
StandardCharsets.UTF_16,
|
||||
].map((javaCharset) => {
|
||||
return javaCharset.name().toLowerCase();
|
||||
}).includes(String(encode).toLowerCase()),
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Base64}
|
||||
*/
|
||||
const base64 = new _.Base64Ctor();
|
||||
|
||||
return base64;
|
||||
};
|
||||
42
app/src/main/assets/modules/__bridges__.js
Normal file
42
app/src/main/assets/modules/__bridges__.js
Normal file
@@ -0,0 +1,42 @@
|
||||
( /* @ModuleIIFE */ () => {
|
||||
|
||||
let _ = {
|
||||
unwrapIfNeeded(o) {
|
||||
return isJavaObject(o) ? unwrapJavaObject(o) : o;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
toArray(iterable) {
|
||||
let iterator = iterable.iterator();
|
||||
let arr = [];
|
||||
while (iterator.hasNext()) {
|
||||
arr.push(iterator.next());
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
asArray(list) {
|
||||
let arr = [];
|
||||
for (let i = 0; i < list.size(); i += 1) {
|
||||
arr.push(list.get(i));
|
||||
}
|
||||
for (let key in list) {
|
||||
if (typeof key !== 'number') {
|
||||
let v = list[key];
|
||||
arr[key] = typeof v === 'function' ? v.bind(list) : v;
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
toString(o) {
|
||||
return String(o);
|
||||
},
|
||||
call(func, target, args) {
|
||||
return func.apply(target, args.map(_.unwrapIfNeeded));
|
||||
},
|
||||
toPrimitive(o) {
|
||||
return _.unwrapIfNeeded(o);
|
||||
},
|
||||
};
|
||||
|
||||
})();
|
||||
170
app/src/main/assets/modules/__console__.js
Normal file
170
app/src/main/assets/modules/__console__.js
Normal file
@@ -0,0 +1,170 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { files, util } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Console}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const Log = android.util.Log;
|
||||
const Level = org.apache.log4j.Level;
|
||||
const ConsoleUtils = org.autojs.autojs.util.ConsoleUtils;
|
||||
const LogConfigurator = de.mindpipe.android.logging.log4j.LogConfigurator;
|
||||
|
||||
const rtConsole = scriptRuntime.console;
|
||||
|
||||
let _ = {
|
||||
Console: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Console
|
||||
*/
|
||||
const Console = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Console.prototype = {
|
||||
constructor: Console,
|
||||
trace: function captureStack(message, level) {
|
||||
let target = {};
|
||||
Error.captureStackTrace(target, captureStack);
|
||||
if (typeof level === 'string') {
|
||||
level = level.toUpperCase();
|
||||
}
|
||||
let msg = `${util.format(message)}\n${target.stack}`;
|
||||
switch (level) {
|
||||
case Log.VERBOSE:
|
||||
case 'VERBOSE':
|
||||
console.verbose(msg);
|
||||
break;
|
||||
case Log.DEBUG:
|
||||
case 'DEBUG':
|
||||
console.log(msg);
|
||||
break;
|
||||
case Log.INFO:
|
||||
case 'INFO':
|
||||
console.info(msg);
|
||||
break;
|
||||
case Log.WARN:
|
||||
case 'WARN':
|
||||
console.warn(msg);
|
||||
break;
|
||||
case Log.ERROR:
|
||||
case 'ERROR':
|
||||
console.error(msg);
|
||||
break;
|
||||
default:
|
||||
console.log(msg);
|
||||
}
|
||||
},
|
||||
assert(value, message) {
|
||||
rtConsole.assertTrue(
|
||||
Boolean(typeof value === 'function' ? value() : value),
|
||||
message || util.getClassName(java.lang.AssertionError));
|
||||
},
|
||||
input(data, param) {
|
||||
return eval(String(this.rawInput(data, param)));
|
||||
},
|
||||
log() {
|
||||
rtConsole.log(util.format.apply(util, arguments));
|
||||
},
|
||||
verbose() {
|
||||
rtConsole.verbose(util.format.apply(util, arguments));
|
||||
},
|
||||
print() {
|
||||
rtConsole.print(Log.DEBUG, util.format.apply(util, arguments));
|
||||
},
|
||||
info() {
|
||||
rtConsole.info(util.format.apply(util, arguments));
|
||||
},
|
||||
warn() {
|
||||
rtConsole.warn(util.format.apply(util, arguments));
|
||||
},
|
||||
error() {
|
||||
rtConsole.error(util.format.apply(util, arguments));
|
||||
},
|
||||
time(label) {
|
||||
_.timeTable.save(label);
|
||||
},
|
||||
timeEnd(label) {
|
||||
_.timeTable.loadAndLog(label);
|
||||
},
|
||||
setGlobalLogConfig(config) {
|
||||
let configurator = new LogConfigurator();
|
||||
if (config.file) {
|
||||
configurator.setFileName(files.path(config.file));
|
||||
configurator.setUseFileAppender(true);
|
||||
}
|
||||
configurator.setFilePattern(_.parseOption(config.filePattern, '%m%n'));
|
||||
configurator.setMaxFileSize(_.parseOption(config.maxFileSize, 512 * 1024));
|
||||
configurator.setImmediateFlush(_.parseOption(config.immediateFlush, true));
|
||||
configurator.setRootLevel(Level[_.parseOption(config.rootLevel, 'ALL').toUpperCase()]);
|
||||
configurator.setMaxBackupSize(_.parseOption(config.maxBackupSize, 5));
|
||||
configurator.setResetConfiguration(_.parseOption(config.resetConfiguration, true));
|
||||
configurator.configure();
|
||||
},
|
||||
launch() {
|
||||
ConsoleUtils.launch();
|
||||
},
|
||||
};
|
||||
|
||||
Object.keys(rtConsole).forEach((key) => {
|
||||
if (!Console.prototype.hasOwnProperty(key)) {
|
||||
if (typeof rtConsole[key] === 'function') {
|
||||
Console.prototype[key] = rtConsole[key].bind(rtConsole);
|
||||
} else {
|
||||
Console.prototype[key] = rtConsole[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Console;
|
||||
})(),
|
||||
timeTable: {
|
||||
data: {},
|
||||
default: 'default',
|
||||
uptimeMillis() {
|
||||
return android.os.SystemClock.uptimeMillis();
|
||||
},
|
||||
parseLabel(label) {
|
||||
return label || this.default;
|
||||
},
|
||||
save(label) {
|
||||
this.data[this.parseLabel(label)] = this.uptimeMillis();
|
||||
},
|
||||
load(label) {
|
||||
return this.data[this.parseLabel(label)];
|
||||
},
|
||||
remove(label) {
|
||||
delete this.data[this.parseLabel(label)];
|
||||
},
|
||||
log(label, text) {
|
||||
console.log(`${this.parseLabel(label)}: ${text}ms`);
|
||||
},
|
||||
loadAndLog(label) {
|
||||
let text = this.uptimeMillis() - this.load(label);
|
||||
this.remove(label);
|
||||
this.log(label, text);
|
||||
},
|
||||
},
|
||||
parseOption(value, def) {
|
||||
return value === undefined ? def : value;
|
||||
},
|
||||
scopeAugment() {
|
||||
__asGlobal__(console, [
|
||||
'verbose', 'print', 'log', 'warn', { err: 'error' },
|
||||
{ openConsole: 'show' }, { clearConsole: 'clear' }, { launchConsole: 'launch' },
|
||||
]);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Console}
|
||||
*/
|
||||
const console = new _.Console();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return console;
|
||||
};
|
||||
121
app/src/main/assets/modules/__continuation__.js
Normal file
121
app/src/main/assets/modules/__continuation__.js
Normal file
@@ -0,0 +1,121 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { engines, global: _global } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Continuation}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
// @Caution by SuperMonster003 on Apr 19, 2022.
|
||||
// ! Do not declare globally because variable Continuation which
|
||||
// ! extends org.mozilla.javascript.NativeContinuation has already declared.
|
||||
const Result = org.autojs.autojs.rhino.continuation.Continuation.Result;
|
||||
|
||||
let _ = {
|
||||
Creator: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Continuation.Creator
|
||||
*/
|
||||
const Creator = function (scope) {
|
||||
this.cont = Object.create(scriptRuntime.createContinuation(scope || _global));
|
||||
};
|
||||
|
||||
Creator.prototype = {
|
||||
constructor: Creator,
|
||||
await() {
|
||||
/**
|
||||
* @Caution by SuperMonster003 on Apr 19, 2022.
|
||||
* Continuation without "continuation feature" will cause an exception
|
||||
* which makes all invocations failed and interrupted here.
|
||||
*
|
||||
* @example Exception snippet
|
||||
* Wrapped java.lang.IllegalStateException:
|
||||
* Cannot capture continuation from JavaScript code not called directly
|
||||
* by executeScriptWithContinuations or callFunctionWithContinuations
|
||||
*
|
||||
* @example Code for reappearance
|
||||
* engines.myEngine().hasFeature('continuation'); // false
|
||||
* Object.create(runtime.createContinuation()).suspend(); // throw error
|
||||
*/
|
||||
let result = this.cont.suspend();
|
||||
if (result.error !== null) {
|
||||
throw result.error;
|
||||
}
|
||||
return result.result;
|
||||
},
|
||||
resumeError(error) {
|
||||
if (isNullish(error)) {
|
||||
throw TypeError('Error is null or undefined');
|
||||
}
|
||||
this.cont.resumeWith(Result.failure(error));
|
||||
},
|
||||
resume(result) {
|
||||
this.cont.resumeWith(Result.success(result));
|
||||
},
|
||||
};
|
||||
|
||||
return Creator;
|
||||
})(),
|
||||
Continuation: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Continuation
|
||||
*/
|
||||
const Continuation = function () {
|
||||
return Object.assign(function () {
|
||||
// Empty interface body.
|
||||
}, Continuation.prototype);
|
||||
};
|
||||
|
||||
Continuation.prototype = {
|
||||
constructor: Continuation,
|
||||
get enabled() {
|
||||
return engines.myEngine().hasFeature('continuation');
|
||||
},
|
||||
create(scope) {
|
||||
return new _.Creator(scope);
|
||||
},
|
||||
await(promise) {
|
||||
const cont = this.create(scope);
|
||||
promise
|
||||
.then(result => cont.resume(result))
|
||||
.catch(error => cont.resumeError(error));
|
||||
return cont.await();
|
||||
},
|
||||
delay(millis) {
|
||||
const cont = this.create(scope);
|
||||
setTimeout(() => cont.resume(), millis);
|
||||
cont.await();
|
||||
},
|
||||
};
|
||||
|
||||
return Continuation;
|
||||
})(),
|
||||
promiseAugment() {
|
||||
/**
|
||||
* @implements Internal.Continuation.PromiseExtension
|
||||
*/
|
||||
const PromiseExtension = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Object.assign(PromiseExtension.prototype, {
|
||||
await() {
|
||||
return continuation.await(this);
|
||||
},
|
||||
});
|
||||
|
||||
Object.assign(Promise.prototype, PromiseExtension.prototype);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Continuation}
|
||||
*/
|
||||
const continuation = new _.Continuation();
|
||||
|
||||
_.promiseAugment();
|
||||
|
||||
return continuation;
|
||||
};
|
||||
95
app/src/main/assets/modules/__device__.js
Normal file
95
app/src/main/assets/modules/__device__.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { util } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Device}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const ScreenMetrics = org.autojs.autojs.runtime.api.ScreenMetrics;
|
||||
const NetworkUtils = org.autojs.autojs.util.NetworkUtils;
|
||||
const DeviceUtils = org.autojs.autojs.util.DeviceUtils;
|
||||
|
||||
const rtDevice = scriptRuntime.device;
|
||||
|
||||
let _ = {
|
||||
Device: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Device
|
||||
*/
|
||||
const Device = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Device.prototype = {
|
||||
constructor: Device,
|
||||
get width() {
|
||||
return ScreenMetrics.getDeviceScreenWidth();
|
||||
},
|
||||
get height() {
|
||||
return ScreenMetrics.getDeviceScreenHeight();
|
||||
},
|
||||
get rotation() {
|
||||
return ScreenMetrics.getRotation();
|
||||
},
|
||||
get density() {
|
||||
return ScreenMetrics.getDeviceScreenDensity();
|
||||
},
|
||||
get summary() {
|
||||
return DeviceUtils.getDeviceSummary(context);
|
||||
},
|
||||
get digest() {
|
||||
let digestList = [
|
||||
`${this.brand}${this.manufacturer === this.brand ? `` : ` (${this.manufacturer})`}`,
|
||||
`${this.device}${this.model === this.device ? `` : ` (${this.model})`}`,
|
||||
`${this.release} (${this.sdkInt})`,
|
||||
];
|
||||
return digestList.join(' / ');
|
||||
},
|
||||
vibrate(off, millis) {
|
||||
if (typeof arguments[0] === 'string') {
|
||||
util.morseCode.vibrate.apply(util.morseCode, arguments);
|
||||
} else {
|
||||
rtDevice.vibrate.apply(rtDevice, arguments);
|
||||
}
|
||||
},
|
||||
isScreenOff() {
|
||||
return !rtDevice.isScreenOn();
|
||||
},
|
||||
getIpAddress(useIPv4) {
|
||||
return useIPv4 === undefined
|
||||
? NetworkUtils.getIpAddress()
|
||||
: NetworkUtils.getIpAddress(useIPv4);
|
||||
},
|
||||
getIpv6Address() {
|
||||
return NetworkUtils.getIpv6Address();
|
||||
},
|
||||
getGatewayAddress() {
|
||||
return NetworkUtils.getGatewayAddress();
|
||||
},
|
||||
isActiveNetworkMetered() {
|
||||
return NetworkUtils.isActiveNetworkMetered();
|
||||
},
|
||||
isConnectedOrConnecting() {
|
||||
return NetworkUtils.isConnectedOrConnecting();
|
||||
},
|
||||
isWifiAvailable() {
|
||||
return NetworkUtils.isWifiAvailable();
|
||||
},
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(Device.prototype, rtDevice);
|
||||
|
||||
return Device;
|
||||
})(),
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Device}
|
||||
*/
|
||||
const device = new _.Device();
|
||||
|
||||
return device;
|
||||
};
|
||||
419
app/src/main/assets/modules/__dialogs__.js
Normal file
419
app/src/main/assets/modules/__dialogs__.js
Normal file
@@ -0,0 +1,419 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { colors, threads, ui } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Dialogs}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const Looper = android.os.Looper;
|
||||
const Linkify = android.text.util.Linkify;
|
||||
const LayoutParams = android.view.WindowManager.LayoutParams;
|
||||
const ColorDrawable = android.graphics.drawable.ColorDrawable;
|
||||
|
||||
let _ = {
|
||||
Dialogs: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Dialogs
|
||||
*/
|
||||
const Dialogs = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Dialogs.prototype = {
|
||||
constructor: Dialogs,
|
||||
build(properties) {
|
||||
/**
|
||||
* @type {Dialogs.Builder}
|
||||
*/
|
||||
let builder = Object.create(scriptRuntime.dialogs.newBuilder(), {
|
||||
thread: { value: threads.currentThread() },
|
||||
});
|
||||
|
||||
Object.keys(properties).forEach((name) => {
|
||||
_.applyDialogProperty(builder, name, properties[name]);
|
||||
});
|
||||
_.applyOtherDialogProperties(builder, properties);
|
||||
|
||||
let dialog = ui.run(() => builder.buildDialog());
|
||||
|
||||
_.applyBuiltDialogProperties(dialog, properties);
|
||||
|
||||
return dialog;
|
||||
},
|
||||
rawInput(title, prefill, callback) {
|
||||
if (typeof prefill === 'function') {
|
||||
return this.rawInput(title, /* prefill = */ null, /* callback = */ prefill);
|
||||
}
|
||||
if (_.isUiThread() && !callback) {
|
||||
return new Promise((resolve) => {
|
||||
_.rtDialogs.rawInput(title, prefill || '', function () {
|
||||
resolve.apply(null, arguments);
|
||||
});
|
||||
});
|
||||
}
|
||||
return _.rtDialogs.rawInput(title, prefill || '', callback || null);
|
||||
},
|
||||
input(title, prefill, callback) {
|
||||
if (typeof prefill === 'function') {
|
||||
return this.input(title, /* prefill = */ null, /* callback = */ prefill);
|
||||
}
|
||||
if (_.isUiThread() && !callback) {
|
||||
return new Promise((resolve) => {
|
||||
_.rtDialogs.rawInput(title, prefill || '', function (str) {
|
||||
resolve(eval(str));
|
||||
});
|
||||
});
|
||||
}
|
||||
if (!callback) {
|
||||
return eval(String(this.rawInput(title, prefill)));
|
||||
}
|
||||
this.rawInput(title, prefill, str => callback(eval(str)));
|
||||
},
|
||||
prompt(title, prefill, callback) {
|
||||
if (typeof prefill === 'function') {
|
||||
return this.prompt(title, /* prefill = */ null, /* callback = */ prefill);
|
||||
}
|
||||
return this.rawInput(title, prefill, callback);
|
||||
},
|
||||
alert(title, prefill, callback) {
|
||||
if (typeof prefill === 'function') {
|
||||
return this.alert(title, /* prefill = */ null, /* callback = */ prefill);
|
||||
}
|
||||
if (_.isUiThread() && !callback) {
|
||||
return new Promise((resolve) => {
|
||||
_.rtDialogs.alert(title, prefill || '', function () {
|
||||
resolve.apply(null, arguments);
|
||||
});
|
||||
});
|
||||
}
|
||||
return _.rtDialogs.alert(title, prefill || '', callback || null);
|
||||
},
|
||||
confirm(title, prefill, callback) {
|
||||
if (typeof prefill === 'function') {
|
||||
return this.confirm(title, /* prefill = */ null, /* callback = */ prefill);
|
||||
}
|
||||
if (_.isUiThread() && !callback) {
|
||||
return new Promise((resolve) => {
|
||||
_.rtDialogs.confirm(title, prefill || '', function () {
|
||||
resolve.apply(null, arguments);
|
||||
});
|
||||
});
|
||||
}
|
||||
return _.rtDialogs.confirm(title, prefill || '', callback || null);
|
||||
},
|
||||
select(title, items, callback) {
|
||||
if (Array.isArray(items)) {
|
||||
if (_.isUiThread() && !callback) {
|
||||
return new Promise((resolve) => {
|
||||
_.rtDialogs.select(title, items, function () {
|
||||
resolve.apply(null, arguments);
|
||||
});
|
||||
});
|
||||
}
|
||||
return _.rtDialogs.select(title, items, callback || null);
|
||||
}
|
||||
let itemsGatheredFromArguments = Array.from(arguments).slice(1);
|
||||
return _.rtDialogs.select(title, itemsGatheredFromArguments, null);
|
||||
},
|
||||
singleChoice(title, items, index, callback) {
|
||||
if (_.isUiThread() && !callback) {
|
||||
return new Promise((resolve) => {
|
||||
_.rtDialogs.singleChoice(title, index || 0, items, function () {
|
||||
resolve.apply(null, arguments);
|
||||
});
|
||||
});
|
||||
}
|
||||
return _.rtDialogs.singleChoice(title, index || 0, items, callback || null);
|
||||
},
|
||||
multiChoice(title, items, index, callback) {
|
||||
index = index || [];
|
||||
if (_.isUiThread() && !callback) {
|
||||
return new Promise((resolve) => {
|
||||
_.rtDialogs.multiChoice(title, index, items, function (r) {
|
||||
resolve(_.toJsArray(r));
|
||||
});
|
||||
});
|
||||
}
|
||||
if (callback) {
|
||||
return _.toJsArray(_.rtDialogs.multiChoice(title, index, items, function (r) {
|
||||
callback(_.toJsArray(r));
|
||||
}));
|
||||
}
|
||||
return _.toJsArray(_.rtDialogs.multiChoice(title, index, items, null));
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
return Dialogs;
|
||||
})(),
|
||||
propertySetters: {
|
||||
title: null,
|
||||
titleColor: { adapter: colors.toInt.bind(colors) },
|
||||
buttonRippleColor: { adapter: colors.toInt.bind(colors) },
|
||||
icon: null,
|
||||
content: null,
|
||||
contentColor: { adapter: colors.toInt.bind(colors) },
|
||||
contentLineSpacing: null,
|
||||
items: null,
|
||||
itemsColor: { adapter: colors.toInt.bind(colors) },
|
||||
positive: { method: 'positiveText' },
|
||||
positiveColor: { adapter: colors.toInt.bind(colors) },
|
||||
neutral: { method: 'neutralText' },
|
||||
neutralColor: { adapter: colors.toInt.bind(colors) },
|
||||
negative: { method: 'negativeText' },
|
||||
negativeColor: { adapter: colors.toInt.bind(colors) },
|
||||
cancelable: null,
|
||||
canceledOnTouchOutside: null,
|
||||
autoDismiss: null,
|
||||
limitIconToDefaultSize: undefined,
|
||||
},
|
||||
linkifyMask: [ 'all', 'emailAddresses', 'mapAddresses', 'phoneNumbers', 'webUrls' ],
|
||||
animation: [ 'default', 'activity', 'dialog', 'inputMethod', 'toast', 'translucent' ],
|
||||
/**
|
||||
* @type {org.autojs.autojs.runtime.api.Dialogs|org.autojs.autojs.runtime.api.Dialogs.NonUiDialogs|*}
|
||||
*/
|
||||
get rtDialogs() {
|
||||
if (_._rtDialogs === undefined) {
|
||||
_._rtDialogs = _.isUiThread()
|
||||
? scriptRuntime.dialogs
|
||||
: scriptRuntime.dialogs.nonUiDialogs;
|
||||
}
|
||||
return _._rtDialogs;
|
||||
},
|
||||
applyDialogProperty(builder, name, value) {
|
||||
if (_.propertySetters.hasOwnProperty(name)) {
|
||||
let propertySetter = _.propertySetters[name];
|
||||
if (isObjectSpecies(propertySetter)) {
|
||||
if (propertySetter.method === undefined) {
|
||||
propertySetter.method = name;
|
||||
}
|
||||
if (propertySetter.adapter) {
|
||||
value = propertySetter.adapter(value);
|
||||
}
|
||||
builder[propertySetter.method](value);
|
||||
} else {
|
||||
if (propertySetter === undefined) {
|
||||
value === true && builder[name]();
|
||||
} else {
|
||||
builder[name](value);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @param {Dialogs.Builder} builder
|
||||
* @param {Dialogs.Build.Properties} props
|
||||
*/
|
||||
applyOtherDialogProperties(builder, props) {
|
||||
if (props.inputHint !== undefined || props.inputPrefill !== undefined) {
|
||||
let inputHint = _.wrapNonNullString(props.inputHint);
|
||||
let inputPrefill = _.wrapNonNullString(props.inputPrefill);
|
||||
builder.input(inputHint, inputPrefill, (dialog, input) => {
|
||||
return builder.emit('input_change', builder.getDialog(), String(input));
|
||||
}).alwaysCallInputCallback();
|
||||
}
|
||||
|
||||
if (props.items !== undefined) {
|
||||
let itemsSelectMode = props.itemsSelectMode;
|
||||
if (itemsSelectMode === undefined || itemsSelectMode === 'select') {
|
||||
builder.itemsCallback((dialog, view, position, text) => {
|
||||
builder.emit('item_select', position, text.toString(), builder.getDialog());
|
||||
});
|
||||
} else if (itemsSelectMode === 'single') {
|
||||
let selectedIndex = props.itemsSelectedIndex === undefined ? -1 : props.itemsSelectedIndex;
|
||||
builder.itemsCallbackSingleChoice(selectedIndex, (dialog, view, which, text) => {
|
||||
builder.emit('single_choice', which, text.toString(), builder.getDialog());
|
||||
return true;
|
||||
});
|
||||
} else if (itemsSelectMode === 'multi') {
|
||||
let selectedIndices = props.itemsSelectedIndices !== undefined
|
||||
? Array.isArray(props.itemsSelectedIndices)
|
||||
? props.itemsSelectedIndices
|
||||
: [ props.itemsSelectedIndices ]
|
||||
: props.itemsSelectedIndex === undefined ? []
|
||||
: Array.isArray(props.itemsSelectedIndex)
|
||||
? props.itemsSelectedIndex
|
||||
: [ props.itemsSelectedIndex ];
|
||||
builder.itemsCallbackMultiChoice(selectedIndices, (dialog, indices, texts) => {
|
||||
builder.emit('multi_choice',
|
||||
_.toJsArray(indices, (l, i) => parseInt(l[i])),
|
||||
_.toJsArray(texts, (l, i) => l[i].toString()),
|
||||
builder.getDialog());
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
throw Error(`Unknown itemsSelectMode ${itemsSelectMode}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (props.progress !== undefined) {
|
||||
let { progress } = props;
|
||||
let isIndeterminate = progress.max === -1;
|
||||
builder.progress(isIndeterminate, progress.max, Boolean(progress.showMinMax));
|
||||
builder.progressIndeterminateStyle(Boolean(progress.horizontal));
|
||||
}
|
||||
|
||||
if (props.checkBoxPrompt !== undefined || props.checkBoxChecked !== undefined) {
|
||||
builder.checkBoxPrompt(_.wrapNonNullString(props.checkBoxPrompt),
|
||||
Boolean(props.checkBoxChecked),
|
||||
(view, checked) => builder.getDialog().emit('check', checked, builder.getDialog()));
|
||||
}
|
||||
|
||||
if (props.customView !== undefined) {
|
||||
let customView = props.customView;
|
||||
// noinspection JSTypeOfValues
|
||||
if (typeof customView === 'xml' || typeof customView === 'string') {
|
||||
customView = ui.run(() => ui.inflate(customView));
|
||||
}
|
||||
let wrapInScrollView = props.wrapInScrollView === undefined || Boolean(props.wrapInScrollView);
|
||||
builder.customView(customView, wrapInScrollView);
|
||||
}
|
||||
|
||||
if (props.stubborn) {
|
||||
let isOperationAvail = prop => prop === undefined || Boolean(prop) !== true;
|
||||
if (isOperationAvail(props.autoDismiss) && isOperationAvail(props.canceledOnTouchOutside)) {
|
||||
builder.autoDismiss(false);
|
||||
builder.canceledOnTouchOutside(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {org.autojs.autojs.core.ui.dialog.JsDialog} dialog
|
||||
* @param {Dialogs.Build.Properties} props
|
||||
*/
|
||||
applyBuiltDialogProperties(dialog, props) {
|
||||
if (props.linkify !== undefined && Boolean(props.linkify) !== false) {
|
||||
let linkify = ( /* @IIFE */ () => {
|
||||
let linkify = typeof props.linkify === 'string' ? props.linkify : 'all';
|
||||
if (_.linkifyMask.includes(linkify)) {
|
||||
linkify = linkify.replace(/[A-Z]/g, '_$&').toUpperCase();
|
||||
}
|
||||
if (linkify in Linkify) {
|
||||
return Linkify[linkify];
|
||||
}
|
||||
throw Error(`Unknown linkify: ${props.linkify}`);
|
||||
})();
|
||||
let view = dialog.getContentView();
|
||||
let text = view.getText().toString();
|
||||
ui.run(() => {
|
||||
view.setAutoLinkMask(linkify);
|
||||
view.setText(text);
|
||||
});
|
||||
}
|
||||
|
||||
if (props.onBackKey !== undefined) {
|
||||
let isFunction = typeof props.onBackKey === 'function';
|
||||
let isDisabled = Boolean(props.onBackKey) === false
|
||||
|| String(props.onBackKey).match(/^disabled?$/i);
|
||||
|
||||
if (isDisabled || isFunction) {
|
||||
dialog.setOnKeyListener({
|
||||
onKey(dialogInterface, keyCode, event) {
|
||||
if (event.getAction() !== KeyEvent.ACTION_UP || keyCode !== KeyEvent.KEYCODE_BACK) {
|
||||
return false;
|
||||
}
|
||||
if (isFunction) {
|
||||
props.onBackKey(dialog);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (props.dimAmount !== undefined) {
|
||||
let dim = Number(props.dimAmount);
|
||||
while (dim > 1) {
|
||||
dim /= 100;
|
||||
}
|
||||
if (!isNaN(dim)) {
|
||||
ui.post(() => dialog.getWindow().setDimAmount(dim));
|
||||
}
|
||||
}
|
||||
|
||||
if (props.background !== undefined) {
|
||||
let bg = props.background;
|
||||
let win = dialog.getWindow();
|
||||
ui.post(() => {
|
||||
if (typeof bg === 'string') {
|
||||
bg.startsWith('#')
|
||||
? win.setBackgroundDrawable(new ColorDrawable(colors.toInt(bg)))
|
||||
: win.setBackgroundDrawableResource(android.R.color[bg]);
|
||||
} else if (typeof bg === 'number') {
|
||||
win.setBackgroundDrawable(new ColorDrawable(bg));
|
||||
} else {
|
||||
throw TypeError(`Unknown type of background property: ${props.background}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (props.animation !== undefined && Boolean(props.animation) !== false) {
|
||||
let animation = typeof props.animation === 'string' ? props.animation : 'default';
|
||||
if (!_.animation.includes(animation)) {
|
||||
throw Error(`Unknown linkify: ${props.animation}`);
|
||||
}
|
||||
ui.post(() => {
|
||||
let win = dialog.getWindow();
|
||||
if (animation === 'default') {
|
||||
win.setWindowAnimations(android.R.style.Animation);
|
||||
} else {
|
||||
let suffix = animation[0].toUpperCase() + animation.slice(1);
|
||||
win.setWindowAnimations(android.R.style[`Animation_${suffix}`]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (props.keepScreenOn) {
|
||||
ui.post(() => {
|
||||
let win = dialog.getWindow();
|
||||
win.addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
});
|
||||
}
|
||||
},
|
||||
wrapNonNullString(str) {
|
||||
return isNullish(str) ? '' : String(str);
|
||||
},
|
||||
toJsArray(javaArray, adapter) {
|
||||
let jsArray = [];
|
||||
if (typeof adapter === 'function') {
|
||||
for (let i = 0; i < javaArray.length; i += 1) {
|
||||
jsArray.push(adapter(javaArray, i));
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < javaArray.length; i += 1) {
|
||||
jsArray.push(javaArray[i]);
|
||||
}
|
||||
}
|
||||
return jsArray;
|
||||
},
|
||||
isUiThread() {
|
||||
return Looper.myLooper() === Looper.getMainLooper();
|
||||
},
|
||||
parseColor(c) {
|
||||
if (typeof c === 'string') {
|
||||
return colors.parseColor(c);
|
||||
}
|
||||
return c;
|
||||
},
|
||||
scopeAugment() {
|
||||
/**
|
||||
* @type {(keyof Internal.Dialogs)[]}
|
||||
*/
|
||||
let methods = [ 'rawInput', 'alert', 'confirm', 'prompt' ];
|
||||
__asGlobal__(dialogs, methods);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Dialogs}
|
||||
*/
|
||||
let dialogs = new _.Dialogs();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return dialogs;
|
||||
};
|
||||
92
app/src/main/assets/modules/__engines__.js
Normal file
92
app/src/main/assets/modules/__engines__.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { files } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Engines}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const ExecutionConfig = org.autojs.autojs.execution.ExecutionConfig;
|
||||
|
||||
const rtEngines = scriptRuntime.engines;
|
||||
|
||||
let _ = {
|
||||
Engines: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Engines
|
||||
*/
|
||||
const Engines = function () {
|
||||
// Empty class body.
|
||||
};
|
||||
|
||||
Engines.prototype = {
|
||||
constructor: Engines,
|
||||
all() {
|
||||
return rtEngines.all();
|
||||
},
|
||||
myEngine() {
|
||||
return rtEngines.myEngine();
|
||||
},
|
||||
stopAll() {
|
||||
return rtEngines.stopAll();
|
||||
},
|
||||
stopAllAndToast() {
|
||||
rtEngines.stopAllAndToast();
|
||||
},
|
||||
execScript(name, script, config) {
|
||||
return rtEngines.execScript(name, script, _.fillConfig(config));
|
||||
},
|
||||
execScriptFile(path, config) {
|
||||
return rtEngines.execScriptFile(path, _.fillConfig(config));
|
||||
},
|
||||
execAutoFile(path, config) {
|
||||
return rtEngines.execAutoFile(path, _.fillConfig(config));
|
||||
},
|
||||
};
|
||||
|
||||
return Engines;
|
||||
})(),
|
||||
/**
|
||||
* @param {Internal.Engines.ExecutionConfig | org.autojs.autojs.execution.ExecutionConfig} config
|
||||
* @return {org.autojs.autojs.execution.ExecutionConfig}
|
||||
*/
|
||||
fillConfig(config) {
|
||||
let executionConfig = new ExecutionConfig();
|
||||
let c = config || {};
|
||||
|
||||
executionConfig.setWorkingDirectory(c.path || files.cwd());
|
||||
executionConfig.setDelay(c.delay || 0);
|
||||
executionConfig.setInterval(c.interval || 0);
|
||||
executionConfig.setLoopTimes(typeof c.loopTimes === 'number' ? c.loopTimes : 1);
|
||||
|
||||
Object.entries(c.arguments || []).forEach((value) => {
|
||||
let [ k, v ] = value;
|
||||
executionConfig.setArgument(k, v);
|
||||
});
|
||||
|
||||
return executionConfig;
|
||||
},
|
||||
setEngineExecArgv() {
|
||||
engines.myEngine().setExecArgv( /* @IIFE */ ((e) => {
|
||||
let execArgv = {};
|
||||
let iterator = e.getTag(ExecutionConfig.CREATOR.getTag()).arguments.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
let entry = iterator.next();
|
||||
execArgv[entry.getKey()] = entry.getValue();
|
||||
}
|
||||
return execArgv;
|
||||
})(engines.myEngine()));
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Engines}
|
||||
*/
|
||||
let engines = new _.Engines();
|
||||
|
||||
_.setEngineExecArgv();
|
||||
|
||||
return engines;
|
||||
};
|
||||
69
app/src/main/assets/modules/__events__.js
Normal file
69
app/src/main/assets/modules/__events__.js
Normal file
@@ -0,0 +1,69 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Events}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
let _ = {
|
||||
Events: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Events
|
||||
*/
|
||||
const Events = function () {
|
||||
// Empty class body.
|
||||
};
|
||||
|
||||
Events.prototype = {
|
||||
constructor: Events,
|
||||
__asEmitter__(obj, thread) {
|
||||
let emitter = thread ? this.emitter(thread) : this.emitter();
|
||||
for (let key in emitter) {
|
||||
if (obj[key] === undefined && typeof emitter[key] === 'function') {
|
||||
obj[key] = emitter[key].bind(emitter);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(Events.prototype, scriptRuntime.events);
|
||||
|
||||
return Events;
|
||||
})(),
|
||||
Keys: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Keys
|
||||
*/
|
||||
const Keys = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Keys.prototype = {
|
||||
constructor: Keys,
|
||||
home: KeyEvent.KEYCODE_HOME,
|
||||
menu: KeyEvent.KEYCODE_MENU,
|
||||
back: KeyEvent.KEYCODE_BACK,
|
||||
volume_up: KeyEvent.KEYCODE_VOLUME_UP,
|
||||
volume_down: KeyEvent.KEYCODE_VOLUME_DOWN,
|
||||
};
|
||||
|
||||
return Keys;
|
||||
})(),
|
||||
scopeAugment() {
|
||||
Object.assign(scope, {
|
||||
keys: new _.Keys(),
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Events}
|
||||
*/
|
||||
const events = new _.Events();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return events;
|
||||
};
|
||||
47
app/src/main/assets/modules/__files__.js
Normal file
47
app/src/main/assets/modules/__files__.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Files}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const RtFiles = org.autojs.autojs.runtime.api.Files;
|
||||
|
||||
let _ = {
|
||||
Files: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Files
|
||||
*/
|
||||
const Files = function () {
|
||||
// Empty class body.
|
||||
};
|
||||
|
||||
Files.prototype = {
|
||||
constructor: Files,
|
||||
join(parent, children) {
|
||||
return RtFiles.join.apply(RtFiles, arguments);
|
||||
},
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(Files.prototype, scriptRuntime.files);
|
||||
|
||||
return Files;
|
||||
})(),
|
||||
scopeAugment() {
|
||||
Object.assign(scope, {
|
||||
/** @global */
|
||||
open(path, mode, encoding, bufferSize) {
|
||||
return files.open.apply(files, arguments);
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Files}
|
||||
*/
|
||||
const files = new _.Files();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return files;
|
||||
};
|
||||
80
app/src/main/assets/modules/__floaty__.js
Normal file
80
app/src/main/assets/modules/__floaty__.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Floaty}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const ProxyJavaObject = org.autojs.autojs.rhino.ProxyJavaObject;
|
||||
|
||||
const rtFloaty = scriptRuntime.floaty;
|
||||
|
||||
let _ = {
|
||||
Floaty: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Floaty
|
||||
*/
|
||||
const Floaty = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Floaty.prototype = {
|
||||
constructor: Floaty,
|
||||
closeAll() {
|
||||
rtFloaty.closeAll();
|
||||
},
|
||||
window(xml) {
|
||||
return _.wrap(rtFloaty.window.bind(rtFloaty), xml);
|
||||
},
|
||||
rawWindow(xml) {
|
||||
return _.wrap(rtFloaty.rawWindow.bind(rtFloaty), xml);
|
||||
},
|
||||
};
|
||||
|
||||
return Floaty;
|
||||
})(),
|
||||
toXMLStringIfNeeded(xml) {
|
||||
// noinspection JSTypeOfValues
|
||||
return typeof xml === 'xml' ? xml.toXMLString() : String(xml);
|
||||
},
|
||||
/**
|
||||
* @param {(f: (context: android.content.Context, parent: android.view.ViewGroup) => android.view.View)
|
||||
* => org.autojs.autojs.runtime.api.Floaty.JsResizableWindow
|
||||
* | org.autojs.autojs.runtime.api.Floaty.JsRawWindow} windowFunction
|
||||
* @param {Xml} xml
|
||||
* @return {org.autojs.autojs.rhino.ProxyJavaObject|android.view.View}
|
||||
*/
|
||||
wrap(windowFunction, xml) {
|
||||
let { layoutInflater } = scriptRuntime.ui;
|
||||
let window = windowFunction(function (context, parent) {
|
||||
layoutInflater.setContext(context);
|
||||
return layoutInflater.inflate(_.toXMLStringIfNeeded(xml), parent, true);
|
||||
});
|
||||
let proxyObject = new ProxyJavaObject(scope, window, getClass(window));
|
||||
proxyObject.__proxy__ = {
|
||||
set(name, value) {
|
||||
window[name] = value;
|
||||
},
|
||||
get(name) {
|
||||
let value = window[name];
|
||||
if (typeof value === 'undefined') {
|
||||
if (!value) {
|
||||
value = window.findView(name);
|
||||
}
|
||||
if (!value) {
|
||||
value = undefined;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
},
|
||||
};
|
||||
return proxyObject;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Floaty}
|
||||
*/
|
||||
const floaty = new _.Floaty();
|
||||
|
||||
return floaty;
|
||||
};
|
||||
697
app/src/main/assets/modules/__globals__.js
Normal file
697
app/src/main/assets/modules/__globals__.js
Normal file
@@ -0,0 +1,697 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { autojs, console, device, pickup, ui, util, Numberx } = global;
|
||||
|
||||
/* Here, importClass() is not recommended for intelligent code completion in IDE like WebStorm. */
|
||||
/* The same is true of destructuring assignment syntax (like `let {Uri} = android.net`). */
|
||||
|
||||
let ScriptRuntime = org.autojs.autojs.runtime.ScriptRuntime;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} runtime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
*/
|
||||
module.exports = function (runtime, scope) {
|
||||
let _ = {
|
||||
scale: {
|
||||
base: {
|
||||
x: 720,
|
||||
y: 1280,
|
||||
},
|
||||
baseState: {
|
||||
x: false,
|
||||
y: false,
|
||||
},
|
||||
ensureBase(o) {
|
||||
if (!(o > 0 && Number.isInteger(o))) {
|
||||
throw RangeError(`Scale base "${o}" must be a positive integer.`);
|
||||
}
|
||||
},
|
||||
ensureBaseXSetOnlyOnce(x) {
|
||||
if (this.baseState.x === x) {
|
||||
throw Error(`Scale base X could be set only once, ${this.base.x} has been set as the base.`);
|
||||
}
|
||||
},
|
||||
ensureBaseYSetOnlyOnce(y) {
|
||||
if (this.baseState.y === y) {
|
||||
throw Error(`Scale base Y could be set only once, ${this.base.y} has been set as the base.`);
|
||||
}
|
||||
},
|
||||
ensureBasesConsistent() {
|
||||
if (this.baseState.x !== this.baseState.y) {
|
||||
throw Error(`Scale bases must be consistent, { x: ${this.baseState.x}, y: ${this.baseState.y} }.`);
|
||||
}
|
||||
},
|
||||
},
|
||||
uiHandler: runtime.getUiHandler(),
|
||||
buildTypes: {
|
||||
release: 100, beta: 50, alpha: 0,
|
||||
},
|
||||
toasts: {
|
||||
/**
|
||||
* @type {Set<android.widget.Toast>}
|
||||
*/
|
||||
pool: new Set(),
|
||||
lock: new ReentrantLock(),
|
||||
add(t) {
|
||||
if (t instanceof Toast) {
|
||||
this.lock.lock();
|
||||
this.pool.add(t);
|
||||
this.addCallback(t);
|
||||
this.lock.unlock();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @param {android.widget.Toast} t
|
||||
*/
|
||||
addCallback(t) {
|
||||
const remove = () => _.toasts.remove(t);
|
||||
|
||||
if (util.version.sdkInt >= util.versionCodes.R) {
|
||||
t.addCallback(new JavaAdapter(Toast.Callback, {
|
||||
onToastShown: () => void 0,
|
||||
onToastHidden: remove,
|
||||
}));
|
||||
} else {
|
||||
_.uiHandler.postDelayed(new JavaAdapter(java.lang.Runnable, {
|
||||
run: remove,
|
||||
}), this.getDuration(t) + 1e3 /* As toast may show with some delay. */);
|
||||
}
|
||||
},
|
||||
remove(t) {
|
||||
if (this.pool.has(t)) {
|
||||
this.lock.lock();
|
||||
this.pool.delete(t);
|
||||
this.lock.unlock();
|
||||
}
|
||||
},
|
||||
dismissAll() {
|
||||
if (this.pool.size > 0) {
|
||||
this.lock.lock();
|
||||
this.pool.forEach((t) => t.cancel());
|
||||
this.pool.clear();
|
||||
this.lock.unlock();
|
||||
}
|
||||
},
|
||||
getDuration(t) {
|
||||
let du = {
|
||||
SHORT_DELAY: 2e3,
|
||||
LONG_DELAY: 3.5e3,
|
||||
};
|
||||
switch (t.getDuration()) {
|
||||
case Toast.LENGTH_SHORT:
|
||||
return du.SHORT_DELAY;
|
||||
case Toast.LENGTH_LONG:
|
||||
return du.LONG_DELAY;
|
||||
default:
|
||||
return Math.max.apply(null, Object.values(du));
|
||||
}
|
||||
},
|
||||
},
|
||||
extensions: {
|
||||
/** @global */
|
||||
get WIDTH() {
|
||||
return ScreenMetrics.getDeviceScreenWidth();
|
||||
},
|
||||
/** @global */
|
||||
get HEIGHT() {
|
||||
return ScreenMetrics.getDeviceScreenHeight();
|
||||
},
|
||||
// @Caution by SuperMonster003 on Oct 11, 2022.
|
||||
// ! android.widget.Toast.makeText() doesn't work well on Android API Level 28 (Android 9) [P].
|
||||
// ! There hasn't been a solution for this so far.
|
||||
// ! Tested devices:
|
||||
// ! 1. SONY XPERIA XZ1 Compact (G8441)
|
||||
// ! 2. Android Studio AVD (Android 9.0 x86)
|
||||
/** @global */
|
||||
toast(msg, isLong, isForcible) {
|
||||
let $ = {
|
||||
rex: {
|
||||
long: /^l(ong)?$/i,
|
||||
short: /^s(hort)?$/i,
|
||||
forcible: /^f(orcible)?$/i,
|
||||
},
|
||||
toast() {
|
||||
this.init(arguments);
|
||||
this.show();
|
||||
},
|
||||
init() {
|
||||
this.message = isNullish(msg) ? '' : String(msg);
|
||||
this.isForcible = this.parseIsForcible(isForcible);
|
||||
this.isLong = this.parseIsLong(isLong);
|
||||
},
|
||||
parseIsLong(isLong) {
|
||||
if (typeof isLong === 'boolean') {
|
||||
return isLong;
|
||||
}
|
||||
if (typeof isLong === 'number') {
|
||||
return Boolean(isLong);
|
||||
}
|
||||
if (typeof isLong === 'string') {
|
||||
if (this.rex.long.test(isLong)) {
|
||||
return true;
|
||||
}
|
||||
if (this.rex.short.test(isLong)) {
|
||||
return false;
|
||||
}
|
||||
if (this.rex.forcible.test(isLong)) {
|
||||
this.isForcible = true;
|
||||
return false;
|
||||
}
|
||||
throw Error(`Invalid param: {name: isLong, value: ${isLong}, type: ${species(isLong)}.`);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
parseIsForcible(isForcible) {
|
||||
if (typeof isForcible === 'boolean') {
|
||||
return isForcible;
|
||||
}
|
||||
if (typeof isForcible === 'number') {
|
||||
return Boolean(isForcible);
|
||||
}
|
||||
if (typeof isForcible === 'string') {
|
||||
if (this.rex.forcible.test(isForcible)) {
|
||||
return true;
|
||||
}
|
||||
throw Error(`Invalid param: {name: isForcible, value: ${isForcible}, type: ${species(isForcible)}.`);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
show() {
|
||||
_.uiHandler.post(() => {
|
||||
if ($.isForcible) {
|
||||
_.toasts.dismissAll();
|
||||
}
|
||||
let len = $.isLong ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT;
|
||||
let o = Toast.makeText(_.uiHandler.getContext(), $.message, len);
|
||||
_.toasts.add(o);
|
||||
o.show();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
$.toast();
|
||||
},
|
||||
/** @global */
|
||||
toastLog(msg, isLong, isForcible) {
|
||||
this.toast.apply(this, arguments);
|
||||
console.log(msg);
|
||||
},
|
||||
/** @global */
|
||||
sleep(millisMin, millisMax) {
|
||||
let $ = {
|
||||
rexNum: /[+-]?(\d+(\.\d+)?(e\d+)?)/,
|
||||
set min(v) {
|
||||
this._min = Number(v);
|
||||
},
|
||||
get min() {
|
||||
return Math.max(this._min, 0);
|
||||
},
|
||||
set max(v) {
|
||||
this._max = Number(v);
|
||||
},
|
||||
get max() {
|
||||
return Math.min(this._max, Number.MAX_SAFE_INTEGER);
|
||||
},
|
||||
sleep(min, max) {
|
||||
if (this.trigger()) {
|
||||
this.parseArgs(min, max);
|
||||
try {
|
||||
runtime.sleep(this.min + this.randBound);
|
||||
} catch (e) {
|
||||
if (!(e.javaException instanceof ScriptInterruptedException)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
trigger() {
|
||||
if (ui.isUiThread()) {
|
||||
throw Error('不能在ui线程执行阻塞操作,请使用setTimeout代替.');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
parseArgs(min, max) {
|
||||
this.parseMin(min);
|
||||
this.parseMax(max);
|
||||
this.parseRandBound();
|
||||
},
|
||||
parseMin(min) {
|
||||
if (typeof min !== 'number') {
|
||||
throw TypeError('Type of millisMin must be a number.');
|
||||
}
|
||||
this.min = min;
|
||||
},
|
||||
parseMax(max) {
|
||||
if (typeof max === 'number') {
|
||||
this.max = max;
|
||||
} else if (typeof max === 'string') {
|
||||
let matched = max.match(this.rexNum);
|
||||
if (matched === null) {
|
||||
throw TypeError('String millisMax must have a number contained.');
|
||||
}
|
||||
let delta = Number(matched[0]);
|
||||
this.max = this.min + delta;
|
||||
this.min = this.min - delta;
|
||||
} else {
|
||||
this.max = this.min;
|
||||
}
|
||||
},
|
||||
parseRandBound() {
|
||||
this.randBound = Math.ceil(Math.random() * (this.max - this.min));
|
||||
},
|
||||
};
|
||||
|
||||
$.sleep(millisMin, millisMax);
|
||||
},
|
||||
/** @global */
|
||||
isStopped() {
|
||||
return runtime.isStopped();
|
||||
},
|
||||
/** @global */
|
||||
isShuttingDown() {
|
||||
return isStopped();
|
||||
},
|
||||
/** @global */
|
||||
notStopped() {
|
||||
return !this.isStopped();
|
||||
},
|
||||
/** @global */
|
||||
isRunning() {
|
||||
return !this.isStopped();
|
||||
},
|
||||
/** @global */
|
||||
exit(e) {
|
||||
if (typeof e === 'undefined') {
|
||||
runtime.exit();
|
||||
} else if (typeof e === 'string') {
|
||||
runtime.exit(new java.lang.Exception(e));
|
||||
} else if (typeof e instanceof java.lang.Throwable) {
|
||||
runtime.exit(e);
|
||||
} else {
|
||||
throw TypeError(`Unknown type of argument "e" with value ${e}} for exit()`);
|
||||
}
|
||||
},
|
||||
/** @global */
|
||||
stop() {
|
||||
this.exit();
|
||||
},
|
||||
/** @global */
|
||||
setClip(text) {
|
||||
return runtime.setClip(text);
|
||||
},
|
||||
/** @global */
|
||||
getClip() {
|
||||
return runtime.getClip();
|
||||
},
|
||||
/** @global */
|
||||
currentPackage() {
|
||||
auto();
|
||||
return runtime.info.getLatestPackage();
|
||||
},
|
||||
/** @global */
|
||||
currentActivity() {
|
||||
auto();
|
||||
return runtime.info.getLatestActivity();
|
||||
},
|
||||
/**
|
||||
* @global
|
||||
* @param {Wait.Condition} condition
|
||||
* @param {?number|Wait.Callback} [limit=10e3]
|
||||
* @param {?number|Wait.Callback} [interval=200]
|
||||
* @param {Wait.Callback} [callback]
|
||||
* @return {any}
|
||||
*/
|
||||
wait(condition, limit, interval, callback) {
|
||||
if (isObjectSpecies(arguments[1])) {
|
||||
// @Overload wait(condition, callback): any
|
||||
return this.wait(condition, /* limit = */ null, /* interval = */ null, /* callback = */ arguments[1]);
|
||||
}
|
||||
|
||||
if (isObjectSpecies(arguments[2])) {
|
||||
// @Overload wait(condition, limit, callback): any
|
||||
return this.wait(condition, limit, /* interval = */ null, /* callback = */ arguments[2]);
|
||||
}
|
||||
|
||||
let $ = {
|
||||
result: false,
|
||||
start: Date.now(),
|
||||
callback: callback || {},
|
||||
parseArgs() {
|
||||
let lmt = typeof limit === 'number' ? limit : limit === null ? NaN : Number(limit);
|
||||
if (isNaN(lmt)) {
|
||||
lmt = 10e3;
|
||||
}
|
||||
if (lmt < 0) {
|
||||
throw Error(`Limitation (${lmt}) cannot be negative for wait().`);
|
||||
}
|
||||
if (lmt < 100) {
|
||||
this.times = lmt;
|
||||
this.timeout = Infinity;
|
||||
} else {
|
||||
this.times = Infinity;
|
||||
this.timeout = lmt;
|
||||
}
|
||||
|
||||
let itv = typeof interval === 'number' ? interval : interval === null ? NaN : Number(interval);
|
||||
if (isNaN(itv)) {
|
||||
itv = 200;
|
||||
}
|
||||
if (!isFinite(itv)) {
|
||||
throw Error(`Interval cannot be Infinity for wait().`);
|
||||
}
|
||||
if (itv < 0) {
|
||||
throw Error(`Interval (${itv}) cannot be negative for wait().`);
|
||||
}
|
||||
this.interval = itv;
|
||||
|
||||
if (this.interval >= this.timeout) {
|
||||
this.times = Math.min(this.times, 1);
|
||||
}
|
||||
},
|
||||
check() {
|
||||
if (condition instanceof UiObject) {
|
||||
throw TypeError('UiObject cannot be used as the condition for wait().');
|
||||
}
|
||||
return typeof condition === 'function' ? condition() : pickup(condition);
|
||||
},
|
||||
wait() {
|
||||
if (!this.times) {
|
||||
return;
|
||||
}
|
||||
while (true) {
|
||||
let checked = this.checked = this.check();
|
||||
|
||||
// Some falsy values [ 0, 0n, -0, "" (empty string) ] should pass the check.
|
||||
this.result = !(isNullish(checked) || Number.isNaN(checked) || checked === false);
|
||||
|
||||
this.times -= 1;
|
||||
|
||||
if (this.result || !this.times) {
|
||||
break;
|
||||
}
|
||||
if (Date.now() - this.start > this.timeout) {
|
||||
break;
|
||||
}
|
||||
sleep(this.interval);
|
||||
}
|
||||
},
|
||||
callbackIFN() {
|
||||
let fn = this.result ? this.callback.then : this.callback.else;
|
||||
if (fn !== undefined) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw TypeError(`Callback must be function type for wait().`);
|
||||
}
|
||||
let res = fn(this.checked);
|
||||
if (res !== undefined) {
|
||||
this.result = res;
|
||||
}
|
||||
}
|
||||
},
|
||||
getResult() {
|
||||
this.parseArgs();
|
||||
this.wait();
|
||||
this.callbackIFN();
|
||||
|
||||
return this.result;
|
||||
},
|
||||
};
|
||||
|
||||
return $.getResult();
|
||||
},
|
||||
/** @global */
|
||||
waitForActivity(activityName, limit, interval, callback) {
|
||||
_.ensureNonUiThread();
|
||||
let condition = () => currentActivity() === activityName;
|
||||
return wait.apply(scope, [ condition ].concat(Array.from(arguments).slice(1)));
|
||||
},
|
||||
/** @global */
|
||||
waitForPackage(packageName, limit, interval, callback) {
|
||||
_.ensureNonUiThread();
|
||||
let condition = () => currentPackage() === packageName;
|
||||
return wait.apply(scope, [ condition ].concat(Array.from(arguments).slice(1)));
|
||||
},
|
||||
/** @global */
|
||||
random(min, max) {
|
||||
if (arguments.length === 0) {
|
||||
return Math.random();
|
||||
}
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
},
|
||||
/** @global */
|
||||
setScreenMetrics(width, height) {
|
||||
runtime.setScreenMetrics(width, height);
|
||||
},
|
||||
/** @global */
|
||||
requiresApi(requiresApi) {
|
||||
ScriptRuntime.requiresApi(requiresApi);
|
||||
},
|
||||
/** @global */
|
||||
requiresAutojsVersion(version) {
|
||||
if (typeof version === 'number') {
|
||||
if (_.compare(version, autojs.versionCode) > 0) {
|
||||
throw Error(`AutoJs6 版本号需不低于 ${version}.`);
|
||||
}
|
||||
} else {
|
||||
if (_.compareVersion(version, autojs.versionName) > 0) {
|
||||
throw Error(`AutoJs6 版本需不低于 ${version}.`);
|
||||
}
|
||||
}
|
||||
},
|
||||
getScaleBases() {
|
||||
return _.scale.base;
|
||||
},
|
||||
getScaleBaseX() {
|
||||
return _.scale.base.x;
|
||||
},
|
||||
getScaleBaseY() {
|
||||
return _.scale.base.y;
|
||||
},
|
||||
setScaleBases(baseX, baseY) {
|
||||
this.setScaleBaseX(baseX);
|
||||
this.setScaleBaseY(baseY);
|
||||
},
|
||||
setScaleBaseX(baseX) {
|
||||
_.scale.ensureBaseXSetOnlyOnce(baseX);
|
||||
_.scale.ensureBase(baseX);
|
||||
_.scale.base.x = baseX;
|
||||
_.scale.baseState.x = true;
|
||||
},
|
||||
setScaleBaseY(baseY) {
|
||||
_.scale.ensureBaseYSetOnlyOnce(baseY);
|
||||
_.scale.ensureBase(baseY);
|
||||
_.scale.base.y = baseY;
|
||||
_.scale.baseState.y = true;
|
||||
},
|
||||
/** @global */
|
||||
cX(num, base, isRatio) {
|
||||
let W = device.width;
|
||||
if (arguments.length === 0) {
|
||||
return W;
|
||||
}
|
||||
// @Overload
|
||||
if (typeof base === 'boolean') {
|
||||
return this.cX(num, null, base);
|
||||
}
|
||||
if (Math.abs(num) < 1 && isRatio !== false || isRatio) {
|
||||
return Math.round(W * num);
|
||||
}
|
||||
if (typeof base === 'number') {
|
||||
_.scale.ensureBase(base);
|
||||
} else {
|
||||
base = _.scale.base.x;
|
||||
}
|
||||
return Math.round(W * num / base);
|
||||
},
|
||||
/** @global */
|
||||
cY(num, base, isRatio) {
|
||||
let H = device.height;
|
||||
if (arguments.length === 0) {
|
||||
return H;
|
||||
}
|
||||
// @Overload
|
||||
if (typeof base === 'boolean') {
|
||||
return this.cY(num, null, base);
|
||||
}
|
||||
if (Math.abs(num) < 1 && isRatio !== false || isRatio) {
|
||||
return Math.round(H * num);
|
||||
}
|
||||
if (typeof base === 'number') {
|
||||
_.scale.ensureBase(base);
|
||||
} else {
|
||||
base = _.scale.base.y;
|
||||
}
|
||||
return Math.round(H * num / base);
|
||||
},
|
||||
/** @global */
|
||||
cYx(num, base, isRatio) {
|
||||
_.scale.ensureBasesConsistent();
|
||||
// @Overload
|
||||
if (typeof base === 'boolean') {
|
||||
return this.cYx(num, null, base);
|
||||
}
|
||||
// @Overload
|
||||
if (typeof base === 'string') {
|
||||
return this.cYx(num, Numberx.parseRatio(base), true);
|
||||
}
|
||||
let W = device.width;
|
||||
if (Math.abs(num) < 1 || isRatio) {
|
||||
if (isNullish(base)) {
|
||||
base = _.scale.base.y / _.scale.base.x;
|
||||
}
|
||||
if (typeof base === 'number') {
|
||||
return Numberx.check(0, '<', base, '<=', 1)
|
||||
? Math.round(num * W / base)
|
||||
: Math.round(num * W * base);
|
||||
}
|
||||
throw Error('Base of cYx() must be a valid number.');
|
||||
}
|
||||
if (isNullish(base)) {
|
||||
base = _.scale.base.x;
|
||||
}
|
||||
return Math.round(num * W / base);
|
||||
},
|
||||
/** @global */
|
||||
cXy(num, base, isRatio) {
|
||||
_.scale.ensureBasesConsistent();
|
||||
// @Overload
|
||||
if (typeof base === 'boolean') {
|
||||
return this.cXy(num, null, base);
|
||||
}
|
||||
// @Overload
|
||||
if (typeof base === 'string') {
|
||||
return this.cXy(num, Numberx.parseRatio(base), true);
|
||||
}
|
||||
let H = device.height;
|
||||
if (Math.abs(num) < 1 || isRatio) {
|
||||
if (isNullish(base)) {
|
||||
base = _.scale.base.y / _.scale.base.x;
|
||||
}
|
||||
if (typeof base === 'number') {
|
||||
return Numberx.check(0, '<', base, '<=', 1)
|
||||
? Math.round(num * H * base)
|
||||
: Math.round(num * H / base);
|
||||
}
|
||||
throw Error('Base of cXy() must be a valid number.');
|
||||
}
|
||||
if (isNullish(base)) {
|
||||
base = _.scale.base.y;
|
||||
}
|
||||
return Math.round(num * H / base);
|
||||
},
|
||||
$bind() {
|
||||
this.toast.dismissAll = () => {
|
||||
_.uiHandler.post(() => {
|
||||
_.toasts.dismissAll();
|
||||
});
|
||||
};
|
||||
delete this.$bind;
|
||||
return this;
|
||||
},
|
||||
// $selfProtect() {
|
||||
// /* Protection of global properties from being modified or deleted. */
|
||||
// ( /* @IIFE */ () => [
|
||||
// [ 'auto', 'colors' ],
|
||||
//
|
||||
// [ 'android', 'com', 'edu', 'java', 'javax', 'net', 'org' ],
|
||||
//
|
||||
// [ 'Array', 'BigInt', 'Boolean', 'Error', 'Function', 'JSON', 'Map', 'Math' ],
|
||||
// [ 'Module', 'Number', 'Object', 'Promise', 'RegExp', 'Set', 'String', 'Symbol' ],
|
||||
//
|
||||
// [ 'clearImmediate', 'clearInterval', 'clearTimeout', 'decodeURI', 'decodeURIComponent' ],
|
||||
// [ 'encodeURI', 'encodeURIComponent', 'escape', 'eval', 'isFinite', 'isNaN', 'parseFloat' ],
|
||||
// [ 'parseInt', 'setImmediate', 'setInterval', 'setTimeout', 'unescape' ],
|
||||
//
|
||||
// [ 'Packages', 'alert', 'confirm', 'click', 'err', 'log', 'pickup', 'detect', 'prompt' ],
|
||||
// ]
|
||||
// .flat()
|
||||
// .filter((name) => {
|
||||
// return Object.prototype.hasOwnProperty.call(scope, name)
|
||||
// && Object.getOwnPropertyDescriptor(scope, name).writable;
|
||||
// })
|
||||
// .forEach((key) => {
|
||||
// Object.defineProperty(scope, key, {
|
||||
// configurable: false,
|
||||
// writable: false,
|
||||
// });
|
||||
// }))();
|
||||
//
|
||||
// delete this.$selfProtect;
|
||||
// },
|
||||
$appropriateProtect() {
|
||||
[
|
||||
'continuation', 'selector',
|
||||
].forEach((key) => {
|
||||
Object.defineProperty(scope, key, {
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
});
|
||||
});
|
||||
|
||||
delete this.$appropriateProtect;
|
||||
},
|
||||
},
|
||||
ensureNonUiThread() {
|
||||
if (ui.isUiThread()) {
|
||||
throw Error('不能在ui线程执行阻塞操作,请在子线程或子脚本执行,或者使用setInterval循环检测当前activity和package.');
|
||||
}
|
||||
},
|
||||
compareVersion(v1, v2) {
|
||||
v1 = this.parseVersion(v1);
|
||||
v2 = this.parseVersion(v2);
|
||||
if (v1.major !== v2.major) {
|
||||
return this.compare(v1.major, v2.major);
|
||||
}
|
||||
if (v1.minor !== v2.minor) {
|
||||
return this.compare(v1.minor, v2.minor);
|
||||
}
|
||||
if (v1.revision !== v2.revision) {
|
||||
return this.compare(v1.revision, v2.revision);
|
||||
}
|
||||
if (v1.buildType !== v2.buildType) {
|
||||
return this.compare(v1.buildType, v2.buildType);
|
||||
}
|
||||
return this.compare(v1.build, v2.build);
|
||||
},
|
||||
compare(a, b) {
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
},
|
||||
parseVersion(v) {
|
||||
const m = /(\d+)\.(\d+)\.(\d+)\s*(A(lpha)?|B(eta)?)?(\d*)/i.exec(v);
|
||||
if (!m) {
|
||||
throw Error(`版本格式不合法: ${v}.`);
|
||||
}
|
||||
return {
|
||||
major: parseInt(m[1]),
|
||||
minor: parseInt(m[2]),
|
||||
revision: parseInt(m[3]),
|
||||
buildType: _.buildType(m[4]),
|
||||
build: m[5] ? parseInt(m[5]) : 1,
|
||||
};
|
||||
},
|
||||
buildType(str) {
|
||||
if (str === 'Alpha') {
|
||||
return this.buildTypes.alpha;
|
||||
}
|
||||
if (str === 'Beta') {
|
||||
return this.buildTypes.beta;
|
||||
}
|
||||
return this.buildTypes.release;
|
||||
},
|
||||
};
|
||||
|
||||
Object.assign(scope, _.extensions.$bind());
|
||||
|
||||
// Object.keys(_.extensions)
|
||||
// .filter(key => !key.startsWith('$'))
|
||||
// .forEach((key) => {
|
||||
// Object.defineProperty(scope, key, {
|
||||
// enumerable: true,
|
||||
// configurable: false,
|
||||
// writable: false,
|
||||
// });
|
||||
// });
|
||||
};
|
||||
310
app/src/main/assets/modules/__http__.js
Normal file
310
app/src/main/assets/modules/__http__.js
Normal file
@@ -0,0 +1,310 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { ui } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Http}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const PFile = org.autojs.pio.PFile;
|
||||
const Request = okhttp3.Request;
|
||||
const RequestBody = okhttp3.RequestBody;
|
||||
const MultipartBody = okhttp3.MultipartBody;
|
||||
const MediaType = okhttp3.MediaType;
|
||||
const FormBody = okhttp3.FormBody;
|
||||
const Callback = okhttp3.Callback;
|
||||
const MimeTypeMap = android.webkit.MimeTypeMap;
|
||||
|
||||
let _ = {
|
||||
Http: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Http
|
||||
*/
|
||||
const Http = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Http.prototype = {
|
||||
constructor: Http,
|
||||
__okhttp__: new MutableOkHttp(),
|
||||
/**
|
||||
* @returns {okhttp3.OkHttpClient}
|
||||
*/
|
||||
client() {
|
||||
return this.__okhttp__.client();
|
||||
},
|
||||
/**
|
||||
* @param {string} url
|
||||
* @param {Http.RequestOptions} [options]
|
||||
* @return {okhttp3.Request}
|
||||
*/
|
||||
buildRequest(url, options) {
|
||||
let __ = {
|
||||
options: options || {},
|
||||
getUrl(url) {
|
||||
if (typeof url !== 'string') {
|
||||
throw TypeError('Param url must be a string');
|
||||
}
|
||||
// noinspection HttpUrlsUsage
|
||||
return url.match(/^https?:\/\//) ? url : `http://${url}`;
|
||||
},
|
||||
setHeaders(request) {
|
||||
Object.entries(this.options.headers || {}).forEach((entries) => {
|
||||
let [ key, value ] = entries;
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach(v => request.header(key, v));
|
||||
} else {
|
||||
request.header(key, value);
|
||||
}
|
||||
});
|
||||
},
|
||||
setMethod(request) {
|
||||
if (this.options.body) {
|
||||
this.ensureMethodInOptions();
|
||||
request.method(this.options.method, this.parseBody());
|
||||
} else if (this.options.files) {
|
||||
this.ensureMethodInOptions();
|
||||
request.method(this.options.method, this.parseMultipart());
|
||||
} else {
|
||||
this.ensureMethodInOptions();
|
||||
request.method(this.options.method, null);
|
||||
}
|
||||
},
|
||||
ensureMethodInOptions() {
|
||||
if (typeof this.options.method !== 'string') {
|
||||
throw Error('Property method is required for header options');
|
||||
}
|
||||
},
|
||||
parseBody() {
|
||||
let body = this.options.body;
|
||||
|
||||
if (body instanceof RequestBody) {
|
||||
return body;
|
||||
}
|
||||
if (typeof body === 'string') {
|
||||
return RequestBody.create(MediaType.parse(this.options.contentType), body);
|
||||
}
|
||||
if (typeof body === 'function') {
|
||||
// noinspection JSValidateTypes
|
||||
return new RequestBody({
|
||||
contentType() {
|
||||
return MediaType.parse(this.options.contentType);
|
||||
},
|
||||
writeTo: body,
|
||||
});
|
||||
}
|
||||
throw TypeError('Unknown type of body for header options');
|
||||
},
|
||||
parseMultipart() {
|
||||
let files = this.options.files;
|
||||
|
||||
let builder = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM);
|
||||
|
||||
Object.entries(files).forEach((entries) => {
|
||||
let [ key, value ] = entries;
|
||||
if (typeof value === 'string') {
|
||||
builder.addFormDataPart(key, value);
|
||||
return;
|
||||
}
|
||||
let path, mimeType, fileName;
|
||||
if (typeof value.getPath === 'function') {
|
||||
path = value.getPath();
|
||||
} else if (value.length === 2) {
|
||||
[ fileName, path ] = value;
|
||||
} else if (value.length > 2) {
|
||||
[ fileName, mimeType, path ] = value;
|
||||
}
|
||||
let file = new PFile(path);
|
||||
fileName = fileName || file.getName();
|
||||
mimeType = mimeType || this.parseMimeType(file.getExtension());
|
||||
let requestBody = RequestBody.create(MediaType.parse(mimeType), file);
|
||||
builder.addFormDataPart(key, fileName, requestBody);
|
||||
});
|
||||
|
||||
return builder.build();
|
||||
},
|
||||
parseMimeType(ext) {
|
||||
if (ext.length > 0) {
|
||||
let type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
|
||||
if (type) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return 'application/octet-stream';
|
||||
},
|
||||
};
|
||||
|
||||
let $$ = {
|
||||
request: new Request.Builder(),
|
||||
build() {
|
||||
this.setUrl();
|
||||
this.setHeader();
|
||||
this.setMethod();
|
||||
|
||||
return this.request.build();
|
||||
},
|
||||
setUrl() {
|
||||
this.request.url(__.getUrl(url));
|
||||
},
|
||||
setHeader() {
|
||||
__.setHeaders(this.request);
|
||||
},
|
||||
setMethod() {
|
||||
__.setMethod(this.request);
|
||||
},
|
||||
};
|
||||
|
||||
return $$.build();
|
||||
},
|
||||
/**
|
||||
* @param {string} url
|
||||
* @param {Http.RequestOptions} [options]
|
||||
* @param {(response: Http.WrappedResponse, ex?: java.io.IOException) => void} [callback]
|
||||
* @return {Http.WrappedResponse | void}
|
||||
*/
|
||||
request(url, options, callback) {
|
||||
let cont = !callback && ui.isUiThread() && continuation.enabled
|
||||
? continuation.create() : null;
|
||||
|
||||
/**
|
||||
* @type {okhttp3.Call}
|
||||
*/
|
||||
let call = this.client().newCall(this.buildRequest(url, options));
|
||||
|
||||
if (!callback && !cont) {
|
||||
return _.wrapResponse(call.execute());
|
||||
}
|
||||
|
||||
call.enqueue(new Callback({
|
||||
onResponse(call, response) {
|
||||
let wrappedResponse = _.wrapResponse(response);
|
||||
cont && cont.resume(wrappedResponse);
|
||||
callback && callback(wrappedResponse);
|
||||
},
|
||||
onFailure(call, ex) {
|
||||
cont && cont.resumeError(ex);
|
||||
callback && callback(null, ex);
|
||||
},
|
||||
}));
|
||||
|
||||
if (cont) {
|
||||
return cont.await();
|
||||
}
|
||||
},
|
||||
get(url, options, callback) {
|
||||
return this.request(url, Object.assign(options || {}, {
|
||||
method: 'GET',
|
||||
}), callback);
|
||||
},
|
||||
post(url, data, options, callback) {
|
||||
let opt = Object.assign({
|
||||
contentType: _.constants.DEF_CONTENT_TYPE,
|
||||
}, options, {
|
||||
method: 'POST',
|
||||
});
|
||||
_.fillPostData(opt, data);
|
||||
return this.request(url, opt, callback);
|
||||
},
|
||||
postJson(url, data, options, callback) {
|
||||
return this.post(url, data, Object.assign(options || {}, {
|
||||
contentType: 'application/json',
|
||||
}), callback);
|
||||
},
|
||||
postMultipart(url, files, options, callback) {
|
||||
return this.request(url, Object.assign(options || {}, {
|
||||
method: 'POST',
|
||||
contentType: 'multipart/form-data',
|
||||
files: files,
|
||||
}), callback);
|
||||
},
|
||||
};
|
||||
|
||||
return Http;
|
||||
})(),
|
||||
constants: {
|
||||
DEF_CONTENT_TYPE: 'application/x-www-form-urlencoded',
|
||||
},
|
||||
/**
|
||||
* @param {okhttp3.Response} res
|
||||
* @return {Http.WrappedResponse}
|
||||
*/
|
||||
wrapResponse: (res) => /* @AXR */ ({
|
||||
request: res.request(),
|
||||
getResponse() {
|
||||
return {
|
||||
request: this.request,
|
||||
statusMessage: res.message(),
|
||||
statusCode: res.code(),
|
||||
body: this.getBody(),
|
||||
headers: this.getHeaders(),
|
||||
url: this.request.url(),
|
||||
method: this.request.method(),
|
||||
};
|
||||
},
|
||||
getHeaders() {
|
||||
let result = {};
|
||||
let headers = res.headers();
|
||||
for (let i = 0; i < headers.size(); i += 1) {
|
||||
let name = headers.name(i);
|
||||
let value = headers.value(i);
|
||||
if (!(name in result)) {
|
||||
result[name] = value;
|
||||
continue;
|
||||
}
|
||||
let origin = result[name];
|
||||
if (!Array.isArray(origin)) {
|
||||
result[name] = [ origin ];
|
||||
}
|
||||
result[name].push(value);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
getBody() {
|
||||
let body = res.body();
|
||||
return {
|
||||
string: body.string.bind(body),
|
||||
bytes: body.bytes.bind(body),
|
||||
contentType: body.contentType(),
|
||||
json() {
|
||||
try {
|
||||
return JSON.parse(this.string());
|
||||
} catch (e) {
|
||||
throw Error('Failed to parse JSON. Body string may be not in JSON format');
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
}.getResponse()),
|
||||
/**
|
||||
* @param {Http.RequestOptions} options
|
||||
* @param {?Object.<string, string> | string} data
|
||||
*/
|
||||
fillPostData(options, data) {
|
||||
data = data || {};
|
||||
if (options.contentType === _.constants.DEF_CONTENT_TYPE) {
|
||||
let b = new FormBody.Builder();
|
||||
Object.entries(data).forEach((entries) => {
|
||||
let [ key, value ] = entries;
|
||||
b.add(key, value);
|
||||
});
|
||||
options.body = b.build();
|
||||
} else if (options.contentType === 'application/json') {
|
||||
options.body = JSON.stringify(data);
|
||||
} else {
|
||||
options.body = data;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Http}
|
||||
*/
|
||||
const http = new _.Http();
|
||||
|
||||
return http;
|
||||
};
|
||||
102
app/src/main/assets/modules/__i18n__.js
Normal file
102
app/src/main/assets/modules/__i18n__.js
Normal file
@@ -0,0 +1,102 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { files } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.I18n}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
let _ = {
|
||||
I18n: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @type {Internal.Banana}
|
||||
*/
|
||||
const banana = new (require('banana-i18n'))(void 0, { finalFallback: 'default' });
|
||||
|
||||
/**
|
||||
* @implements Internal.I18n
|
||||
*/
|
||||
const I18n = function () {
|
||||
return Object.assign(banana.i18n.bind(banana), I18n.prototype);
|
||||
};
|
||||
|
||||
I18n.prototype = {
|
||||
constructor: I18n,
|
||||
banana,
|
||||
setPath(relativePath) {
|
||||
if (!files.isDir(relativePath)) {
|
||||
throw Error(`Invalid path: ${relativePath}`);
|
||||
}
|
||||
_.config.path = relativePath;
|
||||
},
|
||||
setLocale(locale) {
|
||||
banana.setLocale(locale);
|
||||
},
|
||||
getFallbackLocales() {
|
||||
return banana.getFallbackLocales();
|
||||
},
|
||||
getParser() {
|
||||
return banana.parser;
|
||||
},
|
||||
getPath() {
|
||||
if (!files.isDir(_.config.path)) {
|
||||
let fallback = files.join('assets', _.config.path);
|
||||
if (files.isDir(fallback)) {
|
||||
this.setPath(fallback);
|
||||
}
|
||||
}
|
||||
return _.config.path;
|
||||
},
|
||||
getLocale() {
|
||||
return banana.locale;
|
||||
},
|
||||
getFinalFallback() {
|
||||
return banana.finalFallback;
|
||||
},
|
||||
load(messageSource, locale) {
|
||||
if (typeof messageSource === 'object') {
|
||||
return banana.load(messageSource, locale);
|
||||
}
|
||||
if (typeof messageSource === 'string') {
|
||||
if (arguments.length === 1) {
|
||||
return this.load(messageSource, messageSource);
|
||||
}
|
||||
if (!`${messageSource}`.includes(java.io.File.separator)) {
|
||||
messageSource = files.join(this.getPath(), `${messageSource}.json`);
|
||||
}
|
||||
let path = files.path(messageSource);
|
||||
if (!files.isFile(path)) {
|
||||
throw Error(`Invalid path: ${path}`);
|
||||
}
|
||||
try {
|
||||
return this.load(JSON.parse(files.read(path)), locale);
|
||||
} catch (e) {
|
||||
scriptRuntime.console.warn(`${e.message}\n${e.stack}`);
|
||||
throw Error(`Failed to parse JSON file: ${path}`);
|
||||
}
|
||||
}
|
||||
throw TypeError(`Unknown message source: ${messageSource}`);
|
||||
},
|
||||
loadAll() {
|
||||
files
|
||||
.listDir(this.getPath(), file => files.getExtension(file).toLowerCase() === 'json')
|
||||
.forEach((file) => this.load(files.getNameWithoutExtension(file)));
|
||||
},
|
||||
};
|
||||
|
||||
return I18n;
|
||||
})(),
|
||||
config: { path: 'i18n' },
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.I18n}
|
||||
*/
|
||||
const i18n = new _.I18n();
|
||||
|
||||
return i18n;
|
||||
};
|
||||
1298
app/src/main/assets/modules/__images__.js
Normal file
1298
app/src/main/assets/modules/__images__.js
Normal file
File diff suppressed because it is too large
Load Diff
32
app/src/main/assets/modules/__media__.js
Normal file
32
app/src/main/assets/modules/__media__.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Media}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
let _ = {
|
||||
Media: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Media
|
||||
*/
|
||||
const Media = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Media.prototype = {
|
||||
constructor: Media,
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(Media.prototype, scriptRuntime.media);
|
||||
|
||||
return Media;
|
||||
})(),
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Media}
|
||||
*/
|
||||
const media = new _.Media();
|
||||
|
||||
return media;
|
||||
};
|
||||
109
app/src/main/assets/modules/__plugins__.js
Normal file
109
app/src/main/assets/modules/__plugins__.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Plugins}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
let _ = {
|
||||
Plugins: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Plugins
|
||||
*/
|
||||
const Plugins = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Plugins.prototype = {
|
||||
constructor: Plugins,
|
||||
/**
|
||||
* @type {Internal.Plugins.Extend}
|
||||
*/
|
||||
extend: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Plugins.Extend
|
||||
*/
|
||||
let Extend = function () {
|
||||
return Object.assign(function (modules) {
|
||||
Array.from(new Set(Array.from(arguments).flat(Infinity))).forEach((name) => {
|
||||
let moduleName = _.normalizeModuleName(name);
|
||||
if (moduleName in _.modules) {
|
||||
_.modules[moduleName].extendJsBuildInObjects();
|
||||
}
|
||||
});
|
||||
}, Extend.prototype);
|
||||
};
|
||||
|
||||
Extend.prototype = {
|
||||
constructor: Extend,
|
||||
exclude() {
|
||||
Array.from(arguments).flat(Infinity).forEach((name) => {
|
||||
let moduleName = _.normalizeModuleName(name);
|
||||
if (!_.excludes.includes(moduleName)) {
|
||||
_.excludes.push(moduleName);
|
||||
}
|
||||
});
|
||||
},
|
||||
registerModule(module) {
|
||||
Object.assign(_.modules, module);
|
||||
},
|
||||
};
|
||||
|
||||
return new Extend();
|
||||
})(),
|
||||
extendAll() {
|
||||
Object.entries(_.modules).forEach((entry) => {
|
||||
let [ name, action ] = entry;
|
||||
if (!_.excludes.includes(name)) {
|
||||
action.extendJsBuildInObjects();
|
||||
}
|
||||
});
|
||||
},
|
||||
extendAllBut() {
|
||||
this.extend.exclude.apply(this.extend, arguments);
|
||||
this.extendAll();
|
||||
},
|
||||
load(name) {
|
||||
if (typeof name !== 'string') {
|
||||
throw TypeError('The "name" argument for plugins.load() must be of type string');
|
||||
}
|
||||
if (name.includes('.') && !name.endsWith('.js')) /* As package name. */ {
|
||||
let plugin = scriptRuntime.plugins.load(name);
|
||||
let moduleExportedFunc = require(plugin.getMainScriptPath());
|
||||
return moduleExportedFunc(plugin.unwrap());
|
||||
}
|
||||
if (files.exists('./plugins')) /* As project-level plugins name. */ {
|
||||
return require(`./plugins${name}`);
|
||||
}
|
||||
throw Error('A directory named "plugins" must be found in the root directory of current project');
|
||||
},
|
||||
};
|
||||
|
||||
return Plugins;
|
||||
})(),
|
||||
/**
|
||||
* @type {Object.<string, Internal.Plugins.ExtendModules.Interface>}
|
||||
*/
|
||||
modules: {},
|
||||
/**
|
||||
* @type {string[]}
|
||||
*/
|
||||
excludes: [],
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns {string}
|
||||
*/
|
||||
normalizeModuleName(name) {
|
||||
if (!name.endsWith('x')) {
|
||||
name += 'x';
|
||||
}
|
||||
return name[0].toUpperCase() + name.slice(1);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Plugins}
|
||||
*/
|
||||
const plugins = new _.Plugins();
|
||||
|
||||
return plugins;
|
||||
};
|
||||
149
app/src/main/assets/modules/__recorder__.js
Normal file
149
app/src/main/assets/modules/__recorder__.js
Normal file
@@ -0,0 +1,149 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Recorder}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
let _ = {
|
||||
Recorder: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Recorder
|
||||
*/
|
||||
const Recorder = function () {
|
||||
/**
|
||||
* Record or get the record for a time gap
|
||||
* @param {string|function} [key]
|
||||
* @param {number|ThisType<any>} [timestamp]
|
||||
* @return {number|void} - timestamp
|
||||
*/
|
||||
const callable = function (key, timestamp) {
|
||||
return _.shortcut(key, timestamp);
|
||||
};
|
||||
return Object.assign(callable, Recorder.prototype);
|
||||
};
|
||||
|
||||
Recorder.prototype = {
|
||||
constructor: Recorder,
|
||||
/**
|
||||
* @param {string} [key]
|
||||
* @param {number} [ts=Date.now()]
|
||||
*/
|
||||
save: (key, ts) => _.save(key, ts),
|
||||
/**
|
||||
* @param {string} [key]
|
||||
* @param {number} [ts=Date.now()]
|
||||
* @return {number}
|
||||
*/
|
||||
load: (key, ts) => _.load(key, ts),
|
||||
isLessThan: (key, compare) => _.load(key) < compare,
|
||||
isGreaterThan: (key, compare) => _.load(key) > compare,
|
||||
has: (key) => _.has(key),
|
||||
remove: (key) => _.remove(key),
|
||||
clear: () => _.clear(),
|
||||
};
|
||||
|
||||
return Recorder;
|
||||
})(),
|
||||
/**
|
||||
* @type {Object.<string,number>}
|
||||
*/
|
||||
keys: {},
|
||||
/**
|
||||
* @type {number[]}
|
||||
*/
|
||||
anonymity: [],
|
||||
/**
|
||||
* @param {?number} [ts]
|
||||
* @return {number}
|
||||
*/
|
||||
ts(ts) {
|
||||
return typeof ts === 'number' ? ts : Date.now();
|
||||
},
|
||||
/**
|
||||
* @param {string} [key]
|
||||
* @return {boolean}
|
||||
*/
|
||||
has(key) {
|
||||
return key in this.keys;
|
||||
},
|
||||
clear() {
|
||||
this.keys = {};
|
||||
this.anonymity.splice(0);
|
||||
},
|
||||
/**
|
||||
* @param {string} [key]
|
||||
* @param {?number} [ts]
|
||||
* @return {number}
|
||||
*/
|
||||
add(key, ts) {
|
||||
key === undefined
|
||||
? this.anonymity.push(this.ts(ts))
|
||||
: this.keys[key] = this.ts(ts);
|
||||
return this.ts(ts);
|
||||
},
|
||||
/**
|
||||
* @param {string} [key]
|
||||
* @param {boolean} [isErrorSuppressed=false]
|
||||
* @return {number|void}
|
||||
*/
|
||||
get(key, isErrorSuppressed) {
|
||||
if (key === undefined) {
|
||||
return this.anonymity.pop();
|
||||
}
|
||||
if (!this.has(key) && !isErrorSuppressed) {
|
||||
throw Error(`key "${key}" does not exist`);
|
||||
}
|
||||
return this.keys[key];
|
||||
},
|
||||
/**
|
||||
* @param {string} [key]
|
||||
* @param {?number} [ts]
|
||||
* @return {number}
|
||||
*/
|
||||
save(key, ts) {
|
||||
return this.add(key, ts);
|
||||
},
|
||||
/**
|
||||
* @param {string} [key]
|
||||
* @param {?number} [ts]
|
||||
* @return {number}
|
||||
*/
|
||||
load(key, ts) {
|
||||
return this.ts(ts) - this.get(key);
|
||||
},
|
||||
/**
|
||||
* @param {string} key
|
||||
* @returns {boolean}
|
||||
*/
|
||||
remove(key) {
|
||||
return delete this.keys[key];
|
||||
},
|
||||
/**
|
||||
* @param {string|function} [key]
|
||||
* @param {?number|ThisType<any>} [ts]
|
||||
* @return {number}
|
||||
*/
|
||||
shortcut(key, ts) {
|
||||
if (typeof key === 'function') {
|
||||
let k = `${key.name || '(anonymous)'}@${Date.now()}`;
|
||||
this.save(k);
|
||||
key.call(typeof ts === 'object' ? ts : null);
|
||||
let res = this.load(k);
|
||||
this.remove(k);
|
||||
return res;
|
||||
}
|
||||
return typeof key !== 'undefined'
|
||||
? this.has(key) ? this.load(key, ts) : this.save(key, ts)
|
||||
: this.anonymity.length ? this.load() : this.save();
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Recorder}
|
||||
*/
|
||||
const recorder = new _.Recorder();
|
||||
|
||||
return recorder;
|
||||
};
|
||||
184
app/src/main/assets/modules/__selector__.js
Normal file
184
app/src/main/assets/modules/__selector__.js
Normal file
@@ -0,0 +1,184 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { i18n } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {() => Internal.Selector}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
let _ = {
|
||||
Selector: (() => {
|
||||
/**
|
||||
* @extends Internal.Selector
|
||||
*/
|
||||
const Selector = function () {
|
||||
/**
|
||||
* @global
|
||||
*/
|
||||
const selector = function () {
|
||||
return scriptRuntime.selector();
|
||||
};
|
||||
return Object.assign(selector, Selector.prototype);
|
||||
};
|
||||
|
||||
Selector.prototype = {
|
||||
constructor: Selector,
|
||||
};
|
||||
|
||||
return Selector;
|
||||
})(),
|
||||
javaObjectInstance: new java.lang.Object(),
|
||||
isInJavaObject: key => key in _.javaObjectInstance,
|
||||
isInScope: key => key in scope,
|
||||
scopeAugment() {
|
||||
Object.assign(scope, {
|
||||
pickup(root, selector, compass, resultType, callback) {
|
||||
switch (arguments.length) {
|
||||
case 5:
|
||||
// @Signature pickup<R>(root: UiObject, selector: Pickup.Selector, compass: Selector.Compass, resultType: Pickup.ResultType, callback: (o: any) => R): R;
|
||||
return UiSelector.pickup(root, selector, compass, resultType, callback);
|
||||
case 4:
|
||||
if (arguments[0] instanceof UiObject) {
|
||||
if (typeof arguments[3] === 'function') {
|
||||
if (UiObject.isCompass(arguments[2])) {
|
||||
// @Overload pickup<R>(root: UiObject, selector: Pickup.Selector, compass: Selector.Compass, callback: (o: any) => R): R;
|
||||
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], /* compass = */ arguments[2], UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[3]);
|
||||
}
|
||||
// @Overload pickup<R>(root: UiObject, selector: Pickup.Selector, resultType: Pickup.ResultType, callback: (o: any) => R): R;
|
||||
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[2], /* callback = */ arguments[3]);
|
||||
}
|
||||
// @Overload pickup(root: UiObject, selector: Pickup.Selector, compass: Selector.Compass, resultType: Pickup.ResultType): any;
|
||||
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], /* compass = */ arguments[2], /* resultType = */ arguments[3], /* callback = */ null);
|
||||
}
|
||||
// @Overload pickup<R>(selector: Pickup.Selector, compass: Selector.Compass, resultType: Pickup.ResultType, callback: (o: any) => R): R;
|
||||
return this.pickup(/* root = */ null, /* selector = */ arguments[0], /* compass = */ arguments[1], /* resultType = */ arguments[2], /* callback = */ arguments[3]);
|
||||
case 3:
|
||||
if (arguments[0] instanceof UiObject) {
|
||||
if (typeof arguments[2] === 'function') {
|
||||
// @Overload pickup<R>(root: UiObject, selector: Pickup.Selector, callback: (o: any) => R): R;
|
||||
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[2]);
|
||||
}
|
||||
if (UiObject.isCompass(arguments[2])) {
|
||||
// @Overload pickup(root: UiObject, selector: Pickup.Selector, compass: Selector.Compass): any;
|
||||
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], /* compass = */ arguments[2], UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
|
||||
}
|
||||
// @Overload pickup(root: UiObject, selector: Pickup.Selector, resultType: Pickup.ResultType): any;
|
||||
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[2], /* callback = */ null);
|
||||
}
|
||||
if (typeof arguments[2] === 'function') {
|
||||
if (UiObject.isCompass(arguments[1])) {
|
||||
// @Overload pickup<R>(selector: Pickup.Selector, compass: Selector.Compass, callback: (o: any) => R): R;
|
||||
return this.pickup(/* root = */ null, /* selector = */ arguments[0], /* compass = */ arguments[1], UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[2]);
|
||||
}
|
||||
// @Overload pickup<R>(selector: Pickup.Selector, resultType: Pickup.ResultType, callback: (o: any) => R): R;
|
||||
return this.pickup(/* root = */ null, /* selector = */ arguments[0], UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[1], /* callback = */ arguments[2]);
|
||||
}
|
||||
// @Overload pickup(selector: Pickup.Selector, compass: Selector.Compass, resultType: Pickup.ResultType): any;
|
||||
return this.pickup(/* root = */ null, /* selector = */ arguments[0], /* compass = */ arguments[1], /* resultType = */ arguments[2], /* callback = */ null);
|
||||
case 2:
|
||||
if (arguments[0] instanceof UiObject) {
|
||||
// @Overload pickup(root: UiObject, selector: Pickup.Selector): any;
|
||||
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
|
||||
}
|
||||
if (typeof arguments[1] === 'function') {
|
||||
// @Overload pickup<R>(selector: Pickup.Selector, callback: (o: any) => R): R;
|
||||
return this.pickup(/* root = */ null, /* selector = */ arguments[0], UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[1]);
|
||||
}
|
||||
if (UiObject.isCompass(arguments[1])) {
|
||||
// @Overload pickup(selector: Pickup.Selector, compass: Selector.Compass): any;
|
||||
return this.pickup(/* root = */ null, /* selector = */ arguments[0], /* compass = */ arguments[1], UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
|
||||
}
|
||||
// @Overload pickup(selector: Pickup.Selector, resultType: Pickup.ResultType): any;
|
||||
return this.pickup(/* root = */ null, /* selector = */ arguments[0], UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[1], /* callback = */ null);
|
||||
case 1:
|
||||
// @Overload pickup(selector: Pickup.Selector): any;
|
||||
return this.pickup(/* root = */ null, /* selector = */ arguments[0], UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
|
||||
case 0:
|
||||
// @Signature pickup(): UiObject;
|
||||
return findOnce();
|
||||
default:
|
||||
throw Error(i18n('error-invalid-arguments-with-name-and-args', 'pickup', Array.from(arguments).join()));
|
||||
}
|
||||
},
|
||||
detect(w, compass, resultType, callback) {
|
||||
switch (arguments.length) {
|
||||
case 4:
|
||||
// @Signature detect<R>(w: UiObject, compass: Detect.Compass, resultType: Detect.ResultType, callback: ((o: any) => R)): R;
|
||||
return UiObject.detect(w, compass, resultType, callback);
|
||||
case 3:
|
||||
if (typeof arguments[2] === 'function') {
|
||||
if (UiObject.isCompass(arguments[1])) {
|
||||
// @Overload detect<R>(w: UiObject, compass: Detect.Compass, callback: ((w: UiObject) => R)): R;
|
||||
return this.detect(w, /* compass = */ arguments[1], UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[2]);
|
||||
}
|
||||
// @Overload detect<R>(w: UiObject, resultType: Detect.ResultType, callback: ((o: any) => R)): R;
|
||||
return this.detect(w, UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[1], /* callback = */ arguments[2]);
|
||||
}
|
||||
// @Overload detect(w: UiObject, compass: Detect.Compass, resultType: Detect.ResultType): any;
|
||||
return this.detect(w, /* compass = */ arguments[1], /* resultType = */ arguments[2], /* callback = */ null);
|
||||
case 2:
|
||||
if (typeof arguments[1] === 'function') {
|
||||
// @Overload detect<T extends UiObject, R>(w: T, callback: ((w: T) => R)): R;
|
||||
return this.detect(w, UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[1]);
|
||||
}
|
||||
if (UiObject.isCompass(arguments[1])) {
|
||||
// @Overload detect(w: UiObject, compass: Detect.Compass): any;
|
||||
return this.detect(w, /* compass = */ arguments[1], UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
|
||||
}
|
||||
// @Overload detect(w: UiObject, resultType: Detect.ResultType): any;
|
||||
return this.detect(w, UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[1], /* callback = */ null);
|
||||
default:
|
||||
throw Error(i18n('error-invalid-arguments-with-name-and-args', 'detect', Array.from(arguments).join()));
|
||||
}
|
||||
},
|
||||
existsAll() {
|
||||
return Array.from(arguments).every(sel => this.pickup(sel, '?'));
|
||||
},
|
||||
existsOne() {
|
||||
return Array.from(arguments).some(sel => this.pickup(sel, '?'));
|
||||
},
|
||||
});
|
||||
|
||||
for (let method in scriptRuntime.selector()) {
|
||||
if (_.isInJavaObject(method) || _.isInScope(method)) {
|
||||
// @Caution by SuperMonster003 as of Oct 23, 2022.
|
||||
// ! The following methods have been assigned by 'automator' module,
|
||||
// ! which not belonging to UiSelector:
|
||||
// ! [ click / longClick / scrollDown / scrollUp / setText ].
|
||||
continue;
|
||||
}
|
||||
// @Caution by SuperMonster003 as of Apr 26, 2022.
|
||||
// ! Make param "method" scoped to this IIFE immediately.
|
||||
// ! Unwrapping this IIFE will cause TypeError.
|
||||
// ! Reappearance: `let f = idMatches; f(/.+/).findOnce();`
|
||||
// ! TypeError: Cannot find function findOnce in object true.
|
||||
// @ScopeBinding
|
||||
scope[method] = ( /* @IIFE */ (method) => {
|
||||
return function () {
|
||||
let s = selector();
|
||||
try {
|
||||
return s[method].apply(s, arguments);
|
||||
} catch (e) {
|
||||
scriptRuntime.console.warn(`${e.message}\n${e.stack}`);
|
||||
scriptRuntime.console.warn(`method: ${method}, arguments: ${Array.from(arguments).join()}`);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
})(method);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {() => Internal.Selector}
|
||||
*/
|
||||
const selector = new _.Selector();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return selector;
|
||||
};
|
||||
32
app/src/main/assets/modules/__sensors__.js
Normal file
32
app/src/main/assets/modules/__sensors__.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Sensors}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
let _ = {
|
||||
Sensors: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Sensors
|
||||
*/
|
||||
const Sensors = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Sensors.prototype = {
|
||||
constructor: Sensors,
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(Sensors.prototype, scriptRuntime.sensors);
|
||||
|
||||
return Sensors;
|
||||
})(),
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Sensors}
|
||||
*/
|
||||
const sensors = new _.Sensors();
|
||||
|
||||
return sensors;
|
||||
};
|
||||
84
app/src/main/assets/modules/__shell__.js
Normal file
84
app/src/main/assets/modules/__shell__.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Shell}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const rtRootShell = scriptRuntime.getRootShell();
|
||||
|
||||
let _ = {
|
||||
ShellCtor: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Shell
|
||||
*/
|
||||
const ShellCtor = function () {
|
||||
/**
|
||||
* @global
|
||||
*/
|
||||
const shell = function (cmd, root) {
|
||||
return scriptRuntime.shell(cmd, Number(Boolean(root)));
|
||||
};
|
||||
return Object.assign(shell, ShellCtor.prototype);
|
||||
};
|
||||
|
||||
ShellCtor.prototype = {
|
||||
constructor: ShellCtor,
|
||||
fromIntent(i) {
|
||||
return app.intentToShell(i);
|
||||
},
|
||||
};
|
||||
|
||||
return ShellCtor;
|
||||
})(),
|
||||
scopeAugment() {
|
||||
Object.assign(scope, {
|
||||
/** @global */
|
||||
Menu: () => KeyCode(KeyEvent.KEYCODE_MENU),
|
||||
/** @global */
|
||||
Home: () => KeyCode(KeyEvent.KEYCODE_HOME),
|
||||
/** @global */
|
||||
Back: () => KeyCode(KeyEvent.KEYCODE_BACK),
|
||||
/** @global */
|
||||
Up: () => KeyCode(KeyEvent.KEYCODE_DPAD_UP),
|
||||
/** @global */
|
||||
Down: () => KeyCode(KeyEvent.KEYCODE_DPAD_DOWN),
|
||||
/** @global */
|
||||
Left: () => KeyCode(KeyEvent.KEYCODE_DPAD_LEFT),
|
||||
/** @global */
|
||||
Right: () => KeyCode(KeyEvent.KEYCODE_DPAD_RIGHT),
|
||||
/** @global */
|
||||
OK: () => KeyCode(KeyEvent.KEYCODE_DPAD_CENTER),
|
||||
/** @global */
|
||||
VolumeUp: () => KeyCode(KeyEvent.KEYCODE_VOLUME_UP),
|
||||
/** @global */
|
||||
VolumeDown: () => KeyCode(KeyEvent.KEYCODE_VOLUME_DOWN),
|
||||
/** @global */
|
||||
Power: () => KeyCode(KeyEvent.KEYCODE_POWER),
|
||||
/** @global */
|
||||
Camera: () => KeyCode(KeyEvent.KEYCODE_CAMERA),
|
||||
/** @global */
|
||||
Text: text => rtRootShell.Text(text),
|
||||
/** @global */
|
||||
Input: text => rtRootShell.Text(text),
|
||||
/** @global */
|
||||
Tap: (x, y) => rtRootShell.Tap(x, y),
|
||||
/** @global */
|
||||
Screencap: path => rtRootShell.Screencap(path),
|
||||
/** @global */
|
||||
KeyCode: keyCode => rtRootShell.KeyCode(keyCode),
|
||||
/** @global */
|
||||
SetScreenMetrics: (w, h) => rtRootShell.SetScreenMetrics(w, h),
|
||||
/** @global */
|
||||
Swipe: (x1, y1, x2, y2, duration) => duration === undefined
|
||||
? rtRootShell.Swipe(x1, y1, x2, y2)
|
||||
: rtRootShell.Swipe(x1, y1, x2, y2, duration),
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const shell = new _.ShellCtor();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return shell;
|
||||
};
|
||||
71
app/src/main/assets/modules/__storages__.js
Normal file
71
app/src/main/assets/modules/__storages__.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Storages}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const LocalStorage = org.autojs.autojs.core.storage.LocalStorage;
|
||||
|
||||
let _ = {
|
||||
ProxyStorage: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.LocalStorage
|
||||
*/
|
||||
const ProxyStorage = function (name) {
|
||||
this._storage = new LocalStorage(scope.context, name);
|
||||
};
|
||||
|
||||
ProxyStorage.prototype = {
|
||||
constructor: ProxyStorage,
|
||||
put(key, value) {
|
||||
if (value === undefined) {
|
||||
throw TypeError('Value cannot be undefined');
|
||||
}
|
||||
this._storage.put(key, JSON.stringify(value));
|
||||
},
|
||||
get(key, def) {
|
||||
let value = this._storage.getString(key, null);
|
||||
return value ? JSON.parse(value) : def;
|
||||
},
|
||||
remove(key) {
|
||||
this._storage.remove(key);
|
||||
},
|
||||
contains(key) {
|
||||
return this._storage.contains(key);
|
||||
},
|
||||
clear() {
|
||||
this._storage.clear();
|
||||
},
|
||||
};
|
||||
|
||||
return ProxyStorage;
|
||||
})(),
|
||||
Storages: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Storages
|
||||
*/
|
||||
const Storage = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Storage.prototype = {
|
||||
constructor: Storage,
|
||||
create(name) {
|
||||
return new _.ProxyStorage(name);
|
||||
},
|
||||
remove(name) {
|
||||
this.create(name).clear();
|
||||
},
|
||||
};
|
||||
|
||||
return Storage;
|
||||
})(),
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Storages}
|
||||
*/
|
||||
const storages = new _.Storages();
|
||||
|
||||
return storages;
|
||||
};
|
||||
354
app/src/main/assets/modules/__tasks__.js
Normal file
354
app/src/main/assets/modules/__tasks__.js
Normal file
@@ -0,0 +1,354 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { ui, threads, files } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Tasks}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const TimedTask = org.autojs.autojs.timing.TimedTask;
|
||||
const IntentTask = org.autojs.autojs.timing.IntentTask;
|
||||
const TimedTaskManager = org.autojs.autojs.timing.TimedTaskManager;
|
||||
const ExecutionConfig = org.autojs.autojs.execution.ExecutionConfig;
|
||||
const DynamicBroadcastReceivers = org.autojs.autojs.external.receiver.DynamicBroadcastReceivers;
|
||||
|
||||
let _ = {
|
||||
Tasks: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Tasks
|
||||
*/
|
||||
let Task = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Task.prototype = {
|
||||
constructor: Task,
|
||||
timedTaskManager: TimedTaskManager.getInstance(),
|
||||
/**
|
||||
* @template {TimedTask$|IntentTask$|null} T
|
||||
* @param {T} task
|
||||
* @return {T}
|
||||
*/
|
||||
addTask(task) {
|
||||
if (task) {
|
||||
this.timedTaskManager.addTask(task);
|
||||
}
|
||||
return task || null;
|
||||
},
|
||||
/**
|
||||
* @param {Timers.TimedTask.Daily} [options]
|
||||
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
|
||||
*/
|
||||
addDailyTask(options) {
|
||||
let opt = options || {};
|
||||
|
||||
let localTime = _.parseDateTime('LocalTime', opt.time || Date.now());
|
||||
let path = _.parsePath(opt.path);
|
||||
let config = _.parseConfig(opt);
|
||||
|
||||
let timedTask = this.addTask(TimedTask.dailyTask(localTime, path, config));
|
||||
|
||||
return _.taskFulfilled(timedTask, opt);
|
||||
},
|
||||
/**
|
||||
* @param {Timers.TimedTask.Weekly} [options]
|
||||
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
|
||||
*/
|
||||
addWeeklyTask(options) {
|
||||
let timeFlag = 0;
|
||||
let opt = options || {};
|
||||
|
||||
let daysOfWeek = opt.daysOfWeek || [ _.getCurrentDayOfWeek() ];
|
||||
let daysOfWeekList = _.getDaysOfWeekFlatList();
|
||||
|
||||
for (let i = 0; i < daysOfWeek.length; i += 1) {
|
||||
let dayString = daysOfWeek[i].toString();
|
||||
let dayIndex = daysOfWeekList.indexOf(dayString.toLowerCase()) % 7;
|
||||
if (dayIndex < 0) {
|
||||
throw Error(`Unknown day: ${dayString}`);
|
||||
}
|
||||
timeFlag |= TimedTask.getDayOfWeekTimeFlag(dayIndex + 1);
|
||||
}
|
||||
|
||||
let localTime = _.parseDateTime('LocalTime', opt.time || Date.now());
|
||||
let flagsNum = Number(new java.lang.Long(timeFlag));
|
||||
let path = _.parsePath(opt.path);
|
||||
let config = _.parseConfig(opt);
|
||||
|
||||
let timedTask = this.addTask(TimedTask.weeklyTask(localTime, flagsNum, path, config));
|
||||
|
||||
return _.taskFulfilled(timedTask, opt);
|
||||
},
|
||||
/**
|
||||
* @param {Timers.TimedTask.Disposable} options
|
||||
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
|
||||
*/
|
||||
addDisposableTask(options) {
|
||||
let opt = options || {};
|
||||
|
||||
let localDateTime = _.parseDateTime('LocalDateTime', opt.date || Date.now());
|
||||
let path = _.parsePath(opt.path);
|
||||
let config = _.parseConfig(opt);
|
||||
|
||||
let timedTask = this.addTask(TimedTask.disposableTask(localDateTime, path, config));
|
||||
|
||||
return _.taskFulfilled(timedTask, opt);
|
||||
},
|
||||
/**
|
||||
* @param {Timers.IntentTask.Basic} [options]
|
||||
* @return {IntentTask$|org.autojs.autojs.core.looper.TimerThread|null}
|
||||
*/
|
||||
addIntentTask(options) {
|
||||
let opt = options || {};
|
||||
|
||||
let intentTask = (function $iiFe() {
|
||||
let intentTask = new IntentTask();
|
||||
intentTask.setScriptPath(_.parsePath(opt.path));
|
||||
if (typeof opt.action === 'string') {
|
||||
intentTask.setAction(opt.action);
|
||||
if (opt.action === DynamicBroadcastReceivers.ACTION_STARTUP) {
|
||||
// @Indecision opt.local
|
||||
intentTask.setLocal(true);
|
||||
}
|
||||
}
|
||||
if (typeof opt.dataType === 'string') {
|
||||
intentTask.setDataType(opt.dataType);
|
||||
}
|
||||
if (typeof opt.local === 'boolean') {
|
||||
// @FinalDecision opt.action
|
||||
intentTask.setLocal(opt.local);
|
||||
}
|
||||
return intentTask;
|
||||
})();
|
||||
|
||||
let timedTask = this.addTask(intentTask);
|
||||
|
||||
return _.taskFulfilled(timedTask, opt);
|
||||
},
|
||||
/**
|
||||
* @param {number} id
|
||||
* @return {TimedTask$}
|
||||
*/
|
||||
getTimedTask(id) {
|
||||
return this.timedTaskManager.getTimedTask(id);
|
||||
},
|
||||
/**
|
||||
* @param {number} id
|
||||
* @return {IntentTask$}
|
||||
*/
|
||||
getIntentTask(id) {
|
||||
return this.timedTaskManager.getIntentTask(id);
|
||||
},
|
||||
/**
|
||||
* @param {TimedTask$|IntentTask$|null} task
|
||||
* @return {TimedTask$|IntentTask$}
|
||||
*/
|
||||
removeTask(task) {
|
||||
if (task) {
|
||||
this.timedTaskManager.removeTask(task);
|
||||
}
|
||||
return task;
|
||||
},
|
||||
/**
|
||||
* @param {number} id
|
||||
* @param {Timers.TimedTask.Extension} [options]
|
||||
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
|
||||
*/
|
||||
removeTimedTask(id, options) {
|
||||
let opt = options || {};
|
||||
let task = this.removeTask(this.getTimedTask(id));
|
||||
return _.taskFulfilled(task, Object.assign(opt, {
|
||||
condition: () => !this.getTimedTask(id),
|
||||
}));
|
||||
},
|
||||
/**
|
||||
* @param {number} id
|
||||
* @param {Timers.TimedTask.Extension} [options]
|
||||
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
|
||||
*/
|
||||
removeIntentTask(id, options) {
|
||||
let opt = options || {};
|
||||
let task = this.removeTask(this.getIntentTask(id));
|
||||
return _.taskFulfilled(task, Object.assign(opt, {
|
||||
condition: () => !this.getIntentTask(id),
|
||||
}));
|
||||
},
|
||||
/**
|
||||
* @param {TimedTask$|null} task
|
||||
* @return {TimedTask$|null}
|
||||
*/
|
||||
updateTask(task) {
|
||||
if (!task) {
|
||||
return null;
|
||||
}
|
||||
task.setScheduled(false);
|
||||
this.timedTaskManager.updateTask(task);
|
||||
return task;
|
||||
},
|
||||
/**
|
||||
* @param {{path?:string}} [options]
|
||||
* @return {TimedTask$[]}
|
||||
*/
|
||||
queryTimedTasks(options) {
|
||||
let opt = options || {};
|
||||
let path = opt.path;
|
||||
let list = this.timedTaskManager.getAllTasksAsList().toArray();
|
||||
return path ? list.filter(task => task.getScriptPath() === path) : list;
|
||||
},
|
||||
/**
|
||||
* @param {{path?:string,action?:string}} [options]
|
||||
* @return {IntentTask$[]}
|
||||
*/
|
||||
queryIntentTasks(options) {
|
||||
let opt = options || {};
|
||||
let { path, action } = opt;
|
||||
|
||||
let list = this.timedTaskManager.getAllIntentTasksAsList().toArray();
|
||||
|
||||
if (!path && !action) {
|
||||
return list;
|
||||
}
|
||||
|
||||
let pathTrigger = task => !path || task.getScriptPath() === path;
|
||||
let actionTrigger = task => !action || task.getAction() === action;
|
||||
|
||||
return list.filter(task => pathTrigger(task) && actionTrigger(task));
|
||||
},
|
||||
/**
|
||||
* @param flag {number} -- number from 0 to 127
|
||||
* @return {number[]}
|
||||
*/
|
||||
timeFlagToDays(flag) {
|
||||
let days = [];
|
||||
let binaryString = Number(flag).toString(2);
|
||||
let currentDayNumber = binaryString.length - 1;
|
||||
for (let i of binaryString) {
|
||||
if (i !== '0') {
|
||||
days.unshift(currentDayNumber);
|
||||
}
|
||||
currentDayNumber -= 1;
|
||||
}
|
||||
return days;
|
||||
},
|
||||
/**
|
||||
* @param days {number[]}
|
||||
* @return {number}
|
||||
*/
|
||||
daysToTimeFlag(days) {
|
||||
return Array(7).fill(0).reduce((a, b, i) => {
|
||||
return a + (days.includes(i) ? Math.pow(2, i) : 0);
|
||||
}, 0);
|
||||
},
|
||||
};
|
||||
|
||||
return Task;
|
||||
})(),
|
||||
parsePath(path) {
|
||||
if (!path) {
|
||||
throw 'A path is necessary for a task';
|
||||
}
|
||||
if (!files.exists(path)) {
|
||||
scriptRuntime.console.warn(`Specified path "${path}" doesn't exist`);
|
||||
}
|
||||
return files.path(path);
|
||||
},
|
||||
/**
|
||||
* @param {any} num
|
||||
* @param {number|function():number} [def=0]
|
||||
* @returns {number}
|
||||
*/
|
||||
parseNumber(num, def) {
|
||||
return typeof num === 'number' ? num : typeof def === 'function' ? def() : def || 0;
|
||||
},
|
||||
/**
|
||||
* @param {Object} config
|
||||
* @param {number} [config.delay=0]
|
||||
* @param {number} [config.interval=0]
|
||||
* @param {number} [config.loopTimes=1]
|
||||
* @return {org.autojs.autojs.execution.ExecutionConfig}
|
||||
*/
|
||||
parseConfig(config) {
|
||||
let execConfig = new ExecutionConfig();
|
||||
execConfig.setDelay(_.parseNumber(config.delay, 0));
|
||||
execConfig.setInterval(_.parseNumber(config.interval, 0));
|
||||
execConfig.setLoopTimes(_.parseNumber(config.loopTimes, 1));
|
||||
return execConfig;
|
||||
},
|
||||
/**
|
||||
* @param {'LocalTime'|'LocalDateTime'} clazz
|
||||
* @param {string|Date|number} dateTime
|
||||
* @return {org.joda.time.LocalTime|org.joda.time.LocalDateTime}
|
||||
*/
|
||||
parseDateTime(clazz, dateTime) {
|
||||
let clz = ( /* @IIFE */ () => {
|
||||
switch (clazz) {
|
||||
case 'LocalTime':
|
||||
return org.joda.time.LocalTime;
|
||||
case 'LocalDateTime':
|
||||
return org.joda.time.LocalDateTime;
|
||||
default:
|
||||
throw Error('Unknown clazz for parseDateTime');
|
||||
}
|
||||
})();
|
||||
if (typeof dateTime === 'string') {
|
||||
return clz.parse(dateTime);
|
||||
}
|
||||
if (dateTime instanceof Date) {
|
||||
return new clz(dateTime.getTime());
|
||||
}
|
||||
if (typeof dateTime === 'number') {
|
||||
return new clz(dateTime);
|
||||
}
|
||||
throw Error('Unknown dateTime for parseDateTime');
|
||||
},
|
||||
/**
|
||||
* @param {TimedTask$|IntentTask$} task
|
||||
* @param {Timers.TimedTask.Extension|{}} [options]
|
||||
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
|
||||
*/
|
||||
taskFulfilled(task, options) {
|
||||
let opt = options || {};
|
||||
|
||||
let run = () => {
|
||||
if (task) {
|
||||
let timeout = 2e3;
|
||||
let interval = 50;
|
||||
let condition = opt.condition || (() => task['id'] > 0);
|
||||
while (timeout > 0) {
|
||||
if (condition()) {
|
||||
break;
|
||||
}
|
||||
sleep(interval);
|
||||
timeout -= interval;
|
||||
}
|
||||
}
|
||||
return opt.callback ? opt.callback(task) : task || null;
|
||||
};
|
||||
|
||||
return opt.isAsync || ui.isUiThread() ? threads.start(run) : run();
|
||||
},
|
||||
getCurrentDayOfWeek() {
|
||||
return new Date().getDay();
|
||||
},
|
||||
getDaysOfWeekFlatList() {
|
||||
return [
|
||||
'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
|
||||
'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun',
|
||||
'一', '二', '三', '四', '五', '六', '日',
|
||||
1, 2, 3, 4, 5, 6, 0,
|
||||
1, 2, 3, 4, 5, 6, 7,
|
||||
].map(x => typeof x === 'string' ? x : x.toString());
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Tasks}
|
||||
*/
|
||||
const tasks = new _.Tasks();
|
||||
|
||||
return tasks;
|
||||
};
|
||||
107
app/src/main/assets/modules/__threads__.js
Normal file
107
app/src/main/assets/modules/__threads__.js
Normal file
@@ -0,0 +1,107 @@
|
||||
// noinspection NpmUsedModulesInstalled
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Threads}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const Throwable = java.lang.Throwable;
|
||||
const Synchronizer = org.mozilla.javascript.Synchronizer;
|
||||
const TimerThread = org.autojs.autojs.core.looper.TimerThread;
|
||||
|
||||
const rtThreads = runtime.threads;
|
||||
|
||||
let _ = {
|
||||
Threads: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Threads
|
||||
*/
|
||||
const Threads = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Threads.prototype = {
|
||||
constructor: Threads,
|
||||
atomic(value) {
|
||||
return rtThreads.atomic.apply(rtThreads, arguments);
|
||||
},
|
||||
currentThread() {
|
||||
return rtThreads.currentThread.apply(rtThreads, arguments);
|
||||
},
|
||||
disposable() {
|
||||
return rtThreads.disposable.apply(rtThreads, arguments);
|
||||
},
|
||||
lock() {
|
||||
return rtThreads.lock.apply(rtThreads, arguments);
|
||||
},
|
||||
interrupt(thread) {
|
||||
if (thread instanceof TimerThread) {
|
||||
thread.isAlive() && thread.interrupt();
|
||||
}
|
||||
},
|
||||
start(runnable) {
|
||||
try {
|
||||
// noinspection JSCheckFunctionSignatures
|
||||
return rtThreads.start(runnable);
|
||||
} catch (e) {
|
||||
if (!ScriptInterruptedException.causedByInterrupted(new Throwable(e))) {
|
||||
if (!e.message.endsWith(context.getString(R.strings.error_script_is_on_exiting))) {
|
||||
throw Error(`${e}\n${e.stack}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(Threads.prototype, scriptRuntime.threads);
|
||||
|
||||
return Threads;
|
||||
})(),
|
||||
scopeAugment() {
|
||||
Object.assign(scope, {
|
||||
/**
|
||||
* @global
|
||||
*/
|
||||
sync(func, lock) {
|
||||
return new Synchronizer(func, lock || null);
|
||||
},
|
||||
});
|
||||
},
|
||||
promiseAugment() {
|
||||
/**
|
||||
* @implements Internal.Threads.PromiseExtension
|
||||
*/
|
||||
const PromiseExtension = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Object.assign(PromiseExtension.prototype, {
|
||||
wait() {
|
||||
let disposable = scriptRuntime.threads.disposable();
|
||||
this
|
||||
.then(result => disposable.setAndNotify({ result: result }))
|
||||
.catch(error => disposable.setAndNotify({ error: error }));
|
||||
|
||||
let resultObj = disposable.blockedGet();
|
||||
if (resultObj.error) {
|
||||
throw resultObj.error;
|
||||
}
|
||||
return resultObj.result;
|
||||
},
|
||||
});
|
||||
|
||||
Object.assign(Promise.prototype, PromiseExtension.prototype);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Threads}
|
||||
*/
|
||||
const threads = new _.Threads();
|
||||
|
||||
_.scopeAugment();
|
||||
_.promiseAugment();
|
||||
|
||||
return threads;
|
||||
};
|
||||
86
app/src/main/assets/modules/__timers__.js
Normal file
86
app/src/main/assets/modules/__timers__.js
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Timers}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
|
||||
let _ = {
|
||||
Timers: (() => {
|
||||
/**
|
||||
* @implements Internal.Timers
|
||||
*/
|
||||
const Timers = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Timers.prototype = {
|
||||
constructor: Timers,
|
||||
setIntervalExt(listener, interval, timeout, callback) {
|
||||
let $ = {
|
||||
initTimestamp: Date.now(),
|
||||
interval: interval > 0 ? interval : 200,
|
||||
timeout: timeout > 0 ? timeout : Infinity,
|
||||
setIntervalExt() {
|
||||
return setTimeout(this.run.bind(this), this.interval);
|
||||
},
|
||||
run() {
|
||||
listener();
|
||||
this.relayIFN();
|
||||
},
|
||||
relayIFN() {
|
||||
if (!this.isTimedOut()) {
|
||||
this.setIntervalExt();
|
||||
} else if (typeof callback === 'function') {
|
||||
callback.call(this, this.timeoutResult);
|
||||
}
|
||||
},
|
||||
isTimedOut() {
|
||||
if (typeof this.isTimedOutCache !== 'function') {
|
||||
this.isTimedOutCache = typeof timeout === 'function'
|
||||
? timeout.bind(this)
|
||||
: () => Date.now() - this.initTimestamp > this.timeout;
|
||||
}
|
||||
this.timeoutResult = this.isTimedOutCache();
|
||||
return this.timeoutResult !== false && !isNullish(this.timeoutResult);
|
||||
},
|
||||
};
|
||||
return $.setIntervalExt();
|
||||
},
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(Timers.prototype, scriptRuntime.timers);
|
||||
|
||||
return Timers;
|
||||
})(),
|
||||
scopeAugment() {
|
||||
/**
|
||||
* @type {(keyof Internal.Timers)[]}
|
||||
*/
|
||||
let methods = [
|
||||
'setTimeout', 'clearTimeout',
|
||||
'setInterval', 'clearInterval',
|
||||
'setImmediate', 'clearImmediate',
|
||||
];
|
||||
__asGlobal__(scriptRuntime.timers, methods);
|
||||
|
||||
Object.assign(scope, {
|
||||
/**
|
||||
* @global
|
||||
*/
|
||||
loop() {
|
||||
return scriptRuntime.console.warn('Method loop() is deprecated and has no effect.');
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Timers}
|
||||
*/
|
||||
const timers = new _.Timers();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return timers;
|
||||
};
|
||||
416
app/src/main/assets/modules/__ui__.js
Normal file
416
app/src/main/assets/modules/__ui__.js
Normal file
@@ -0,0 +1,416 @@
|
||||
// noinspection NpmUsedModulesInstalled,JSUnusedGlobalSymbols,JSUnusedLocalSymbols
|
||||
|
||||
/* Overwritten protection. */
|
||||
|
||||
let { files } = global;
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.UI}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const Looper = android.os.Looper;
|
||||
const Runnable = java.lang.Runnable;
|
||||
const Color = android.graphics.Color;
|
||||
const ContextThemeWrapper = android.view.ContextThemeWrapper;
|
||||
const ViewExtras = org.autojs.autojs.core.ui.ViewExtras;
|
||||
const JsListView = org.autojs.autojs.core.ui.widget.JsListView;
|
||||
const JsGridView = org.autojs.autojs.core.ui.widget.JsGridView;
|
||||
const JsViewHelper = org.autojs.autojs.core.ui.JsViewHelper;
|
||||
const DynamicLayoutInflater = org.autojs.autojs.core.ui.inflater.DynamicLayoutInflater;
|
||||
|
||||
require('object-observe-lite.min').call(scope);
|
||||
require('array-observe.min').call(scope);
|
||||
|
||||
// noinspection JSValidateTypes
|
||||
let _ = {
|
||||
// @Coerce by SuperMonster003 on Nov 9, 2022.
|
||||
/** @type {Internal.UI} */
|
||||
rtUi: ( /* @IIFE */ () => {
|
||||
let inRtUi = scriptRuntime.ui;
|
||||
inRtUi.bindingContext = scope;
|
||||
inRtUi.__proxy__ = {
|
||||
set(name, value) {
|
||||
uiProxy[name] = value;
|
||||
},
|
||||
get(name) {
|
||||
if (!uiProxy[name] && uiProxy.view) {
|
||||
let view = uiProxy.findById(name);
|
||||
if (view) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
return uiProxy[name];
|
||||
},
|
||||
};
|
||||
return inRtUi;
|
||||
})(),
|
||||
UI: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.UI
|
||||
*/
|
||||
const UI = function () {
|
||||
// Empty class body.
|
||||
};
|
||||
|
||||
UI.prototype = {
|
||||
constructor: UI,
|
||||
__widgets__: {},
|
||||
Widget: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.UI.Widget
|
||||
*/
|
||||
let Widget = function () {
|
||||
this.__attrs__ = {};
|
||||
return Object.assign(function () {
|
||||
// Empty interface body.
|
||||
}, Widget.prototype);
|
||||
};
|
||||
|
||||
Widget.prototype = {
|
||||
constructor: Widget,
|
||||
renderInternal() {
|
||||
if (typeof this.render === 'function') {
|
||||
return this.render.call(this);
|
||||
}
|
||||
return '< />';
|
||||
},
|
||||
defineAttr(attrName, getter, setter) {
|
||||
//// -=-= PENDING =-=- ////
|
||||
let attrAlias = attrName;
|
||||
let applier;
|
||||
if (typeof arguments[1] === 'string') {
|
||||
attrAlias = arguments[1];
|
||||
if (arguments.length >= 3) {
|
||||
applier = arguments[2];
|
||||
}
|
||||
} else if (typeof arguments[1] === 'function' && typeof arguments[2] !== 'function') {
|
||||
applier = arguments[1];
|
||||
}
|
||||
if (!(typeof arguments[1] === 'function' && typeof arguments[2] === 'function')) {
|
||||
getter = () => {
|
||||
return this[attrAlias];
|
||||
};
|
||||
setter = (view, attrName, value, setter) => {
|
||||
this[attrAlias] = value;
|
||||
if (typeof applier === 'function') {
|
||||
applier(view, attrName, value, setter);
|
||||
}
|
||||
};
|
||||
}
|
||||
this.__attrs__[attrName] = {
|
||||
getter: getter,
|
||||
setter: setter,
|
||||
};
|
||||
},
|
||||
hasAttr(attrName) {
|
||||
return this.__attrs__.hasOwnProperty(attrName);
|
||||
},
|
||||
setAttr(view, attrName, value, setter) {
|
||||
this.__attrs__[attrName].setter(view, attrName, value, setter);
|
||||
},
|
||||
getAttr(view, attrName, getter) {
|
||||
return this.__attrs__[attrName].getter(view, attrName, getter);
|
||||
},
|
||||
notifyViewCreated(view) {
|
||||
if (typeof this.onViewCreated === 'function') {
|
||||
this.onViewCreated.call(this, view);
|
||||
}
|
||||
},
|
||||
notifyAfterInflation(view) {
|
||||
if (typeof this.onFinishInflation === 'function') {
|
||||
this.onFinishInflation.call(this, view);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return Widget;
|
||||
})(),
|
||||
get R() {
|
||||
return scope.R;
|
||||
},
|
||||
get emitter() {
|
||||
return typeof activity !== 'undefined' ? activity.getEventEmitter() : null;
|
||||
},
|
||||
__inflate__(ctx, xml, parent, isAttachedToParent) {
|
||||
return layoutInflater.inflate(ctx, _.toXMLString(xml), parent || null, Boolean(isAttachedToParent));
|
||||
},
|
||||
inflate(xml, parent, isAttachedToParent) {
|
||||
layoutInflater.setContext(typeof activity === 'undefined'
|
||||
? new ContextThemeWrapper(context, R.style.ScriptTheme)
|
||||
: activity);
|
||||
return layoutInflater.inflate(_.toXMLString(xml), parent || null, Boolean(isAttachedToParent));
|
||||
},
|
||||
run(action) {
|
||||
if (this.isUiThread()) {
|
||||
return action();
|
||||
}
|
||||
let error, result;
|
||||
|
||||
let disposable = scope.threads.disposable();
|
||||
scriptRuntime.getUiHandler().post(() => {
|
||||
try {
|
||||
result = action();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
} finally {
|
||||
disposable.setAndNotify(true);
|
||||
}
|
||||
});
|
||||
disposable.blockedGet();
|
||||
|
||||
if (error instanceof Error) {
|
||||
scriptRuntime.console.warn(`${species(error)} occurred in \`ui.run()\`.`);
|
||||
scriptRuntime.console.warn(error.message);
|
||||
scriptRuntime.console.warn(error.stack);
|
||||
throw error;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
post(action, delay) {
|
||||
if (delay === undefined) {
|
||||
scriptRuntime.getUiHandler().post(_.wrapUiAction(action));
|
||||
} else {
|
||||
scriptRuntime.getUiHandler().postDelayed(_.wrapUiAction(action), delay);
|
||||
}
|
||||
},
|
||||
layout(layout) {
|
||||
_.ensureActivity();
|
||||
layoutInflater.setContext(activity);
|
||||
// noinspection JSCheckFunctionSignatures
|
||||
this.setContentView(layoutInflater.inflate(layout, activity.window.decorView, false));
|
||||
},
|
||||
layoutFile(path) {
|
||||
this.layout(files.read(path));
|
||||
},
|
||||
isUiThread() {
|
||||
return Looper.myLooper() === Looper.getMainLooper();
|
||||
},
|
||||
registerWidget(name, widget) {
|
||||
if (typeof widget !== 'function') {
|
||||
throw TypeError('Param "widget" should be a class-like function');
|
||||
}
|
||||
this.__widgets__[name] = widget;
|
||||
},
|
||||
setContentView(view) {
|
||||
_.ensureActivity();
|
||||
this.view = view;
|
||||
this.run(() => activity.setContentView(view));
|
||||
},
|
||||
statusBarColor(color) {
|
||||
_.ensureActivity();
|
||||
let colorInt = ( /* @IIFE */ () => {
|
||||
if (typeof color === 'string') {
|
||||
if (Number(color).toString() === color) {
|
||||
color = Number(color);
|
||||
}
|
||||
}
|
||||
if (typeof color === 'number') {
|
||||
return color;
|
||||
}
|
||||
return scriptRuntime.colors.parseColor(String(color));
|
||||
})();
|
||||
this.run(() => activity.window.setStatusBarColor(colorInt));
|
||||
},
|
||||
findById(id) {
|
||||
return this.view ? this.findByStringId(this.view, id) : null;
|
||||
},
|
||||
findByStringId(view, id) {
|
||||
return JsViewHelper.findViewByStringId(view, id);
|
||||
},
|
||||
findView(id) {
|
||||
return this.findById(id);
|
||||
},
|
||||
finish() {
|
||||
_.ensureActivity();
|
||||
this.run(() => activity.finish());
|
||||
},
|
||||
};
|
||||
|
||||
return UI;
|
||||
})(),
|
||||
/**
|
||||
* @type {org.autojs.autojs.core.ui.inflater.LayoutInflaterDelegate}
|
||||
*/
|
||||
layoutInflaterDelegate: {
|
||||
beforeConvertXml(context, xml) {
|
||||
return null;
|
||||
},
|
||||
afterConvertXml(context, xml) {
|
||||
return xml;
|
||||
},
|
||||
beforeInflation(context, xml, parent) {
|
||||
return null;
|
||||
},
|
||||
afterInflation(context, result, xml, parent) {
|
||||
return result;
|
||||
},
|
||||
beforeInflateView(context, node, parent, attachToParent) {
|
||||
return null;
|
||||
},
|
||||
afterInflateView(context, view, node, parent, attachToParent) {
|
||||
let { widget } = view;
|
||||
if (widget && context.get('root') !== widget) {
|
||||
widget.notifyAfterInflation(view);
|
||||
}
|
||||
return view;
|
||||
},
|
||||
beforeCreateView(context, node, viewName, parent, attrs) {
|
||||
if (uiProxy.__widgets__.hasOwnProperty(viewName)) {
|
||||
let Widget = uiProxy.__widgets__[viewName];
|
||||
let widget = new Widget();
|
||||
let ctx = layoutInflater.newInflateContext();
|
||||
ctx.put('root', widget);
|
||||
ctx.put('widget', widget);
|
||||
return uiProxy.__inflate__(ctx, widget.renderInternal(), parent, false);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
afterCreateView(context, view, node, viewName, parent, attrs) {
|
||||
if (view instanceof JsListView || view instanceof JsGridView) {
|
||||
_.initListView(view);
|
||||
}
|
||||
let widget = context.get('widget');
|
||||
if (widget !== null) {
|
||||
widget.view = view;
|
||||
view.widget = widget;
|
||||
ViewExtras.getViewAttributes(view, layoutInflater.getResourceParser()).setViewAttributeDelegate({
|
||||
has: name => widget.hasAttr(name),
|
||||
get: (view, name, getter) => widget.getAttr(view, name, getter),
|
||||
set: (view, name, value, setter) => widget.setAttr(view, name, value, setter),
|
||||
});
|
||||
widget.notifyViewCreated(view);
|
||||
}
|
||||
return view;
|
||||
},
|
||||
beforeApplyAttributes(context, view, inflater, attrs, parent) {
|
||||
return false;
|
||||
},
|
||||
afterApplyAttributes(context, view, inflater, attrs, parent) {
|
||||
context.remove('widget');
|
||||
},
|
||||
beforeInflateChildren(context, inflater, node, parent) {
|
||||
return false;
|
||||
},
|
||||
afterInflateChildren(context, inflater, node, parent) {
|
||||
// Empty method body
|
||||
},
|
||||
beforeApplyPendingAttributesOfChildren(context, inflater, view) {
|
||||
return false;
|
||||
},
|
||||
afterApplyPendingAttributesOfChildren(context, inflater, view) {
|
||||
// Empty method body
|
||||
},
|
||||
beforeApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs) {
|
||||
let isDynamic = layoutInflater.isDynamicValue(value);
|
||||
return isDynamic && layoutInflater.getInflateFlags() === DynamicLayoutInflater.FLAG_IGNORES_DYNAMIC_ATTRS
|
||||
|| !isDynamic && layoutInflater.getInflateFlags() === DynamicLayoutInflater.FLAG_JUST_DYNAMIC_ATTRS
|
||||
|| ( /* @IIFE */ () => {
|
||||
value = _.bind(value);
|
||||
let widget = context.get('widget');
|
||||
if (widget !== null && widget.hasAttr(attrName)) {
|
||||
widget.setAttr(view, attrName, value, (view, attrName, value) => {
|
||||
inflater.setAttr(view, ns, attrName, value, parent, attrs);
|
||||
});
|
||||
} else {
|
||||
inflater.setAttr(view, ns, attrName, value, parent, attrs);
|
||||
}
|
||||
this.afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs);
|
||||
return true;
|
||||
})();
|
||||
},
|
||||
afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs) {
|
||||
// Empty method body
|
||||
},
|
||||
},
|
||||
bind(value) {
|
||||
let ctx = this.rtUi.bindingContext;
|
||||
if (ctx !== null) {
|
||||
let i = -1;
|
||||
while ((i = value.indexOf('{{', i + 1)) >= 0) {
|
||||
let j = value.indexOf('}}', i + 1);
|
||||
if (j < 0) {
|
||||
return value;
|
||||
}
|
||||
value = value.slice(0, i) + _.evalInContext(value.slice(i + 2, j), ctx) + value.slice(j + 2);
|
||||
i = j + 1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
toXMLString(xml) {
|
||||
// noinspection JSTypeOfValues
|
||||
if (typeof xml === 'xml') {
|
||||
xml = xml.toXMLString();
|
||||
}
|
||||
return xml.toString();
|
||||
},
|
||||
evalInContext(expression, ctx) {
|
||||
return __exitIfError__(() => {
|
||||
// @ScopeBinding
|
||||
// noinspection WithStatementJS
|
||||
with (ctx) {
|
||||
return ( /* @IIFE */ function () {
|
||||
return eval(expression);
|
||||
})();
|
||||
}
|
||||
});
|
||||
},
|
||||
initListView(list) {
|
||||
list.setDataSourceAdapter({
|
||||
getItemCount(data) {
|
||||
return data.length;
|
||||
},
|
||||
getItem(data, i) {
|
||||
return data[i];
|
||||
},
|
||||
setDataSource(data) {
|
||||
let adapter = list.getAdapter();
|
||||
Array.observe(data, function (changes) {
|
||||
changes.forEach((change) => {
|
||||
if (change.type === 'splice') {
|
||||
if (change.removed && change.removed.length > 0) {
|
||||
adapter.notifyItemRangeRemoved(change.index, change.removed.length);
|
||||
}
|
||||
if (change.addedCount > 0) {
|
||||
adapter.notifyItemRangeInserted(change.index, change.addedCount);
|
||||
}
|
||||
} else if (change.type === 'update') {
|
||||
try {
|
||||
adapter.notifyItemChanged(parseInt(change.name));
|
||||
} catch (e) {
|
||||
// Ignored.
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
wrapUiAction(action) {
|
||||
return new Runnable({
|
||||
run: () => typeof activity !== 'undefined' ? action() : __exitIfError__(action),
|
||||
});
|
||||
},
|
||||
ensureActivity() {
|
||||
if (typeof activity === 'undefined') {
|
||||
throw ReferenceError('An activity is needed. Try running in "ui" thread');
|
||||
}
|
||||
},
|
||||
setLayoutInflaterDelegate() {
|
||||
layoutInflater.setLayoutInflaterDelegate(this.layoutInflaterDelegate);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.UI}
|
||||
*/
|
||||
const ui = _.rtUi;
|
||||
const uiProxy = new _.UI();
|
||||
const layoutInflater = ui.layoutInflater;
|
||||
|
||||
_.setLayoutInflaterDelegate();
|
||||
|
||||
return ui;
|
||||
};
|
||||
1406
app/src/main/assets/modules/__util__.js
Normal file
1406
app/src/main/assets/modules/__util__.js
Normal file
File diff suppressed because it is too large
Load Diff
55
app/src/main/assets/modules/__web__.js
Normal file
55
app/src/main/assets/modules/__web__.js
Normal file
@@ -0,0 +1,55 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||
* @return {Internal.Web}
|
||||
*/
|
||||
module.exports = function (scriptRuntime, scope) {
|
||||
const Context = org.mozilla.javascript.Context;
|
||||
const InjectableWebView = org.autojs.autojs.core.web.InjectableWebView;
|
||||
const InjectableWebClient = org.autojs.autojs.core.web.InjectableWebClient;
|
||||
|
||||
let _ = {
|
||||
Web: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Web
|
||||
*/
|
||||
const Web = function () {
|
||||
// Empty interface body.
|
||||
};
|
||||
|
||||
Web.prototype = {
|
||||
constructor: Web,
|
||||
};
|
||||
|
||||
return Web;
|
||||
})(),
|
||||
scopeAugment() {
|
||||
Object.assign(scope, {
|
||||
/**
|
||||
* @global
|
||||
*/
|
||||
newInjectableWebClient() {
|
||||
return new InjectableWebClient(Context.getCurrentContext(), scope);
|
||||
},
|
||||
/**
|
||||
* @global
|
||||
*/
|
||||
newInjectableWebView(activity) {
|
||||
let ctx = activity || scope.activity;
|
||||
return new InjectableWebView(ctx, Context.getCurrentContext(), scope);
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Internal.Web}
|
||||
*/
|
||||
const web = new _.Web();
|
||||
|
||||
_.scopeAugment();
|
||||
|
||||
return web;
|
||||
};
|
||||
3
app/src/main/assets/modules/array-observe.min.js
vendored
Normal file
3
app/src/main/assets/modules/array-observe.min.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function(){
|
||||
Object.observe&&!Array.observe&&function(t,e){"use strict";var n=t.getNotifier,r="performChange",i="_original",o="splice";var u={push:function h(t){var e=arguments,u=h[i].apply(this,e);n(this)[r](o,function(){return{index:u-e.length,addedCount:e.length,removed:[]}});return u},unshift:function d(t){var e=arguments,u=d[i].apply(this,e);n(this)[r](o,function(){return{index:0,addedCount:e.length,removed:[]}});return u},pop:function a(){var t=this.length,e=a[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:this.length,addedCount:0,removed:[e]}},this);return e},shift:function l(){var t=this.length,e=l[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:0,addedCount:0,removed:[e]}},this);return e},splice:function f(t,e){var u=arguments,s=f[i].apply(this,u);if(s.length||u.length>2)n(this)[r](o,function(){return{index:t,addedCount:u.length-2,removed:s}},this);return s}};for(var s in u){u[s][i]=e.prototype[s];e.prototype[s]=u[s]}e.observe=function(e,n){return t.observe(e,n,["add","update","delete",o])};e.unobserve=t.unobserve}(Object,Array);
|
||||
}
|
||||
1249
app/src/main/assets/modules/banana-i18n.js
Normal file
1249
app/src/main/assets/modules/banana-i18n.js
Normal file
File diff suppressed because one or more lines are too long
282
app/src/main/assets/modules/jvm-npm.js
Normal file
282
app/src/main/assets/modules/jvm-npm.js
Normal file
@@ -0,0 +1,282 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/**
|
||||
* Copyright 2014-2016 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Since we intend to use the Function constructor.
|
||||
/* jshint evil: true */
|
||||
|
||||
( /* @ModuleIIFE */ () => {
|
||||
const File = java.io.File;
|
||||
const Scanner = java.util.Scanner;
|
||||
const System = java.lang.System;
|
||||
const Thread = java.lang.Thread;
|
||||
|
||||
let _ = {
|
||||
Module: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @extends Internal.Require.Module
|
||||
*/
|
||||
const Module = function (id, parent, core) {
|
||||
this._exports = {};
|
||||
this.id = id;
|
||||
this.core = core;
|
||||
this.parent = parent;
|
||||
this.children = [];
|
||||
this.filename = id;
|
||||
this.loaded = false;
|
||||
|
||||
Object.defineProperty(this, 'exports', {
|
||||
get() {
|
||||
return this._exports;
|
||||
},
|
||||
set(val) {
|
||||
require.cache[this.filename] = val;
|
||||
this._exports = val;
|
||||
},
|
||||
});
|
||||
this.exports = {};
|
||||
|
||||
if (parent && parent.children) {
|
||||
parent.children.push(this);
|
||||
}
|
||||
|
||||
this.require = function (id) {
|
||||
return require(id, this);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
Object.assign(Module, {
|
||||
require(id, parent) {
|
||||
return require(id, parent);
|
||||
},
|
||||
_load(file) {
|
||||
return NativeRequire.require(file);
|
||||
},
|
||||
runMain(main) {
|
||||
return Module._load(require.resolve(main));
|
||||
},
|
||||
});
|
||||
|
||||
return Module;
|
||||
})(),
|
||||
RequireCtor: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @implements Internal.Require
|
||||
*/
|
||||
const RequireCtor = function () {
|
||||
return Object.assign(function (id, parent) {
|
||||
const normalizedPath = _.normalizeName(id);
|
||||
if (_.builtInModules.includes(normalizedPath) && !runtime.files.exists(normalizedPath)) {
|
||||
return NativeRequire.require(normalizedPath);
|
||||
}
|
||||
if (id === 'events') {
|
||||
return global[id];
|
||||
}
|
||||
// noinspection HttpUrlsUsage
|
||||
if (id.startsWith('http://') || id.startsWith('https://')) {
|
||||
return NativeRequire.require(id);
|
||||
}
|
||||
|
||||
let file = this.resolve(id, parent);
|
||||
if (!file) {
|
||||
if (typeof NativeRequire.require === 'function') {
|
||||
if (this.debug) {
|
||||
System.out.println([ 'Cannot resolve', id, 'defaulting to native' ].join(' '));
|
||||
}
|
||||
let nativeRequired = NativeRequire.require(id);
|
||||
if (nativeRequired) {
|
||||
return nativeRequired;
|
||||
}
|
||||
}
|
||||
if (this.debug) {
|
||||
System.err.println('Cannot find module ' + id);
|
||||
}
|
||||
throw new _.ModuleError('Cannot find module ' + id, 'MODULE_NOT_FOUND');
|
||||
}
|
||||
if (file.core) {
|
||||
file = file.path;
|
||||
}
|
||||
if (this.cache[file]) {
|
||||
return this.cache[file];
|
||||
}
|
||||
if (file.endsWith('.js')) {
|
||||
return _.Module._load(file, parent);
|
||||
}
|
||||
if (file.endsWith('.json')) {
|
||||
return _.loadJSON(file);
|
||||
}
|
||||
}.bind(this), RequireCtor.prototype);
|
||||
};
|
||||
|
||||
Object.assign(RequireCtor.prototype, {
|
||||
NODE_PATH: undefined,
|
||||
// System.getProperty('user.dir');
|
||||
root: runtime.files.cwd(),
|
||||
debug: true,
|
||||
cache: {},
|
||||
extensions: {},
|
||||
resolve(id, parent) {
|
||||
const roots = _.findRoots(parent);
|
||||
for (let i = 0; i < roots.length; ++i) {
|
||||
const root = roots[i];
|
||||
const result = _.resolveCoreModule(id)
|
||||
|| _.resolveAsFile(id, root, '.js')
|
||||
|| _.resolveAsFile(id, root, '.json')
|
||||
|| _.resolveAsDirectory(id, root)
|
||||
|| _.resolveAsNodeModule(id, root);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
paths() {
|
||||
let r = [
|
||||
System.getProperty('user.home') + '/.node_modules',
|
||||
System.getProperty('user.home') + '/.node_libraries',
|
||||
];
|
||||
|
||||
if (this.NODE_PATH) {
|
||||
r = r.concat(_.parsePaths(this.NODE_PATH));
|
||||
} else {
|
||||
const { NODE_PATH } = System.getenv();
|
||||
if (NODE_PATH) {
|
||||
r = r.concat(_.parsePaths(NODE_PATH));
|
||||
}
|
||||
}
|
||||
// r.push( $PREFIX + "/node/library" )
|
||||
return r;
|
||||
},
|
||||
});
|
||||
|
||||
return RequireCtor;
|
||||
})(),
|
||||
ModuleError: ( /* @IIFE */ () => {
|
||||
/**
|
||||
* @param {?string} [message]
|
||||
* @param {?string} [code]
|
||||
* @param {?string} [cause]
|
||||
* @extends Error
|
||||
*/
|
||||
const ModuleError = function (message, code, cause) {
|
||||
this.message = message || 'Error loading module';
|
||||
this.code = code || 'UNDEFINED';
|
||||
this.cause = cause;
|
||||
};
|
||||
|
||||
ModuleError.prototype = Object.assign(new Error(), { constructor: ModuleError });
|
||||
|
||||
return ModuleError;
|
||||
})(),
|
||||
builtInModules: [ 'lodash.js' ],
|
||||
findRoots(parent) {
|
||||
return [ this.findRoot(parent) ].concat(require.paths());
|
||||
},
|
||||
findRoot(parent) {
|
||||
if (!parent || !parent.id) {
|
||||
return require.root;
|
||||
}
|
||||
return (/* pathParts = */ parent.id.split(/[\/|\\,]+/g).slice(0, -1)).join(File.separator);
|
||||
},
|
||||
readFile(filename, core) {
|
||||
try {
|
||||
let input = core
|
||||
? Thread.currentThread().getContextClassLoader().getResourceAsStream(filename)
|
||||
: new File(filename);
|
||||
// TODO: I think this is not very efficient
|
||||
return new Scanner(input).useDelimiter('\\A').next();
|
||||
} catch (e) {
|
||||
throw new _.ModuleError(`Cannot read file [${filename}]: `, 'IO_ERROR', e);
|
||||
}
|
||||
},
|
||||
parsePaths: (paths) => paths && paths !== ''
|
||||
? paths.split(/* separator = */ System.getProperty('os.name').toLowerCase().includes('win') ? ';' : ':')
|
||||
: [],
|
||||
normalizeName(fileName, ext) {
|
||||
if (fileName.endsWith('.json')) {
|
||||
return fileName;
|
||||
}
|
||||
ext = ext || '.js';
|
||||
if (!fileName.endsWith(ext)) {
|
||||
fileName += ext;
|
||||
}
|
||||
return fileName;
|
||||
},
|
||||
loadJSON(file) {
|
||||
return require.cache[file] = JSON.parse(this.readFile(file));
|
||||
},
|
||||
resolveCoreModule(id) {
|
||||
const name = this.normalizeName(id);
|
||||
if (Thread.currentThread().getContextClassLoader().getResource(name)) {
|
||||
return { path: name, core: true };
|
||||
}
|
||||
},
|
||||
resolveAsFile(id, root, ext) {
|
||||
let file;
|
||||
if (!id.startsWith(File.separator)) {
|
||||
file = new File([ root, this.normalizeName(id, ext) ].join(File.separator));
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
file = new File(this.normalizeName(id, ext));
|
||||
if (!file.exists()) {
|
||||
return this.resolveAsDirectory(id);
|
||||
}
|
||||
}
|
||||
return file.getCanonicalPath();
|
||||
},
|
||||
resolveAsDirectory(id, root) {
|
||||
const base = [ root, id ].join(File.separator);
|
||||
const file = new File([ base, 'package.json' ].join(File.separator));
|
||||
if (file.exists()) {
|
||||
try {
|
||||
const body = this.readFile(file.getCanonicalPath());
|
||||
const pkg = JSON.parse(body);
|
||||
if (pkg.main) {
|
||||
return this.resolveAsFile(pkg.main, base)
|
||||
|| this.resolveAsDirectory(pkg.main, base);
|
||||
}
|
||||
return this.resolveAsFile('index.js', base);
|
||||
} catch (ex) {
|
||||
throw new _.ModuleError('Cannot load JSON file', 'PARSE_ERROR', ex);
|
||||
}
|
||||
}
|
||||
return this.resolveAsFile('index.js', base);
|
||||
},
|
||||
resolveAsNodeModule(id, root) {
|
||||
const base = [ root, 'node_modules' ].join(File.separator);
|
||||
return this.resolveAsFile(id, base)
|
||||
|| this.resolveAsDirectory(id, base)
|
||||
|| (root ? this.resolveAsNodeModule(id, new File(root).getParent()) : false);
|
||||
},
|
||||
};
|
||||
|
||||
let NativeRequire = ( /* @IIFE */ function () {
|
||||
const o = this['NativeRequire'] || {};
|
||||
if (!o.require && typeof this.require === 'function') {
|
||||
o.require = this.require;
|
||||
}
|
||||
return o;
|
||||
}).call(global);
|
||||
|
||||
/**
|
||||
* @type {Internal.Require}
|
||||
*/
|
||||
const require = global.require = new _.RequireCtor();
|
||||
|
||||
module.exports = _.Module;
|
||||
})();
|
||||
29
app/src/main/assets/modules/lodash.js
Normal file
29
app/src/main/assets/modules/lodash.js
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @license
|
||||
* Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
|
||||
* Build: `lodash core -o ./dist/lodash.core.js`
|
||||
*/
|
||||
;(function(){function n(n){return H(n)&&pn.call(n,"callee")&&!yn.call(n,"callee")}function t(n,t){return n.push.apply(n,t),n}function r(n){return function(t){return null==t?Z:t[n]}}function e(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function u(n,t){return j(t,function(t){return n[t]})}function o(n){return n instanceof i?n:new i(n)}function i(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t}function c(n,t,r){if(typeof n!="function")throw new TypeError("Expected a function");
|
||||
return setTimeout(function(){n.apply(Z,r)},t)}function f(n,t){var r=true;return mn(n,function(n,e,u){return r=!!t(n,e,u)}),r}function a(n,t,r){for(var e=-1,u=n.length;++e<u;){var o=n[e],i=t(o);if(null!=i&&(c===Z?i===i:r(i,c)))var c=i,f=o}return f}function l(n,t){var r=[];return mn(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function p(n,r,e,u,o){var i=-1,c=n.length;for(e||(e=R),o||(o=[]);++i<c;){var f=n[i];0<r&&e(f)?1<r?p(f,r-1,e,u,o):t(o,f):u||(o[o.length]=f)}return o}function s(n,t){return n&&On(n,t,Dn);
|
||||
}function h(n,t){return l(t,function(t){return U(n[t])})}function v(n,t){return n>t}function b(n,t,r,e,u){return n===t||(null==n||null==t||!H(n)&&!H(t)?n!==n&&t!==t:y(n,t,r,e,b,u))}function y(n,t,r,e,u,o){var i=Nn(n),c=Nn(t),f=i?"[object Array]":hn.call(n),a=c?"[object Array]":hn.call(t),f="[object Arguments]"==f?"[object Object]":f,a="[object Arguments]"==a?"[object Object]":a,l="[object Object]"==f,c="[object Object]"==a,a=f==a;o||(o=[]);var p=An(o,function(t){return t[0]==n}),s=An(o,function(n){
|
||||
return n[0]==t});if(p&&s)return p[1]==t;if(o.push([n,t]),o.push([t,n]),a&&!l){if(i)r=T(n,t,r,e,u,o);else n:{switch(f){case"[object Boolean]":case"[object Date]":case"[object Number]":r=J(+n,+t);break n;case"[object Error]":r=n.name==t.name&&n.message==t.message;break n;case"[object RegExp]":case"[object String]":r=n==t+"";break n}r=false}return o.pop(),r}return 1&r||(i=l&&pn.call(n,"__wrapped__"),f=c&&pn.call(t,"__wrapped__"),!i&&!f)?!!a&&(r=B(n,t,r,e,u,o),o.pop(),r):(i=i?n.value():n,f=f?t.value():t,
|
||||
r=u(i,f,r,e,o),o.pop(),r)}function g(n){return typeof n=="function"?n:null==n?X:(typeof n=="object"?d:r)(n)}function _(n,t){return n<t}function j(n,t){var r=-1,e=M(n)?Array(n.length):[];return mn(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function d(n){var t=_n(n);return function(r){var e=t.length;if(null==r)return!e;for(r=Object(r);e--;){var u=t[e];if(!(u in r&&b(n[u],r[u],3)))return false}return true}}function m(n,t){return n=Object(n),C(t,function(t,r){return r in n&&(t[r]=n[r]),t},{})}function O(n){return xn(I(n,void 0,X),n+"");
|
||||
}function x(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++e<u;)r[e]=n[e+t];return r}function A(n){return x(n,0,n.length)}function E(n,t){var r;return mn(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function w(n,r){return C(r,function(n,r){return r.func.apply(r.thisArg,t([n],r.args))},n)}function k(n,t,r){var e=!r;r||(r={});for(var u=-1,o=t.length;++u<o;){var i=t[u],c=Z;if(c===Z&&(c=n[i]),e)r[i]=c;else{var f=r,a=f[i];pn.call(f,i)&&J(a,c)&&(c!==Z||i in f)||(f[i]=c);
|
||||
}}return r}function N(n){return O(function(t,r){var e=-1,u=r.length,o=1<u?r[u-1]:Z,o=3<n.length&&typeof o=="function"?(u--,o):Z;for(t=Object(t);++e<u;){var i=r[e];i&&n(t,i,e,o)}return t})}function F(n){return function(){var t=arguments,r=dn(n.prototype),t=n.apply(r,t);return V(t)?t:r}}function S(n,t,r){function e(){for(var o=-1,i=arguments.length,c=-1,f=r.length,a=Array(f+i),l=this&&this!==on&&this instanceof e?u:n;++c<f;)a[c]=r[c];for(;i--;)a[c++]=arguments[++o];return l.apply(t,a)}if(typeof n!="function")throw new TypeError("Expected a function");
|
||||
var u=F(n);return e}function T(n,t,r,e,u,o){var i=n.length,c=t.length;if(i!=c&&!(1&r&&c>i))return false;for(var c=-1,f=true,a=2&r?[]:Z;++c<i;){var l=n[c],p=t[c];if(void 0!==Z){f=false;break}if(a){if(!E(t,function(n,t){if(!P(a,t)&&(l===n||u(l,n,r,e,o)))return a.push(t)})){f=false;break}}else if(l!==p&&!u(l,p,r,e,o)){f=false;break}}return f}function B(n,t,r,e,u,o){var i=1&r,c=Dn(n),f=c.length,a=Dn(t).length;if(f!=a&&!i)return false;for(var l=f;l--;){var p=c[l];if(!(i?p in t:pn.call(t,p)))return false}for(a=true;++l<f;){var p=c[l],s=n[p],h=t[p];
|
||||
if(void 0!==Z||s!==h&&!u(s,h,r,e,o)){a=false;break}i||(i="constructor"==p)}return a&&!i&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(a=false)),a}function R(t){return Nn(t)||n(t)}function D(n){var t=[];if(null!=n)for(var r in Object(n))t.push(r);return t}function I(n,t,r){return t=jn(t===Z?n.length-1:t,0),function(){for(var e=arguments,u=-1,o=jn(e.length-t,0),i=Array(o);++u<o;)i[u]=e[t+u];for(u=-1,
|
||||
o=Array(t+1);++u<t;)o[u]=e[u];return o[t]=r(i),n.apply(this,o)}}function $(n){return(null==n?0:n.length)?p(n,1):[]}function q(n){return n&&n.length?n[0]:Z}function P(n,t,r){var e=null==n?0:n.length;r=typeof r=="number"?0>r?jn(e+r,0):r:0,r=(r||0)-1;for(var u=t===t;++r<e;){var o=n[r];if(u?o===t:o!==o)return r}return-1}function z(n,t){return mn(n,g(t))}function C(n,t,r){return e(n,g(t),r,3>arguments.length,mn)}function G(n,t){var r;if(typeof t!="function")throw new TypeError("Expected a function");return n=Fn(n),
|
||||
function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=Z),r}}function J(n,t){return n===t||n!==n&&t!==t}function M(n){var t;return(t=null!=n)&&(t=n.length,t=typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t),t&&!U(n)}function U(n){return!!V(n)&&(n=hn.call(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function V(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function H(n){return null!=n&&typeof n=="object"}function K(n){
|
||||
return typeof n=="number"||H(n)&&"[object Number]"==hn.call(n)}function L(n){return typeof n=="string"||!Nn(n)&&H(n)&&"[object String]"==hn.call(n)}function Q(n){return typeof n=="string"?n:null==n?"":n+""}function W(n){return null==n?[]:u(n,Dn(n))}function X(n){return n}function Y(n,r,e){var u=Dn(r),o=h(r,u);null!=e||V(r)&&(o.length||!u.length)||(e=r,r=n,n=this,o=h(r,Dn(r)));var i=!(V(e)&&"chain"in e&&!e.chain),c=U(n);return mn(o,function(e){var u=r[e];n[e]=u,c&&(n.prototype[e]=function(){var r=this.__chain__;
|
||||
if(i||r){var e=n(this.__wrapped__);return(e.__actions__=A(this.__actions__)).push({func:u,args:arguments,thisArg:n}),e.__chain__=r,e}return u.apply(n,t([this.value()],arguments))})}),n}var Z,nn=1/0,tn=/[&<>"']/g,rn=RegExp(tn.source),en=/^(?:0|[1-9]\d*)$/,un=typeof self=="object"&&self&&self.Object===Object&&self,on=typeof global=="object"&&global&&global.Object===Object&&global||un||Function("return this")(),cn=(un=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,fn=function(n){
|
||||
return function(t){return null==n?Z:n[t]}}({"&":"&","<":"<",">":">",'"':""","'":"'"}),an=Array.prototype,ln=Object.prototype,pn=ln.hasOwnProperty,sn=0,hn=ln.toString,vn=on._,bn=Object.create,yn=ln.propertyIsEnumerable,gn=on.isFinite,_n=function(n,t){return function(r){return n(t(r))}}(Object.keys,Object),jn=Math.max,dn=function(){function n(){}return function(t){return V(t)?bn?bn(t):(n.prototype=t,t=new n,n.prototype=Z,t):{}}}();i.prototype=dn(o.prototype),i.prototype.constructor=i;
|
||||
var mn=function(n,t){return function(r,e){if(null==r)return r;if(!M(r))return n(r,e);for(var u=r.length,o=t?u:-1,i=Object(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}(s),On=function(n){return function(t,r,e){var u=-1,o=Object(t);e=e(t);for(var i=e.length;i--;){var c=e[n?i:++u];if(false===r(o[c],c,o))break}return t}}(),xn=X,An=function(n){return function(t,r,e){var u=Object(t);if(!M(t)){var o=g(r);t=Dn(t),r=function(n){return o(u[n],n,u)}}return r=n(t,r,e),-1<r?u[o?t[r]:r]:Z}}(function(n,t,r){var e=null==n?0:n.length;
|
||||
if(!e)return-1;r=null==r?0:Fn(r),0>r&&(r=jn(e+r,0));n:{for(t=g(t),e=n.length,r+=-1;++r<e;)if(t(n[r],r,n)){n=r;break n}n=-1}return n}),En=O(function(n,t,r){return S(n,t,r)}),wn=O(function(n,t){return c(n,1,t)}),kn=O(function(n,t,r){return c(n,Sn(t)||0,r)}),Nn=Array.isArray,Fn=Number,Sn=Number,Tn=N(function(n,t){k(t,_n(t),n)}),Bn=N(function(n,t){k(t,D(t),n)}),Rn=O(function(n,t){n=Object(n);var r,e=-1,u=t.length,o=2<u?t[2]:Z;if(r=o){r=t[0];var i=t[1];if(V(o)){var c=typeof i;if("number"==c){if(c=M(o))var c=o.length,f=typeof i,c=null==c?9007199254740991:c,c=!!c&&("number"==f||"symbol"!=f&&en.test(i))&&-1<i&&0==i%1&&i<c;
|
||||
}else c="string"==c&&i in o;r=!!c&&J(o[i],r)}else r=false}for(r&&(u=1);++e<u;)for(o=t[e],r=In(o),i=-1,c=r.length;++i<c;){var f=r[i],a=n[f];(a===Z||J(a,ln[f])&&!pn.call(n,f))&&(n[f]=o[f])}return n}),Dn=_n,In=D,$n=function(n){return xn(I(n,Z,$),n+"")}(function(n,t){return null==n?{}:m(n,t)});o.assignIn=Bn,o.before=G,o.bind=En,o.chain=function(n){return n=o(n),n.__chain__=true,n},o.compact=function(n){return l(n,Boolean)},o.concat=function(){var n=arguments.length;if(!n)return[];for(var r=Array(n-1),e=arguments[0];n--;)r[n-1]=arguments[n];
|
||||
return t(Nn(e)?A(e):[e],p(r,1))},o.create=function(n,t){var r=dn(n);return null==t?r:Tn(r,t)},o.defaults=Rn,o.defer=wn,o.delay=kn,o.filter=function(n,t){return l(n,g(t))},o.flatten=$,o.flattenDeep=function(n){return(null==n?0:n.length)?p(n,nn):[]},o.iteratee=g,o.keys=Dn,o.map=function(n,t){return j(n,g(t))},o.matches=function(n){return d(Tn({},n))},o.mixin=Y,o.negate=function(n){if(typeof n!="function")throw new TypeError("Expected a function");return function(){return!n.apply(this,arguments)}},o.once=function(n){
|
||||
return G(2,n)},o.pick=$n,o.slice=function(n,t,r){var e=null==n?0:n.length;return r=r===Z?e:+r,e?x(n,null==t?0:+t,r):[]},o.sortBy=function(n,t){var e=0;return t=g(t),j(j(n,function(n,r,u){return{value:n,index:e++,criteria:t(n,r,u)}}).sort(function(n,t){var r;n:{r=n.criteria;var e=t.criteria;if(r!==e){var u=r!==Z,o=null===r,i=r===r,c=e!==Z,f=null===e,a=e===e;if(!f&&r>e||o&&c&&a||!u&&a||!i){r=1;break n}if(!o&&r<e||f&&u&&i||!c&&i||!a){r=-1;break n}}r=0}return r||n.index-t.index}),r("value"))},o.tap=function(n,t){
|
||||
return t(n),n},o.thru=function(n,t){return t(n)},o.toArray=function(n){return M(n)?n.length?A(n):[]:W(n)},o.values=W,o.extend=Bn,Y(o,o),o.clone=function(n){return V(n)?Nn(n)?A(n):k(n,_n(n)):n},o.escape=function(n){return(n=Q(n))&&rn.test(n)?n.replace(tn,fn):n},o.every=function(n,t,r){return t=r?Z:t,f(n,g(t))},o.find=An,o.forEach=z,o.has=function(n,t){return null!=n&&pn.call(n,t)},o.head=q,o.identity=X,o.indexOf=P,o.isArguments=n,o.isArray=Nn,o.isBoolean=function(n){return true===n||false===n||H(n)&&"[object Boolean]"==hn.call(n);
|
||||
},o.isDate=function(n){return H(n)&&"[object Date]"==hn.call(n)},o.isEmpty=function(t){return M(t)&&(Nn(t)||L(t)||U(t.splice)||n(t))?!t.length:!_n(t).length},o.isEqual=function(n,t){return b(n,t)},o.isFinite=function(n){return typeof n=="number"&&gn(n)},o.isFunction=U,o.isNaN=function(n){return K(n)&&n!=+n},o.isNull=function(n){return null===n},o.isNumber=K,o.isObject=V,o.isRegExp=function(n){return H(n)&&"[object RegExp]"==hn.call(n)},o.isString=L,o.isUndefined=function(n){return n===Z},o.last=function(n){
|
||||
var t=null==n?0:n.length;return t?n[t-1]:Z},o.max=function(n){return n&&n.length?a(n,X,v):Z},o.min=function(n){return n&&n.length?a(n,X,_):Z},o.noConflict=function(){return on._===this&&(on._=vn),this},o.noop=function(){},o.reduce=C,o.result=function(n,t,r){return t=null==n?Z:n[t],t===Z&&(t=r),U(t)?t.call(n):t},o.size=function(n){return null==n?0:(n=M(n)?n:_n(n),n.length)},o.some=function(n,t,r){return t=r?Z:t,E(n,g(t))},o.uniqueId=function(n){var t=++sn;return Q(n)+t},o.each=z,o.first=q,Y(o,function(){
|
||||
var n={};return s(o,function(t,r){pn.call(o.prototype,r)||(n[r]=t)}),n}(),{chain:false}),o.VERSION="4.17.15",mn("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:an)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n);o.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Nn(u)?u:[],n)}return this[r](function(r){return t.apply(Nn(r)?r:[],n);
|
||||
})}}),o.prototype.toJSON=o.prototype.valueOf=o.prototype.value=function(){return w(this.__wrapped__,this.__actions__)},typeof define=="function"&&typeof define.amd=="object"&&define.amd?(on._=o, define(function(){return o})):cn?((cn.exports=o)._=o,un._=o):on._=o}).call(this);
|
||||
3
app/src/main/assets/modules/object-observe-lite.min.js
vendored
Normal file
3
app/src/main/assets/modules/object-observe-lite.min.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function(){
|
||||
Object.observe||function(e,t,n,r){var o,i,c=["add","update","delete","reconfigure","setPrototype","preventExtensions"],a=t.isArray||function(e){return function(t){return"[object Array]"===e.call(t)}}(e.prototype.toString),f=t.prototype.indexOf?t.indexOf||function(e,n,r){return t.prototype.indexOf.call(e,n,r)}:function(e,t,n){for(var r=n||0;r<e.length;r++)if(e[r]===t)return r;return-1},s=n.Map!==r&&Map.prototype.forEach?function(){return new Map}:function(){var e=[],t=[];return{size:0,has:function(t){return f(e,t)>-1},get:function(n){return t[f(e,n)]},set:function(n,r){var o=f(e,n);-1===o?(e.push(n),t.push(r),this.size++):t[o]=r},"delete":function(n){var r=f(e,n);r>-1&&(e.splice(r,1),t.splice(r,1),this.size--)},forEach:function(n){for(var r=0;r<e.length;r++)n.call(arguments[1],t[r],e[r],this)}}},u=e.getOwnPropertyNames?function(){var t=e.getOwnPropertyNames;try{arguments.callee}catch(n){var r=(t(f).join(" ")+" ").replace(/prototype |length |name /g,"").slice(0,-1).split(" ");r.length&&(t=function(t){var n=e.getOwnPropertyNames(t);if("function"==typeof t)for(var o,i=0;i<r.length;)(o=f(n,r[i++]))>-1&&n.splice(o,1);return n})}return t}():function(t){var n,r,o=[];if("hasOwnProperty"in t)for(n in t)t.hasOwnProperty(n)&&o.push(n);else{r=e.hasOwnProperty;for(n in t)r.call(t,n)&&o.push(n)}return a(t)&&o.push("length"),o},p=n.requestAnimationFrame||n.webkitRequestAnimationFrame||function(){var e=+new Date,t=e;return function(n){return setTimeout(function(){n((t=+new Date)-e)},17)}}(),l=function(e,t,n){var r=o.get(e);r?(v(r,e),g(e,r,t,n)):(r=h(e),g(e,r,t,n),1===o.size&&p(d))},h=function(e,t){for(var n=u(e),r=[],i=0,t={handlers:s(),properties:n,values:r,notifier:b(e,t)};i<n.length;)r[i]=e[n[i++]];return o.set(e,t),t},v=function(e,t,n){if(e.handlers.size){var r,o,i,c,a,s,p,l=e.values,h=0;for(r=e.properties.slice(),o=r.length,i=u(t);h<i.length;)a=i[h++],c=f(r,a),s=t[a],-1===c?(w(t,e,{name:a,type:"add",object:t},n),e.properties.push(a),l.push(s)):(p=l[c],r[c]=null,o--,(p===s?0===p&&1/p!==1/s:p===p||s===s)&&(w(t,e,{name:a,type:"update",object:t,oldValue:p},n),e.values[c]=s));for(h=r.length;o&&h--;)null!==r[h]&&(w(t,e,{name:r[h],type:"delete",object:t,oldValue:l[h]},n),e.properties.splice(h,1),e.values.splice(h,1),o--)}},d=function(){o.size&&(o.forEach(v),i.forEach(y),p(d))},y=function(e,t){var n=e.changeRecords;n.length&&(e.changeRecords=[],t(n))},b=function(e,t){return arguments.length<2&&(t=o.get(e)),t&&t.notifier||{notify:function(t){t.type;var n=o.get(e);if(n){var r,i={object:e};for(r in t)"object"!==r&&(i[r]=t[r]);w(e,n,i)}},performChange:function(t,n){if("string"!=typeof t)throw new TypeError("Invalid non-string changeType");if("function"!=typeof n)throw new TypeError("Cannot perform non-function");var i,c,a=o.get(e),f=arguments[2],s=f===r?n():n.call(f);if(a&&v(a,e,t),a&&s&&"object"==typeof s){c={object:e,type:t};for(i in s)"object"!==i&&"type"!==i&&(c[i]=s[i]);w(e,a,c)}}}},g=function(e,t,n,r){var o=i.get(n);o||i.set(n,o={observed:s(),changeRecords:[]}),o.observed.set(e,{acceptList:r.slice(),data:t}),t.handlers.set(n,o)},w=function(e,t,n,r){t.handlers.forEach(function(t){var o=t.observed.get(e).acceptList;("string"!=typeof r||-1===f(o,r))&&f(o,n.type)>-1&&t.changeRecords.push(n)})};o=s(),i=s(),e.observe=function(t,n,o){if(!t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.observe cannot observe non-object");if("function"!=typeof n)throw new TypeError("Object.observe cannot deliver to non-function");if(e.isFrozen&&e.isFrozen(n))throw new TypeError("Object.observe cannot deliver to a frozen function object");if(o===r)o=c;else if(!o||"object"!=typeof o)throw new TypeError("Third argument to Object.observe must be an array of strings.");return l(t,n,o),t},e.unobserve=function(e,t){if(null===e||"object"!=typeof e&&"function"!=typeof e)throw new TypeError("Object.unobserve cannot unobserve non-object");if("function"!=typeof t)throw new TypeError("Object.unobserve cannot deliver to non-function");var n,r=i.get(t);return r&&(n=r.observed.get(e))&&(r.observed.forEach(function(e,t){v(e.data,t)}),p(function(){y(r,t)}),1===r.observed.size&&r.observed.has(e)?i["delete"](t):r.observed["delete"](e),1===n.data.handlers.size?o["delete"](e):n.data.handlers["delete"](t)),e},e.getNotifier=function(t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.getNotifier cannot getNotifier non-object");return e.isFrozen&&e.isFrozen(t)?null:b(t)},e.deliverChangeRecords=function(e){if("function"!=typeof e)throw new TypeError("Object.deliverChangeRecords cannot deliver to non-function");var t=i.get(e);t&&(t.observed.forEach(function(e,t){v(e.data,t)}),y(t,e))}}(Object,Array,this);
|
||||
}
|
||||
47
app/src/main/assets/modules/polyfill.js
Normal file
47
app/src/main/assets/modules/polyfill.js
Normal file
@@ -0,0 +1,47 @@
|
||||
module.exports = {
|
||||
fill() {
|
||||
// @Comment by SuperMonster003 on May 6, 2022.
|
||||
// ! Already implemented in Rhino 1.7.15-SNAPSHOT as of Mar 18, 2022.
|
||||
|
||||
// if (!Object.getOwnPropertyDescriptors) {
|
||||
// /**
|
||||
// * @param {Object} o
|
||||
// * @return {Object.<string,PropertyDescriptor>} <!-- or {PropertyDescriptorMap} -->
|
||||
// */
|
||||
// Object.getOwnPropertyDescriptors = function (o) {
|
||||
// let descriptor = {};
|
||||
// Object.getOwnPropertyNames(o).forEach((k) => {
|
||||
// descriptor[k] = Object.getOwnPropertyDescriptor(o, k);
|
||||
// });
|
||||
// return descriptor;
|
||||
// };
|
||||
// }
|
||||
|
||||
if (!Array.prototype.flat) {
|
||||
Object.defineProperty(Array.prototype, 'flat', {
|
||||
value(depth) {
|
||||
return ( /* @IIFE */ function flat(arr, d) {
|
||||
return d <= 0 ? arr : arr.reduce((a, b) => {
|
||||
return a.concat(Array.isArray(b) ? flat(b, d - 1) : b);
|
||||
}, []);
|
||||
})(this.slice(), Math.max(Number(depth) || 0, 1));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!Array.prototype.at) {
|
||||
Object.defineProperty(Array.prototype, 'at', {
|
||||
value(index) {
|
||||
let relIdx = ( /* @IIFE */ () => {
|
||||
const num = Number(index);
|
||||
return isNaN(num) ? 0 : isFinite(num) ? Math.trunc(num) : num;
|
||||
})();
|
||||
|
||||
let idx = relIdx >= 0 ? relIdx : relIdx + this.length;
|
||||
|
||||
return idx >= 0 && idx < this.length ? this[idx] : void 0;
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
305
app/src/main/assets/modules/promise.js
Normal file
305
app/src/main/assets/modules/promise.js
Normal file
@@ -0,0 +1,305 @@
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
/**
|
||||
* Updated and modified by SuperMonster003 on May 23, 2022.
|
||||
* @see https://raw.githubusercontent.com/taylorhakes/promise-polyfill/master/dist/polyfill.js
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @type {PromiseConstructorLike}
|
||||
*/
|
||||
module.exports = ( /* @IIFE */ () => {
|
||||
let _ = {
|
||||
isArray(x) {
|
||||
return Boolean(x && typeof x.length !== 'undefined');
|
||||
},
|
||||
noop() {
|
||||
},
|
||||
// Polyfill for Function.prototype.bind
|
||||
bind(fn, thisArg) {
|
||||
return function () {
|
||||
fn.apply(thisArg, arguments);
|
||||
};
|
||||
},
|
||||
handle(self, deferred) {
|
||||
while (self._state === 3) {
|
||||
self = self._value;
|
||||
}
|
||||
if (self._state === 0) {
|
||||
self._deferreds.push(deferred);
|
||||
return;
|
||||
}
|
||||
self._handled = true;
|
||||
Promise._immediateFn(function () {
|
||||
let cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
|
||||
if (cb === null) {
|
||||
(self._state === 1 ? _.resolve : _.reject)(deferred.promise, self._value);
|
||||
return;
|
||||
}
|
||||
let ret;
|
||||
try {
|
||||
ret = cb(self._value);
|
||||
} catch (e) {
|
||||
_.reject(deferred.promise, e);
|
||||
return;
|
||||
}
|
||||
_.resolve(deferred.promise, ret);
|
||||
});
|
||||
},
|
||||
resolve(self, newValue) {
|
||||
try {
|
||||
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
|
||||
if (newValue === self) {
|
||||
// noinspection ExceptionCaughtLocallyJS
|
||||
throw new TypeError('A promise cannot be resolved with itself.');
|
||||
}
|
||||
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
|
||||
let then = newValue.then;
|
||||
if (newValue instanceof Promise) {
|
||||
self._state = 3;
|
||||
self._value = newValue;
|
||||
_.finale(self);
|
||||
return;
|
||||
} else if (typeof then === 'function') {
|
||||
_.doResolve(_.bind(then, newValue), self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
self._state = 1;
|
||||
self._value = newValue;
|
||||
_.finale(self);
|
||||
} catch (e) {
|
||||
_.reject(self, e);
|
||||
}
|
||||
},
|
||||
reject(self, newValue) {
|
||||
self._state = 2;
|
||||
self._value = newValue;
|
||||
_.finale(self);
|
||||
},
|
||||
finale(self) {
|
||||
if (self._state === 2 && self._deferreds.length === 0) {
|
||||
Promise._immediateFn(function () {
|
||||
if (!self._handled) {
|
||||
Promise._unhandledRejectionFn(self._value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0, len = self._deferreds.length; i < len; i++) {
|
||||
_.handle(self, self._deferreds[i]);
|
||||
}
|
||||
self._deferreds = null;
|
||||
},
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
Handler(onFulfilled, onRejected, promise) {
|
||||
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
|
||||
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
|
||||
this.promise = promise;
|
||||
},
|
||||
/**
|
||||
* Take a potentially misbehaving resolver function and make sure
|
||||
* onFulfilled and onRejected are only called once.
|
||||
*
|
||||
* Makes no guarantees about asynchrony.
|
||||
*/
|
||||
doResolve(fn, self) {
|
||||
let done = false;
|
||||
try {
|
||||
fn(
|
||||
function (value) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
_.resolve(self, value);
|
||||
},
|
||||
function (reason) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
_.reject(self, reason);
|
||||
},
|
||||
);
|
||||
} catch (ex) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
_.reject(self, ex);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Function} fn
|
||||
*/
|
||||
let Promise = function (fn) {
|
||||
if (!(this instanceof Promise)) {
|
||||
throw new TypeError('Promises must be constructed via new');
|
||||
}
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('not a function');
|
||||
}
|
||||
/** @type {!number} */
|
||||
this._state = 0;
|
||||
/** @type {!boolean} */
|
||||
this._handled = false;
|
||||
/** @type {Promise|undefined} */
|
||||
this._value = undefined;
|
||||
/** @type {!Array<!Function>} */
|
||||
this._deferreds = [];
|
||||
|
||||
_.doResolve(fn, this);
|
||||
};
|
||||
|
||||
Object.assign(Promise.prototype, {
|
||||
catch(onRejected) {
|
||||
return this.then(null, onRejected);
|
||||
},
|
||||
then(onFulfilled, onRejected) {
|
||||
let prom = new this.constructor(_.noop);
|
||||
_.handle(this, new _.Handler(onFulfilled, onRejected, prom));
|
||||
return prom;
|
||||
},
|
||||
finally(callback) {
|
||||
let constructor = this.constructor;
|
||||
return this.then(
|
||||
function (value) {
|
||||
return constructor.resolve(callback()).then(function () {
|
||||
return value;
|
||||
});
|
||||
},
|
||||
function (reason) {
|
||||
return constructor.resolve(callback()).then(function () {
|
||||
return constructor.reject(reason);
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Object.assign(Promise, {
|
||||
// Use polyfill for setImmediate for performance gains
|
||||
_immediateFn(fn) {
|
||||
typeof setImmediate === 'function'
|
||||
? setImmediate(fn)
|
||||
: setTimeout(fn, 0);
|
||||
},
|
||||
_unhandledRejectionFn(err) {
|
||||
if (typeof console !== 'undefined') {
|
||||
console.warn('Possible Unhandled Promise Rejection:', err);
|
||||
}
|
||||
},
|
||||
all(arr) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (!_.isArray(arr)) {
|
||||
return reject(new TypeError('Promise.all accepts an array'));
|
||||
}
|
||||
|
||||
let args = Array.prototype.slice.call(arr);
|
||||
let remaining = args.length;
|
||||
if (remaining === 0) {
|
||||
return resolve([]);
|
||||
}
|
||||
|
||||
function res(i, val) {
|
||||
try {
|
||||
if (val && (typeof val === 'object' || typeof val === 'function')) {
|
||||
let then = val.then;
|
||||
if (typeof then === 'function') {
|
||||
then.call(
|
||||
val,
|
||||
function (val) {
|
||||
res(i, val);
|
||||
},
|
||||
reject,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
args[i] = val;
|
||||
if (--remaining === 0) {
|
||||
resolve(args);
|
||||
}
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
res(i, args[i]);
|
||||
}
|
||||
});
|
||||
},
|
||||
allSettled(arr) {
|
||||
let P = this;
|
||||
return new P(function (resolve, reject) {
|
||||
if (!(arr && typeof arr.length !== 'undefined')) {
|
||||
let msg = `${typeof arr} ${arr} is not iterable (cannot read property Symbol(Symbol.iterator))`;
|
||||
return reject(new TypeError(msg));
|
||||
}
|
||||
let args = Array.prototype.slice.call(arr);
|
||||
let remaining = args.length;
|
||||
if (remaining === 0) {
|
||||
return resolve([]);
|
||||
}
|
||||
|
||||
function res(i, val) {
|
||||
if (val && (typeof val === 'object' || typeof val === 'function')) {
|
||||
let then = val.then;
|
||||
if (typeof then === 'function') {
|
||||
then.call(
|
||||
val,
|
||||
function (val) {
|
||||
res(i, val);
|
||||
},
|
||||
function (e) {
|
||||
args[i] = {status: 'rejected', reason: e};
|
||||
if (--remaining === 0) {
|
||||
resolve(args);
|
||||
}
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
args[i] = {status: 'fulfilled', value: val};
|
||||
if (--remaining === 0) {
|
||||
resolve(args);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
res(i, args[i]);
|
||||
}
|
||||
});
|
||||
},
|
||||
resolve(value) {
|
||||
if (value && typeof value === 'object' && value.constructor === Promise) {
|
||||
return value;
|
||||
}
|
||||
return new Promise(function (resolve) {
|
||||
resolve(value);
|
||||
});
|
||||
},
|
||||
reject(value) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
reject(value);
|
||||
});
|
||||
},
|
||||
race(arr) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (!_.isArray(arr)) {
|
||||
return reject(new TypeError('Promise.race accepts an array'));
|
||||
}
|
||||
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
Promise.resolve(arr[i]).then(resolve, reject);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return Promise;
|
||||
})();
|
||||
89
app/src/main/assets/modules/result-adapter.js
Normal file
89
app/src/main/assets/modules/result-adapter.js
Normal file
@@ -0,0 +1,89 @@
|
||||
( /* @ModuleIIFE */ () => {
|
||||
const Looper = android.os.Looper;
|
||||
|
||||
let _ = {
|
||||
isUiThread() {
|
||||
return Looper.myLooper() === Looper.getMainLooper();
|
||||
},
|
||||
getOrThrow(result) {
|
||||
if (result.error) {
|
||||
throw result.error;
|
||||
}
|
||||
return result.result;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @extends {Internal.ResultAdapter}
|
||||
*/
|
||||
let ResultAdapter = _.isUiThread()
|
||||
? function () {
|
||||
this.cont = continuation.create();
|
||||
this.impl = {
|
||||
setResult: result => this.cont.resume(result),
|
||||
setError: error => this.cont.resumeError(error),
|
||||
get: () => this.cont.await(),
|
||||
};
|
||||
}
|
||||
: function () {
|
||||
this.disposable = runtime.threads.disposable();
|
||||
this.impl = {
|
||||
setResult: result => this.disposable.setAndNotify({ result }),
|
||||
setError: error => this.disposable.setAndNotify({ error }),
|
||||
get: () => _.getOrThrow(this.disposable.blockedGet()),
|
||||
};
|
||||
};
|
||||
|
||||
Object.assign(ResultAdapter, {
|
||||
prototype: {
|
||||
constructor: ResultAdapter,
|
||||
setResult(result) {
|
||||
this.impl.setResult(result);
|
||||
},
|
||||
setError(error) {
|
||||
this.impl.setError(error);
|
||||
},
|
||||
callback() {
|
||||
return function (result, error) {
|
||||
this.result !== undefined
|
||||
? this.result = { result, error }
|
||||
: error ? this.setError(error) : this.setResult(result);
|
||||
}.bind(this);
|
||||
},
|
||||
get() {
|
||||
if (this.result) {
|
||||
return _.getOrThrow(this.result);
|
||||
}
|
||||
this.result = null;
|
||||
return this.impl.get();
|
||||
},
|
||||
},
|
||||
/**
|
||||
* @param {org.autojs.autojs.runtime.api.ScriptPromiseAdapter} promiseAdapter
|
||||
* @return {Promise<unknown>}
|
||||
*/
|
||||
promise(promiseAdapter) {
|
||||
return new Promise((resolve, reject) => {
|
||||
promiseAdapter
|
||||
.onResolve(result => resolve(result))
|
||||
.onReject(error => reject(error));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @param {Promise<unknown> | org.autojs.autojs.runtime.api.ScriptPromiseAdapter} promise
|
||||
* @return {*}
|
||||
*/
|
||||
wait(promise) {
|
||||
if (!(promise instanceof Promise)) {
|
||||
promise = ResultAdapter.promise(promise);
|
||||
}
|
||||
return continuation.enabled ? promise.await() : promise.wait();
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {typeof Internal.ResultAdapter}
|
||||
*/
|
||||
module.exports = ResultAdapter;
|
||||
})();
|
||||
5
app/src/main/assets/modules/result_adapter.js
Normal file
5
app/src/main/assets/modules/result_adapter.js
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Reserved for legacy usage with old module name.
|
||||
* @type {typeof Internal.ResultAdapter}
|
||||
*/
|
||||
module.exports = require('result-adapter');
|
||||
Reference in New Issue
Block a user