mirror of https://github.com/veypi/OneAuth.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.0 KiB
TypeScript
117 lines
3.0 KiB
TypeScript
/*
|
|
* proxy.ts
|
|
* Copyright (C) 2024 veypi <i@veypi.com>
|
|
* 2024-10-23 17:20
|
|
* Distributed under terms of the GPL license.
|
|
*/
|
|
|
|
type voidFn = () => void
|
|
// TODO: 没有删除机制
|
|
const callbackCache: voidFn[] = []
|
|
const cacheUpdateList: number[] = []
|
|
// 界面响应频率40hz
|
|
setInterval(() => {
|
|
let list = new Set(cacheUpdateList.splice(0))
|
|
for (let l of list) {
|
|
callbackCache[l]()
|
|
}
|
|
}, 25)
|
|
|
|
function generateUniqueId() {
|
|
const timestamp = performance.now().toString(36);
|
|
const random = Math.random().toString(36).substring(2, 5);
|
|
return `${timestamp}-${random}`;
|
|
}
|
|
|
|
function ForceUpdate() {
|
|
for (let c of callbackCache) {
|
|
c()
|
|
}
|
|
}
|
|
|
|
var listen_tags: number[] = []
|
|
function Listen(callback: voidFn) {
|
|
listen_tags.push(callbackCache.length)
|
|
callbackCache.push(callback)
|
|
callback()
|
|
listen_tags.pop()
|
|
}
|
|
|
|
const isProxy = Symbol("isProxy")
|
|
const DataID = Symbol("DataID")
|
|
|
|
function Watch<T extends Object>(data: T) {
|
|
const did = generateUniqueId()
|
|
let isArray = false
|
|
if (Object.prototype.toString.call(data) === '[object Array]') {
|
|
isArray = true
|
|
}
|
|
// console.log(`watch ${did} ${isArray}`, data)
|
|
const listeners: { [key: string | symbol]: number[] } = {}
|
|
const handler = {
|
|
get(target: Object, key: string | symbol, receiver: any) {
|
|
if (key === isProxy) {
|
|
return true
|
|
}
|
|
if (key === DataID) {
|
|
return did
|
|
}
|
|
const value = Reflect.get(target, key, receiver)
|
|
if (typeof value === 'object' && value !== null) {
|
|
if (value[isProxy]) {
|
|
return value
|
|
} else {
|
|
let newValue = Watch(value)
|
|
Reflect.set(target, key, newValue, receiver)
|
|
return newValue
|
|
}
|
|
}
|
|
let idx = -1
|
|
if (listen_tags.length > 0) {
|
|
let lkey = key
|
|
idx = listen_tags[listen_tags.length - 1]
|
|
if (isArray) {
|
|
lkey = ''
|
|
}
|
|
if (!listeners[lkey]) {
|
|
listeners[lkey] = [idx]
|
|
} else if (listeners[lkey].indexOf(idx) == -1) {
|
|
listeners[lkey].push(idx)
|
|
}
|
|
}
|
|
// console.log(`${did} get ${key.toString()}:${value} ${idx}`)
|
|
return value;
|
|
},
|
|
set(target: Object, key: string | symbol, newValue: any, receiver: any) {
|
|
// console.log(`${did} set ${key.toString()} ${newValue}`)
|
|
const result = Reflect.set(target, key, newValue, receiver);
|
|
if (result) {
|
|
let lkey = key
|
|
if (isArray) {
|
|
lkey = ''
|
|
}
|
|
if (listeners[lkey]) {
|
|
for (let cb of listeners[lkey]) {
|
|
cacheUpdateList.push(cb)
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
deleteProperty(target: Object, key: string) {
|
|
// console.log(`del ${key}`)
|
|
const result = Reflect.deleteProperty(target, key);
|
|
if (result) {
|
|
}
|
|
return result
|
|
}
|
|
};
|
|
|
|
let res = new Proxy<T>(data, handler);
|
|
// Symbol(Symbol.toStringTag)
|
|
// res[Symbol.toStringTag] = 'Proxy'
|
|
return res
|
|
}
|
|
|
|
export default { Watch, Listen, ForceUpdate, DataID, generateUniqueId }
|