6.6.3 - Alpha5 - webview 元素支持基于 JsBridge 的 Web 页面布局 (Ref to Auto.js Pro) (issue #281)
This commit is contained in:
163
app/src/main/assets/modules/ui-ext.js
Normal file
163
app/src/main/assets/modules/ui-ext.js
Normal file
@@ -0,0 +1,163 @@
|
||||
( /* @ModuleIIFE */ () => {
|
||||
|
||||
// @Reference to module __ui__.js from Auto.js Pro 9.3.11 on May 24, 2025.
|
||||
|
||||
let JsBridge = (function () {
|
||||
let ResultAdapter = require('result-adapter');
|
||||
|
||||
let EVENT_REQUEST = '$autojs:internal:request';
|
||||
let EVENT_RESPONSE = '$autojs:internal:response';
|
||||
|
||||
function JavaScriptBridgeImpl(webview) {
|
||||
let self = this;
|
||||
events.__asEmitter__(self);
|
||||
self.nextId = 1;
|
||||
self.requestHandlers = new Map();
|
||||
self.webview = webview;
|
||||
webview.setJavascriptEventCallback({
|
||||
onWebJavaScriptEvent(event, args) {
|
||||
let obj = unwrapJson(args) || [];
|
||||
self.emit.apply(self, [ event, { name: event } ].concat(obj));
|
||||
},
|
||||
});
|
||||
self.on(EVENT_REQUEST, function (e, request) {
|
||||
let handler = self.requestHandlers.get(request.channel) ?? self.requestHandlers.get('');
|
||||
if (!handler) {
|
||||
self.sendResponseError(request, new Error('no handler for action: ' + request.channel));
|
||||
return;
|
||||
}
|
||||
let event = {
|
||||
channel: request.channel,
|
||||
arguments: request.args,
|
||||
};
|
||||
let result;
|
||||
try {
|
||||
result = handler.apply(void 0, [ event ].concat(event.arguments));
|
||||
} catch (e) {
|
||||
self.sendResponseError(request, e);
|
||||
return;
|
||||
}
|
||||
if (isPromise(result)) {
|
||||
result.then(function (r) {
|
||||
self.sendResponse(request, r);
|
||||
}).catch(function (err) {
|
||||
self.sendResponseError(request, err);
|
||||
});
|
||||
} else {
|
||||
self.sendResponse(request, result);
|
||||
}
|
||||
});
|
||||
return self;
|
||||
}
|
||||
|
||||
JavaScriptBridgeImpl.prototype.sendResponse = function (request, result, error) {
|
||||
this.send(EVENT_RESPONSE + ':' + request.id, {
|
||||
result: result,
|
||||
error: error,
|
||||
});
|
||||
};
|
||||
JavaScriptBridgeImpl.prototype.sendResponseError = function (request, error) {
|
||||
this.sendResponse(request, undefined, error.toString());
|
||||
};
|
||||
JavaScriptBridgeImpl.prototype.invoke = function (channel) {
|
||||
let self = this;
|
||||
let args = [];
|
||||
for (let _i = 1; _i < arguments.length; _i++) {
|
||||
args[_i - 1] = arguments[_i];
|
||||
}
|
||||
let id = this.nextId++;
|
||||
return new Promise(function (resolve, reject) {
|
||||
self.once(EVENT_RESPONSE + ':' + id, function (event, result) {
|
||||
if (result.error) {
|
||||
reject(new Error('Error occurred while handling invoke: channel = ' + channel + ', error = ' + result.error));
|
||||
} else {
|
||||
resolve(result.result);
|
||||
}
|
||||
});
|
||||
self.send(EVENT_REQUEST, {
|
||||
id: id,
|
||||
channel: channel,
|
||||
args: args,
|
||||
});
|
||||
});
|
||||
};
|
||||
JavaScriptBridgeImpl.prototype.send = function (event) {
|
||||
let args = [];
|
||||
for (let i = 1; i < arguments.length; i++) {
|
||||
args[i - 1] = arguments[i];
|
||||
}
|
||||
this.webview.sendEventToWebJavaScript(event, wrapJson(args));
|
||||
};
|
||||
JavaScriptBridgeImpl.prototype.handle = function (channel, handler) {
|
||||
this.requestHandlers.set(channel !== null && channel !== void 0 ? channel : '', handler);
|
||||
return this;
|
||||
};
|
||||
JavaScriptBridgeImpl.prototype.eval = function (code) {
|
||||
let self = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
ResultAdapter.promise(self.webview.__eval(code))
|
||||
.then(result => resolve(JSON.parse(String(result))))
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
};
|
||||
|
||||
function unwrapJson(maybeJson) {
|
||||
if (!maybeJson) {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.parse(maybeJson);
|
||||
}
|
||||
|
||||
function wrapJson(obj) {
|
||||
if (typeof obj === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
|
||||
function isPromise(obj) {
|
||||
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
|
||||
}
|
||||
|
||||
return JavaScriptBridgeImpl;
|
||||
})();
|
||||
|
||||
/**
|
||||
* @param {org.autojs.autojs.core.ui.widget.JsWebView} webview
|
||||
*/
|
||||
function initWebView(webview) {
|
||||
webview.jsBridge = new JsBridge(webview);
|
||||
let emitter = events.emitter();
|
||||
webview.events = emitter;
|
||||
webview.setSyncWebViewEventCallback({
|
||||
onSyncWebViewEvent(event) {
|
||||
dispatchJavaEvent(event, emitter);
|
||||
},
|
||||
});
|
||||
webview.setSyncEventEnabled('', true);
|
||||
|
||||
function dispatchJavaEvent(event, emitter) {
|
||||
let eventName = event.getName();
|
||||
let args = Array.from(event.getArguments());
|
||||
let _returnValue;
|
||||
let returnValueSet = false;
|
||||
let e = {
|
||||
name: eventName,
|
||||
arguments: args,
|
||||
consumed: false,
|
||||
};
|
||||
Object.defineProperty(e, 'returnValue', {
|
||||
get: function () {
|
||||
return _returnValue;
|
||||
},
|
||||
set: function (value) {
|
||||
_returnValue = value;
|
||||
returnValueSet = true;
|
||||
},
|
||||
});
|
||||
emitter.emit.apply(emitter, [ eventName, e ].concat(args));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = initWebView;
|
||||
})();
|
||||
90
app/src/main/assets/web/dist/autojs.sdk.v1.js
vendored
Normal file
90
app/src/main/assets/web/dist/autojs.sdk.v1.js
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
'use strict';
|
||||
|
||||
( /* @IIFE */ () => {
|
||||
|
||||
// @Reference to .../asset/web/dist/autojs.sdk.v1.js from Auto.js Pro 9.3.11 on May 24, 2025.
|
||||
|
||||
const EVENT_RESPONSE = '$autojs:internal:response';
|
||||
const EVENT_REQUEST = '$autojs:internal:request';
|
||||
|
||||
// noinspection JSValidateTypes
|
||||
/** @type {import('events')} */
|
||||
let nodejsEvents = events;
|
||||
|
||||
let nextId = 1;
|
||||
|
||||
let helper = {
|
||||
isPromise: o => o && typeof o.then === 'function',
|
||||
unwrapJson: o => o ? JSON.parse(o) : undefined,
|
||||
wrapJson: o => o === undefined ? o : JSON.stringify(o),
|
||||
};
|
||||
|
||||
Object.setPrototypeOf($autojs, new nodejsEvents.EventEmitter());
|
||||
|
||||
/** @type {Internal.AutoJsBridge} */
|
||||
let AutoJsBridge = {
|
||||
requestHandlers: {},
|
||||
onEventInternal(event, args) {
|
||||
this.emit(event, ...helper.unwrapJson(args));
|
||||
},
|
||||
send(event, ...args) {
|
||||
this.sendEventInternal(event, helper.wrapJson(args));
|
||||
},
|
||||
invoke(channel, ...args) {
|
||||
let id = nextId++;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.once(EVENT_RESPONSE + ':' + id, (result) => {
|
||||
if (result.error) {
|
||||
reject(new Error('Error occurred while handling invoke: channel = ' + channel + ', error = ' + result.error));
|
||||
} else {
|
||||
resolve(result.result);
|
||||
}
|
||||
});
|
||||
this.send(EVENT_REQUEST, {
|
||||
id, channel, args,
|
||||
});
|
||||
});
|
||||
},
|
||||
/** @this {Internal.AutoJsBridge} */
|
||||
handle(channel, handler) {
|
||||
this.requestHandlers[channel || ''] = handler;
|
||||
return this;
|
||||
},
|
||||
removeHandler(channel) {
|
||||
delete this.requestHandlers[channel];
|
||||
},
|
||||
handleRequest(request) {
|
||||
let handler = this.requestHandlers[request.channel] || this.requestHandlers[''];
|
||||
if (!handler) {
|
||||
return;
|
||||
}
|
||||
let event = {
|
||||
channel: request.channel,
|
||||
arguments: request.args,
|
||||
};
|
||||
let result;
|
||||
try {
|
||||
result = handler(event, ...event.arguments);
|
||||
} catch (e) {
|
||||
this.sendResponse(request, undefined, e);
|
||||
return;
|
||||
}
|
||||
if (helper.isPromise(request)) {
|
||||
result.then((r) => {
|
||||
this.sendResponse(request, r);
|
||||
}).catch((err) => {
|
||||
this.sendResponse(request, undefined, err);
|
||||
});
|
||||
} else {
|
||||
this.sendResponse(request, result);
|
||||
}
|
||||
},
|
||||
sendResponse(request, result, error) {
|
||||
this.send(EVENT_RESPONSE + ':' + request.id, { result, error });
|
||||
},
|
||||
};
|
||||
|
||||
$autojs = Object.assign($autojs, AutoJsBridge);
|
||||
$autojs.on(EVENT_REQUEST, AutoJsBridge.handleRequest.bind($autojs));
|
||||
|
||||
})();
|
||||
23
app/src/main/assets/web/dist/events.min@3.3.0.js
vendored
Normal file
23
app/src/main/assets/web/dist/events.min@3.3.0.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user