Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
427ed9399f | 3 weeks ago |
16 changed files with 306 additions and 190 deletions
@ -1,51 +1,87 @@ |
|||
// type FireKey = string
|
|||
// 从完整事件名称中提取原始事件名称(移除作用域前缀)
|
|||
type ExtractOriginalEventName<T extends string, S extends string> = T extends `${S}:${infer Original}` ? Original : never |
|||
|
|||
// 从完整事件映射中提取原始事件映射
|
|||
type ExtractBaseEventMaps<T extends Record<string, any>, S extends string> = { |
|||
[K in keyof T as ExtractOriginalEventName<K & string, S>]: T[K] |
|||
} |
|||
|
|||
type FireFN = (...argu: any[]) => void |
|||
|
|||
class FireEvent<T extends Record<string | symbol, FireFN>> { |
|||
#events: Record<keyof T, FireFN[]> = {} as any |
|||
// 支持作用域的事件类
|
|||
class ScopedFireEvent< |
|||
T extends Record<string, FireFN>, // 完整的事件映射类型
|
|||
S extends string, // 作用域类型
|
|||
B extends Record<string, FireFN> = ExtractBaseEventMaps<T, S>, // 从完整事件映射中提取的基础事件映射
|
|||
> { |
|||
#scope: S |
|||
#events: Record<string, FireFN[]> = {} |
|||
|
|||
constructor(scope: S) { |
|||
this.#scope = scope |
|||
} |
|||
|
|||
// 获取完整的事件名称(添加作用域前缀)
|
|||
public getFullEventName(eventName: string): string { |
|||
if (this.#scope === "") return eventName |
|||
return `${this.#scope}:${eventName}` |
|||
} |
|||
|
|||
print() { |
|||
Object.keys(this.#events).forEach(key => { |
|||
console.log(`${key}: ${this.#events[key]}\n`) |
|||
}) |
|||
} |
|||
on<S extends keyof T>(name: S, fn: T[S]) { |
|||
if (!this.#events[name]) { |
|||
this.#events[name] = [] |
|||
|
|||
// 订阅事件,支持自动添加作用域前缀
|
|||
on<K extends keyof B>(name: K, fn: B[K]) { |
|||
const fullName = this.getFullEventName(name as string) |
|||
if (!this.#events[fullName]) { |
|||
this.#events[fullName] = [] |
|||
} |
|||
this.#events[name].push(fn) |
|||
this.#events[fullName].push(fn as FireFN) |
|||
} |
|||
emit<S extends keyof T>(name: S, ...argu: Parameters<T[S]>) { |
|||
if (this.#events[name]) { |
|||
this.#events[name].forEach(fn => { |
|||
|
|||
// 触发事件,支持自动添加作用域前缀
|
|||
emit<K extends keyof B>(name: K, ...argu: Parameters<B[K]>) { |
|||
const fullName = this.getFullEventName(name as string) |
|||
if (this.#events[fullName]) { |
|||
this.#events[fullName].forEach(fn => { |
|||
fn(...argu) |
|||
}) |
|||
} |
|||
} |
|||
off<S extends keyof T>(name: S, fn?: T[S]) { |
|||
const len = this.#events[name].length |
|||
|
|||
// 取消订阅事件,支持自动添加作用域前缀
|
|||
off<K extends keyof B>(name: K, fn?: B[K]) { |
|||
const fullName = this.getFullEventName(name as string) |
|||
const len = this.#events[fullName]?.length || 0 |
|||
if (!len) { |
|||
return |
|||
} |
|||
if (!fn) { |
|||
this.#events[name] = [] |
|||
this.#events[fullName] = [] |
|||
} else { |
|||
for (let i = len - 1; i >= 0; i--) { |
|||
const _fn = this.#events[name][i] |
|||
const _fn = this.#events[fullName][i] |
|||
if (_fn === fn) { |
|||
this.#events[name].splice(i, 1) |
|||
this.#events[fullName].splice(i, 1) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
once<S extends keyof T>(name: S, fn: T[S]) { |
|||
const _fn: any = (...argu: any[]) => { |
|||
|
|||
// 一次性订阅事件,支持自动添加作用域前缀
|
|||
once<K extends keyof B>(name: K, fn: B[K]) { |
|||
const _fn: FireFN = (...argu: any[]) => { |
|||
fn(...argu) |
|||
this.off<S>(name, _fn) |
|||
this.off(name, _fn as B[K]) |
|||
} |
|||
this.on(name, _fn) |
|||
this.on(name, _fn as B[K]) |
|||
} |
|||
} |
|||
|
|||
export function buildEmitter<T extends Record<string | symbol, FireFN>>() { |
|||
return new FireEvent<T>() |
|||
// 创建作用域事件发射器的工厂函数 - 仅需一个泛型参数
|
|||
export function buildEmitter<T extends Record<string | symbol, FireFN>>(scope?: string): ScopedFireEvent<T, typeof scope> { |
|||
return new ScopedFireEvent<T, typeof scope>(scope) |
|||
} |
|||
|
@ -1,3 +0,0 @@ |
|||
export type EventMaps = { |
|||
"update-progress": (data: { percent: number; all: number; now: number }) => void |
|||
} |
@ -0,0 +1,16 @@ |
|||
export const EventScope = "updater" as const |
|||
|
|||
// 原始事件映射类型
|
|||
export type BaseEventMaps = { |
|||
"download-progress": (data: { percent: number; all: number; now: number }) => void |
|||
error: () => void |
|||
"checking-for-update": () => void |
|||
"update-available": () => void |
|||
"update-not-available": () => void |
|||
"update-downloaded": () => void |
|||
} |
|||
|
|||
// 将 EventScope 添加到所有事件名称前缀
|
|||
export type EventMaps = { |
|||
[K in keyof BaseEventMaps as `${typeof EventScope}:${K}`]: BaseEventMaps[K] |
|||
} |
@ -1,6 +1,6 @@ |
|||
import { broadcast } from "utils/main" |
|||
import { EventMaps } from "../common" |
|||
import { EventMaps, BaseEventMaps, EventScope } from "../events" |
|||
|
|||
export function emit(key: keyof EventMaps, ...args: Parameters<EventMaps[keyof EventMaps]>) { |
|||
broadcast(key, ...args) |
|||
export function emit(key: keyof BaseEventMaps, ...args: Parameters<EventMaps[keyof EventMaps]>) { |
|||
broadcast<EventMaps>(EventScope, key, ...args) |
|||
} |
|||
|
@ -1,16 +1,20 @@ |
|||
import { EventMaps } from "helper/updater/common" |
|||
import { EventMaps, EventScope } from "helper/updater/events" |
|||
import { defineStore } from "pinia" |
|||
import { Updater } from "." |
|||
|
|||
export const useSettingStore = defineStore( |
|||
export const useUpdateStore = defineStore( |
|||
"Updater", |
|||
() => { |
|||
getApi<EventMaps>().on("update-progress", (_, data) => { |
|||
getApi<EventMaps>().on(EventScope, "download-progress", (_, data) => { |
|||
console.log(data) |
|||
}) |
|||
|
|||
return {} |
|||
}, |
|||
{ |
|||
persist: false, |
|||
}, |
|||
) |
|||
|
|||
export const triggerHotUpdate = () => { |
|||
Updater.getInstance().triggerHotUpdate() |
|||
} |
|||
|
@ -1,7 +1,9 @@ |
|||
<script setup lang="ts"></script> |
|||
<script setup lang="ts"> |
|||
import { triggerHotUpdate } from "common/event/Updater/hook" |
|||
</script> |
|||
|
|||
<template> |
|||
<div h-full flex flex-col>sad</div> |
|||
<div h-full flex flex-col @click="triggerHotUpdate">sad</div> |
|||
</template> |
|||
|
|||
<style lang="scss" scoped></style> |
|||
|
Loading…
Reference in new issue