import { settings } from '@/core/settings'
import { deleteValue } from '@/core/utils'
/** 自定义样式注入模式 */
export enum UserStyleMode {
/** 组件加载完成后注入至
末尾 */
Default = 'default',
/** 随首屏样式注入 */
Instant = 'instant',
/** 组件加载完成后注入至末尾 */
Important = 'important',
}
/** 自定义样式定义 */
export interface UserStyle {
/** 名称 */
name: string
/** 样式内容 */
style: string
/** 显示名称, 默认与`name`相同 */
displayName?: string
/** 注入模式, 默认为`CustomStyleMode.default` */
mode?: UserStyleMode
}
export const styles: Required[] = Object.values(settings.userStyles)
/**
* 安装自定义样式
* @param input 自定义样式数据
*/
export const installStyle = async (input: UserStyle | string) => {
try {
let userStyle: UserStyle
const { loadFeatureCode } = await import('@/core/external-input')
if (typeof input === 'string') {
userStyle = loadFeatureCode(input) as UserStyle
} else {
userStyle = input
}
const { name, style, displayName, mode } = userStyle
const { removeStyle, addImportantStyle, addStyle } = await import('@/core/style')
const existingStyle = settings.userStyles[name]
if (existingStyle) {
Object.assign(existingStyle, userStyle)
removeStyle(name)
} else {
const newStyle = {
displayName: name,
mode: UserStyleMode.Default,
...userStyle,
}
settings.userStyles[name] = newStyle
styles.push(newStyle)
}
if (mode === UserStyleMode.Important) {
addImportantStyle(style, name)
} else {
addStyle(style, name)
}
return {
metadata: userStyle,
message: `已安装样式'${displayName || name}'`,
}
} catch (e) {
throw new Error('无效的样式代码', { cause: e })
}
}
/**
* 卸载自定义样式
* @param nameOrDisplayName 样式的名称(`name`或`displayName`)
*/
export const uninstallStyle = async (nameOrDisplayName: string) => {
const existingStyle = Object.entries(settings.userStyles).find(([name, { displayName }]) => {
if (name === nameOrDisplayName || displayName === nameOrDisplayName) {
return true
}
return false
})
if (!existingStyle) {
throw new Error(`没有找到与名称'${nameOrDisplayName}'相关联的样式`)
}
const { removeStyle } = await import('@/core/style')
const [name, { displayName }] = existingStyle
removeStyle(name)
delete settings.userStyles[name]
deleteValue(styles, it => it.name === name)
return {
metadata: existingStyle,
message: `已卸载样式'${displayName}'`,
}
}