Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 39 additions & 28 deletions fe/packages/render/src/core/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ class Runtime {
const { id, usingComponents, tplComponents } = pageModule.moduleInfo
this.pageId = pageId
const components = this.createComponent(path, bridgeId, usingComponents)
const self = this
const that = this
const rootCom = 'dd-page'
const sId = `data-v-${id}`
return {
Expand Down Expand Up @@ -248,15 +248,15 @@ class Runtime {
provide('bridgeId', bridgeId)
provide('path', path)
provide(path, {
id: self.pageId,
id: that.pageId,
})
provide('info', {
id: self.pageId,
id: that.pageId,
sId,
})
const instance = getCurrentInstance().proxy
instance.__page__ = true
self.setModuleInstance(self.pageId, instance)
that.setModuleInstance(that.pageId, instance)

let ticking = false
const handleScroll = () => {
Expand All @@ -267,7 +267,7 @@ class Runtime {
target: 'service',
body: {
bridgeId,
moduleId: self.pageId,
moduleId: that.pageId,
scrollTop: window.scrollY,
},
})
Expand All @@ -285,7 +285,7 @@ class Runtime {
target: 'service',
body: {
bridgeId,
moduleId: self.pageId,
moduleId: that.pageId,
},
})
})
Expand All @@ -296,9 +296,9 @@ class Runtime {
})

const data = reactive({})
self.setupData.set(self.pageId, data)
const initData = await message.wait(self.pageId)
self.applyInitialData(self.pageId, data, initData)
that.setupData.set(that.pageId, data)
const initData = await message.wait(that.pageId)
that.applyInitialData(that.pageId, data, initData)
return data
},
components,
Expand Down Expand Up @@ -386,7 +386,7 @@ class Runtime {
}

const components = {}
const self = this
const that = this
const newDepthChain = [...depthChain, path]

for (const [componentName, componentPath] of Object.entries(usingComponents)) {
Expand Down Expand Up @@ -417,7 +417,7 @@ class Runtime {
sId: parentInfo.sId,
})
const vueInstance = getCurrentInstance()
const vueParentId = self.getParentModuleId(vueInstance)
const vueParentId = that.getParentModuleId(vueInstance)
const parentId = vueParentId || parentInfo.id
const pageInfo = inject(path)
const pageId = pageInfo.id
Expand All @@ -433,7 +433,7 @@ class Runtime {
pageId,
})
const instance = vueInstance.proxy
self.setModuleInstance(moduleId, instance)
that.setModuleInstance(moduleId, instance)

const externalClasses = []
for (const [k, v] of Object.entries(module.props ?? {})) {
Expand Down Expand Up @@ -482,7 +482,7 @@ class Runtime {
_pendingResolved = true
_resolvePending?.()
}
self._pendingSetups.set(moduleId, new Promise(r => (_resolvePending = r)))
that._pendingSetups.set(moduleId, new Promise(r => (_resolvePending = r)))

onMounted(() => {
nextTick(() => {
Expand Down Expand Up @@ -523,16 +523,16 @@ class Runtime {
moduleId,
},
})
self.deleteModuleInstance(moduleId)
self.setupData.delete(moduleId)
self.initializedModules.delete(moduleId)
self.preInitUpdates.delete(moduleId)
self._pendingSetups.delete(moduleId)
that.deleteModuleInstance(moduleId)
that.setupData.delete(moduleId)
that.initializedModules.delete(moduleId)
that.preInitUpdates.delete(moduleId)
that._pendingSetups.delete(moduleId)
_pendingResolve()
})

const data = reactive({})
self.setupData.set(moduleId, data)
that.setupData.set(moduleId, data)
let skipInitialPropsNotify = true

watch(
Expand Down Expand Up @@ -572,9 +572,9 @@ class Runtime {
)

const initData = await message.wait(moduleId)
self._pendingSetups.delete(moduleId)
that._pendingSetups.delete(moduleId)
_pendingResolve()
self.applyInitialData(moduleId, data, initData)
that.applyInitialData(moduleId, data, initData)
return data
},
render: module.moduleInfo.render,
Expand Down Expand Up @@ -1317,13 +1317,24 @@ class Runtime {
)

const mimeType = fileType === 'jpg' || fileType === 'jpeg' ? 'image/jpeg' : 'image/png'
const tempFilePath = outputCanvas.toDataURL(mimeType, quality)
const result = {
errMsg: 'canvasToTempFilePath:ok',
tempFilePath,
}
this.triggerCallback(bridgeId, params.success, [result], result)
this.triggerCallback(bridgeId, params.complete, [result], result)
const dataURL = outputCanvas.toDataURL(mimeType, quality)

// Forward to Container to write base64 to a temp file and return a real file path
message.invoke({
type: 'invokeAPI',
target: 'container',
body: {
name: 'saveCanvasTempFile',
bridgeId,
params: {
dataURL,
fileType,
success: params.success,
fail: params.fail,
complete: params.complete,
},
},
})
}
catch (error) {
this.triggerCanvasFailure(bridgeId, params, `canvasToTempFilePath:fail ${error.message}`)
Expand Down
2 changes: 1 addition & 1 deletion fe/packages/service/src/api/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ function invokeMessage(name, params, target) {
}
}

function invokePromiseAPI(name, params, target) {
export function invokePromiseAPI(name, params, target) {
return new Promise((resolve, reject) => {
let successId
let failId
Expand Down
81 changes: 81 additions & 0 deletions fe/packages/service/src/api/core/ui/canvas/canvas-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,38 @@ function serializeCanvasArgs(args) {
return Array.from(args).map(arg => serializeCanvasArg(arg))
}

const BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
const BASE64_LOOKUP = new Uint8Array(128)
for (let i = 0; i < BASE64_CHARS.length; i++) {
BASE64_LOOKUP[BASE64_CHARS.charCodeAt(i)] = i
}

function base64ToUint8ClampedArray(base64) {
let end = base64.length
while (end > 0 && base64[end - 1] === '=') end--
const byteLen = (end * 3 / 4) | 0
const bytes = new Uint8ClampedArray(byteLen)
let j = 0
for (let i = 0; i < end; i += 4) {
const a = BASE64_LOOKUP[base64.charCodeAt(i)]
const b = BASE64_LOOKUP[base64.charCodeAt(i + 1)]
const c = BASE64_LOOKUP[base64.charCodeAt(i + 2)]
const d = BASE64_LOOKUP[base64.charCodeAt(i + 3)]
bytes[j++] = (a << 2) | (b >> 4)
if (j < byteLen) bytes[j++] = ((b & 0xF) << 4) | (c >> 2)
if (j < byteLen) bytes[j++] = ((c & 0x3) << 6) | d
}
return bytes
}

function deserializeImageData(res) {
return {
width: res.width,
height: res.height,
data: base64ToUint8ClampedArray(res.data),
}
}

function makeResourceId(prefix = 'canvas_resource') {
return `${prefix}_${uuid()}`
}
Expand Down Expand Up @@ -520,6 +552,16 @@ class CanvasRenderingContext2DProxy {
})
}

getImageData(x, y, w, h) {
return this.canvas.getImageData({
contextId: this.contextId, x, y, width: w, height: h,
})
}

toDataURL(type, quality) {
return this.canvas.toDataURL(type, quality)
}

call(method, args) {
if (method === 'measureText') {
return { width: String(args[0] ?? '').length * 10 }
Expand Down Expand Up @@ -748,6 +790,45 @@ export class CanvasNode {
})
}

getImageData({ contextId, x, y, width, height }) {
Comment thread
Hierifer marked this conversation as resolved.
return new Promise((resolve, reject) => {
const callbackId = callback.store((res) => {
try {
if (res.width && res.height && res.data) {
resolve(deserializeImageData(res))
} else {
reject(new Error('getImageData: invalid format'))
}
} catch (error) {
reject(error)
}
})
this.enqueueOperation({
op: 'getImageData',
contextId,
x,
y,
width,
height,
callback: callbackId,
})
})
}

toDataURL(type = 'image/png', quality) {
return new Promise((resolve) => {
const callbackId = callback.store((dataURL) => {
resolve(dataURL)
})
this.enqueueOperation({
op: 'toDataURL',
mimeType: type,
quality,
callback: callbackId,
})
})
}

enqueueOperation(operation) {
this.pendingOperations.push(operation)
if (this.flushScheduled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ class IntersectionObserver {
* https://developers.weixin.qq.com/miniprogram/dev/api/wxml/IntersectionObserver.observe.html
*/
observe(targetSelector, listener) {
const self = this
const that = this
const id = callback.store((res) => {
if (!self._disconnected) {
self._observerId = res.observerId
if (!that._disconnected) {
that._observerId = res.observerId
}
if (res.info) {
listener.call(self, res.info)
listener.call(that, res.info)
}
}, true)

Expand Down
8 changes: 4 additions & 4 deletions fe/packages/service/src/api/core/wxml/selector-query/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,21 @@ class SelectorQuery {
* @param {Function} callback
*/
exec(callback) {
const self = this
const that = this
const bridgeId = getCurrentBridgeId()
const data = {
tasks: this.__taskQueue,
success: (res) => {
const hydratedRes = hydrateSelectorQueryResult(res, bridgeId) || []
hydratedRes.forEach((nodeInfo, index) => {
const cb = self.__cbQueue[index]
const cb = that.__cbQueue[index]
if (isFunction(cb)) {
cb.call(self, nodeInfo)
cb.call(that, nodeInfo)
}
})

if (isFunction(callback)) {
callback.call(self, hydratedRes)
callback.call(that, hydratedRes)
}
},
}
Expand Down
8 changes: 4 additions & 4 deletions fe/packages/service/src/core/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ export { deepEqual }
* 只能在实例初始化完成后从框架运行时读取。目前通过 __mpxProxy 访问,
* 后续若框架侧暴露标准字段(如 moduleInfo.__computedKeys),可在此替换为更通用的读取方式。
*/
export function addComputedData(self) {
const computed = self.__mpxProxy?.options?.computed
export function addComputedData(ctx) {
const computed = ctx.__mpxProxy?.options?.computed
if (computed) {
for (const ck of Object.keys(computed)) {
if (!Object.prototype.hasOwnProperty.call(self.data, ck)) {
self.data[ck] = null
if (!Object.prototype.hasOwnProperty.call(ctx.data, ck)) {
ctx.data[ck] = null
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion harmony/dimina/src/main/cpp/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ std::string getJsValueString(JSContext *ctx, JSValueConst jsValue, int indentLev
} else if (JS_IsNumber(jsValue)) {
int tag = JS_VALUE_GET_TAG(jsValue);
if (tag == JS_TAG_INT) {
int value = jsValue.u.int32;
int value = JS_VALUE_GET_INT(jsValue);
output = std::to_string(value);
} else if (tag == JS_TAG_FLOAT64) {
double num;
Expand Down
2 changes: 2 additions & 0 deletions harmony/dimina/src/main/ets/Bridges/DMPAppModuleManager.ets
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { DMPContainerBridgesModuleBluetooth } from './DMPContainerBridgesModule+
import { DMPContainerBridgesModuleVideo } from './DMPContainerBridgesModule+Video'
import { DMPContainerBridgesModuleTabBar } from './DMPContainerBridgesModule+TabBar';
import { DMPContainerBridgesModuleFile } from './DMPContainerBridgesModule+File';
import { DMPContainerBridgesModuleCanvas } from './DMPContainerBridgesModule+Canvas';


export class DMPAppModuleManager extends DMPModuleManager {
Expand Down Expand Up @@ -101,6 +102,7 @@ export class DMPAppModuleManager extends DMPModuleManager {
this.registerModule(new DMPContainerBridgesModuleNavigationBar(app))
this.registerModule(new DMPContainerBridgesModuleNavigateToMiniProgram(app))
this.registerModule(new DMPContainerBridgesModuleTabBar(app))
this.registerModule(new DMPContainerBridgesModuleCanvas(app))
}
}

Expand Down
Loading
Loading