mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-28 12:30:12 +02:00
feat(composer_hooks): opera download button
This commit is contained in:
parent
69e5ca74ee
commit
f830ce13c6
@ -9,51 +9,130 @@ if (config.composerLogs) {
|
||||
console.info("loader.js loaded");
|
||||
}
|
||||
|
||||
if (config.bypassCameraRollLimit) {
|
||||
(module => {
|
||||
module.MultiSelectClickHandler = new Proxy(module.MultiSelectClickHandler, {
|
||||
construct: function(target, args, newTarget) {
|
||||
args[1].selectionLimit = 9999999;
|
||||
return Reflect.construct(target, args, newTarget);
|
||||
},
|
||||
});
|
||||
})(require('memories_ui/src/clickhandlers/MultiSelectClickHandler'))
|
||||
// Composer imports
|
||||
|
||||
const jsx = require('composer_core/src/JSX').jsx;
|
||||
const assetCatalog = require("composer_core/src/AssetCatalog")
|
||||
const style = require("composer_core/src/Style");
|
||||
const colors = require("coreui/src/styles/semanticColors");
|
||||
|
||||
function dumpObject(obj, indent = 0) {
|
||||
if (typeof obj !== "object") return console.log(obj);
|
||||
let prefix = ""
|
||||
for (let i = 0; i < indent; i++) {
|
||||
prefix += " ";
|
||||
}
|
||||
for (let key of Object.keys(obj)) {
|
||||
try {
|
||||
console.log(prefix, key, typeof obj[key], obj[key]);
|
||||
if (key == "renderer") continue
|
||||
if (typeof obj[key] === "object" && indent < 10) dumpObject(obj[key], indent + 1);
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(module => {
|
||||
function onComponentPreRender(component, viewModel) {
|
||||
const componentName = component.constructor.name;
|
||||
function proxyProperty(module, functionName, handler) {
|
||||
if (!module || !module[functionName]) {
|
||||
console.warn("Function not found", functionName);
|
||||
return;
|
||||
}
|
||||
module[functionName] = new Proxy(module[functionName], {
|
||||
apply: (a, b, c) => handler(a, b, c),
|
||||
construct: (a, b, c) => handler(a, b, c)
|
||||
});
|
||||
}
|
||||
|
||||
if (componentName == "ProfileIdentityView" && config.showFirstCreatedUsername) {
|
||||
let userInfo = callExport("getFriendInfoByUsername", viewModel.username);
|
||||
function interceptComponent(moduleName, className, functions) {
|
||||
proxyProperty(require(moduleName), className, (target, args, newTarget) => {
|
||||
let initProxy = functions["<init>"]
|
||||
let component;
|
||||
|
||||
if (userInfo) {
|
||||
let userInfoJson = JSON.parse(userInfo);
|
||||
let firstCreatedUsername = userInfoJson.username.split("|")[0];
|
||||
if (firstCreatedUsername != viewModel.username) {
|
||||
viewModel.username += " (" + firstCreatedUsername + ")";
|
||||
if (initProxy) {
|
||||
initProxy(args, (newArgs) => {
|
||||
component = Reflect.construct(target, newArgs || args, newTarget);
|
||||
});
|
||||
} else {
|
||||
component = Reflect.construct(target, args, newTarget);
|
||||
}
|
||||
|
||||
for (let funcName of Object.keys(functions)) {
|
||||
if (funcName == "<init>" || !component[funcName]) continue
|
||||
proxyProperty(component, funcName, (target, thisArg, argumentsList) => {
|
||||
let result;
|
||||
try {
|
||||
functions[funcName](component, argumentsList, (newArgs) => {
|
||||
result = Reflect.apply(target, thisArg, newArgs || argumentsList);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Error in", funcName, e);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
return component;
|
||||
})
|
||||
}
|
||||
|
||||
if (config.bypassCameraRollLimit) {
|
||||
interceptComponent(
|
||||
'memories_ui/src/clickhandlers/MultiSelectClickHandler',
|
||||
'MultiSelectClickHandler',
|
||||
{
|
||||
"<init>": (args, superCall) => {
|
||||
args[1].selectionLimit = 9999999;
|
||||
superCall();
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function onComponentPostRender(component, viewModel) {
|
||||
}
|
||||
if (config.operaDownloadButton) {
|
||||
const downloadIcon = assetCatalog.loadCatalog("share_sheet/res").downloadIcon
|
||||
|
||||
module.Component = new Proxy(module.Component, {
|
||||
construct: function(target, args, newTarget) {
|
||||
let component = Reflect.construct(target, args, newTarget);
|
||||
component.onRender = new Proxy(component.onRender, {
|
||||
apply: function(target, thisArg, argumentsList) {
|
||||
if (onComponentPreRender(component, thisArg.viewModel || {})) return;
|
||||
let result = Reflect.apply(target, thisArg, argumentsList);
|
||||
onComponentPostRender(component, thisArg.viewModel || {});
|
||||
return result;
|
||||
}
|
||||
});
|
||||
return component;
|
||||
interceptComponent(
|
||||
'context_chrome_header/src/ChromeHeaderRenderer',
|
||||
'ChromeHeaderRenderer',
|
||||
{
|
||||
onRenderBaseHeader: (component, args, render) => {
|
||||
render()
|
||||
jsx.beginRender(jsx.makeNodePrototype("image"))
|
||||
jsx.setAttributeStyle("style", new style.Style({
|
||||
height: 32,
|
||||
marginTop: 4,
|
||||
marginLeft: 8,
|
||||
marginRight: 12,
|
||||
objectFit: "contain",
|
||||
tint: colors.SemanticColor.Icon.PRIMARY
|
||||
}))
|
||||
jsx.setAttribute("src", downloadIcon)
|
||||
jsx.setAttributeFunction("onTap", () => callExport("downloadLastOperaMedia", false))
|
||||
jsx.setAttributeFunction("onLongPress", () => callExport("downloadLastOperaMedia", true))
|
||||
jsx.endRender()
|
||||
}
|
||||
}
|
||||
})
|
||||
})(require('composer_core/src/Component'))
|
||||
)
|
||||
}
|
||||
|
||||
if (config.showFirstCreatedUsername) {
|
||||
interceptComponent(
|
||||
'common_profile/src/identity/ProfileIdentityView',
|
||||
'ProfileIdentityView',
|
||||
{
|
||||
onRender: (component, _, render) => {
|
||||
if (component.viewModel) {
|
||||
let userInfo = callExport("getFriendInfoByUsername", component.viewModel.username);
|
||||
if (userInfo) {
|
||||
let userInfoJson = JSON.parse(userInfo);
|
||||
let firstCreatedUsername = userInfoJson.username.split("|")[0];
|
||||
if (firstCreatedUsername != component.viewModel.username) {
|
||||
component.viewModel.username += " (" + firstCreatedUsername + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
render();
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import me.rhunk.snapenhance.common.ui.createComposeAlertDialog
|
||||
import me.rhunk.snapenhance.common.ui.createComposeView
|
||||
import me.rhunk.snapenhance.core.features.Feature
|
||||
import me.rhunk.snapenhance.core.features.FeatureLoadParams
|
||||
import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader
|
||||
import me.rhunk.snapenhance.core.util.hook.HookStage
|
||||
import me.rhunk.snapenhance.core.util.hook.Hooker
|
||||
import me.rhunk.snapenhance.core.util.hook.hook
|
||||
@ -131,12 +132,13 @@ class ComposerHooks: Feature("ComposerHooks", loadParams = FeatureLoadParams.ACT
|
||||
}
|
||||
|
||||
private fun getConfig(): Map<String, Any> {
|
||||
return HashMap<String, Any>().apply {
|
||||
put("bypassCameraRollLimit", config.bypassCameraRollLimit.get())
|
||||
put("showFirstCreatedUsername", config.showFirstCreatedUsername.get())
|
||||
put("composerConsole", config.composerConsole.get())
|
||||
put("composerLogs", config.composerLogs.get())
|
||||
}
|
||||
return mapOf<String, Any>(
|
||||
"operaDownloadButton" to context.config.downloader.operaDownloadButton.get(),
|
||||
"bypassCameraRollLimit" to config.bypassCameraRollLimit.get(),
|
||||
"showFirstCreatedUsername" to config.showFirstCreatedUsername.get(),
|
||||
"composerConsole" to config.composerConsole.get(),
|
||||
"composerLogs" to config.composerLogs.get()
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleExportCall(composerMarshaller: ComposerMarshaller): Boolean {
|
||||
@ -150,6 +152,7 @@ class ComposerHooks: Feature("ComposerHooks", loadParams = FeatureLoadParams.ACT
|
||||
if (argc < 2) return false
|
||||
context.shortToast(composerMarshaller.getUntyped(1) as? String ?: return false)
|
||||
}
|
||||
"downloadLastOperaMedia" -> context.feature(MediaDownloader::class).downloadLastOperaMediaAsync(composerMarshaller.getUntyped(1) == true)
|
||||
"getFriendInfoByUsername" -> {
|
||||
if (argc < 2) return false
|
||||
val username = composerMarshaller.getUntyped(1) as? String ?: return false
|
||||
@ -176,16 +179,6 @@ class ComposerHooks: Feature("ComposerHooks", loadParams = FeatureLoadParams.ACT
|
||||
"error" -> context.log.error(message, tag)
|
||||
}
|
||||
}
|
||||
"eval" -> {
|
||||
if (argc < 2) return false
|
||||
runCatching {
|
||||
composerMarshaller.pushUntyped(context.native.composerEval(
|
||||
composerMarshaller.getUntyped(1) as? String ?: return false
|
||||
))
|
||||
}.onFailure {
|
||||
composerMarshaller.pushUntyped(it.toString())
|
||||
}
|
||||
}
|
||||
else -> context.log.warn("Unknown action: $action", "Composer")
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user