diff --git a/.editorconfig b/.editorconfig index ffe9a1f..7b587a2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,7 +4,7 @@ root = true end_of_line = lf insert_final_newline = true -[*.{js,json,yml}] +[*.{json,yml,css,ts,tsx}] charset = utf-8 indent_style = space indent_size = 4 diff --git a/package.json b/package.json index bd04c3c..2e8f6ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "qqntim-plugin-template", + "name": "qqntim-plugin-wallpaper", "private": true, - "version": "2.0.0", + "version": "1.0.0", "packageManager": "yarn@3.6.1", "license": "MIT", "scripts": { diff --git a/publish/qqntim.json b/publish/qqntim.json index 8f560fc..750e734 100644 --- a/publish/qqntim.json +++ b/publish/qqntim.json @@ -1,8 +1,8 @@ { "manifestVersion": "3.0", - "id": "template-plugin", - "name": "QQNTim 模板插件", - "description": "快速开始开发你自己的插件。", + "id": "wallpaper", + "name": "壁纸插件", + "description": "自定义你的 QQNT 背景。", "version": "1.0.0", "author": "Flysoft", "injections": [ diff --git a/publish/style.css b/publish/style.css index 4ee87da..1d9459a 100644 --- a/publish/style.css +++ b/publish/style.css @@ -1,2 +1,28 @@ -/* Put your stylesheet here. */ - +.wallpaper { + background-color: #000000 !important; +} +.wallpaper-fit { + background-size: contain !important; + background-position: center !important; + background-repeat: no-repeat !important; +} +.wallpaper-tile { + background-size: auto !important; + background-position: 0 0 !important; + background-repeat: repeat !important; +} +.wallpaper-center { + background-size: auto !important; + background-position: center !important; + background-repeat: no-repeat !important; +} +.wallpaper-fill { + background-size: cover !important; + background-position: center !important; + background-repeat: no-repeat !important; +} +.wallpaper-stretch { + background-size: 100% 100% !important; + background-position: center !important; + background-repeat: no-repeat !important; +} diff --git a/src/config.ts b/src/config.ts index 5c49c60..4cbf1bc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,20 +1,25 @@ -export const id = "my-template-plugin" as const; +export const id = "wallpaper-plugin" as const; export const defaults: PluginConfig = { - switchConfigItem: false, - anotherSwitchConfigItem: false, - inputConfigItem: "默认值", - dropdownConfigItem: "A", + wallpapers: [], + duration: 120, + position: "fill", }; export function getPluginConfig(config: Config | undefined) { return Object.assign({}, defaults, config?.[id] || {}); } +export interface Wallpaper { + source: "none" | "file" | "dir" | "url" | "script"; + files: string[]; + dirs: string[]; + urls: string[]; + script: string; +} export interface PluginConfig { - switchConfigItem: boolean; - anotherSwitchConfigItem: boolean; - inputConfigItem: string; - dropdownConfigItem: "A" | "B" | "C"; + wallpapers: Wallpaper[]; + duration: 30 | 60 | 120 | 300 | 600 | 1800 | 3600; + position: "fit" | "tile" | "center" | "fill" | "stretch"; } export type Config = { [X in typeof id]?: Partial; diff --git a/src/renderer.ts b/src/renderer.ts index 9bfc233..06d9f51 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -1,10 +1,72 @@ -import { getPluginConfig } from "./config"; +import { PluginConfig, Wallpaper, getPluginConfig } from "./config"; +import { s } from "./utils/sep"; import * as qqntim from "qqntim/renderer"; +const { fs } = qqntim.modules; export default class Entry implements QQNTim.Entry.Renderer { + private config: PluginConfig; constructor() { - const config = getPluginConfig(qqntim.env.config.plugins.config); - console.log("[Template] Hello world!", qqntim); - console.log("[Template] 当前插件配置:", config); + this.config = getPluginConfig(qqntim.env.config.plugins.config); + } + private pathToURL(file: string) { + return encodeURI(`appimg://${file.replaceAll(s, "/")}`); + } + private async fileToURLs(files: string[]) { + return ( + await Promise.all( + files.map(async (file) => { + if (!(await fs.exists(file)) || !(await fs.stat(file)).isFile()) return; + return this.pathToURL(file); + }), + ) + ).filter(Boolean) as string[]; + } + private async dirToURLs(dirs: string[]) { + const urls: string[] = []; + await Promise.all( + dirs.map(async (dir) => { + if (!(await fs.exists(dir)) || !(await fs.stat(dir)).isDirectory()) return; + urls.push( + ...(( + await Promise.all( + ( + await fs.readdir(dir) + ).map(async (item) => { + const path = `${dir}${s}${item}`; + if ((await fs.exists(path)) && (await fs.stat(path)).isFile()) return this.pathToURL(path); + }), + ) + ).filter(Boolean) as string[]), + ); + }), + ); + return urls; + } + private async getWallpaperURLs(wallpaper: Wallpaper) { + const urls: string[] = []; + if (wallpaper.source == "file" && wallpaper.files) urls.push(...(await this.fileToURLs(wallpaper.files))); + else if (wallpaper.source == "dir" && wallpaper.dirs) urls.push(...(await this.dirToURLs(wallpaper.dirs))); + else if (wallpaper.source == "url" && wallpaper.urls) urls.push(...wallpaper.urls); + else if (wallpaper.source == "script" && wallpaper.script) urls.push(...(await new Function(wallpaper.script)())); + return urls; + } + onWindowLoaded(): void { + document.body.classList.add(`wallpaper-${this.config.position}`); + + const urls: string[] = []; + let currentIdx = 0; + + Promise.all(this.config.wallpapers.map(async (wallpaper) => urls.push(...(await this.getWallpaperURLs(wallpaper))))).then(() => { + if (urls.length == 0) return; + + const renderWallpaper = () => { + document.body.style.backgroundImage = `url(${urls[currentIdx]})`; + currentIdx++; + if (currentIdx >= urls.length) currentIdx = 0; + }; + + setInterval(renderWallpaper, this.config.duration * 1000); + renderWallpaper(); + }); } } diff --git a/src/settings.tsx b/src/settings.tsx index 53cdab9..40991d7 100644 --- a/src/settings.tsx +++ b/src/settings.tsx @@ -1,51 +1,157 @@ +import { Wallpaper } from "./config"; import { usePluginConfig } from "./utils/hooks"; import { defineSettingsPanels } from "qqntim-settings"; -import { Dropdown, Input, SettingsBox, SettingsBoxItem, SettingsSection, Switch } from "qqntim-settings/components"; -import { env } from "qqntim/renderer"; -import { useMemo } from "react"; -import { getPluginConfig } from "./config"; +import { Button, Dropdown, Input, SettingsBox, SettingsBoxItem, SettingsSection, Switch } from "qqntim-settings/components"; +import { dialog } from "qqntim/renderer"; export default class Entry implements QQNTim.Entry.Renderer { constructor() { // 如果不需要设置界面,将下一行注释掉即可;如果需要在设置项目旁边加一个小图标,请将 `undefined` 改为一段 HTML 代码(可以是 ``, `` 等等)。 - defineSettingsPanels(["模板插件设置", SettingsPanel, undefined]); + defineSettingsPanels(["壁纸插件", SettingsPanel, undefined]); } } function SettingsPanel({ config: _config, setConfig: _setConfig }: QQNTim.Settings.PanelProps) { const [pluginConfig, setPluginConfig] = usePluginConfig(_config, _setConfig); - const currentPluginConfigString = useMemo(() => JSON.stringify(getPluginConfig(env.config.plugins.config)), []); return ( <> - + { + setPluginConfig("wallpapers", [...pluginConfig.wallpapers, { source: "none", files: [], dirs: [], urls: [], script: "" }]); + }} + primary={false} + small={true} + > + 增加新壁纸源 + , + ]} + > - - - setPluginConfig("switchConfigItem", state)} /> - - {pluginConfig.switchConfigItem && ( - - setPluginConfig("anotherSwitchConfigItem", state)} /> - - )} - + setPluginConfig("dropdownConfigItem", state)} + selected={pluginConfig.position} + onChange={(state) => setPluginConfig("position", state)} width="150px" /> - - setPluginConfig("inputConfigItem", state)} /> + + setPluginConfig("duration", state)} + width="150px" + /> + {pluginConfig.wallpapers.map((wallpaper, idx) => { + const setWallpaper = (key: T, value: Wallpaper[T]) => + setPluginConfig( + "wallpapers", + pluginConfig.wallpapers.map((currentWallpaper, currentIdx) => (currentIdx == idx ? { ...currentWallpaper, [key]: value } : currentWallpaper)), + ); + return ( + + key={idx} + title={`壁纸 ${idx + 1}`} + buttons={[ + , + ]} + > + + setWallpaper("source", state)} + width="150px" + /> + + {wallpaper.source == "file" && ( + + + + + )} + {wallpaper.source == "dir" && ( + + + + + )} + {wallpaper.source == "url" && ( + + setWallpaper("urls", state.split("\n"))} /> + + )} + {wallpaper.source == "script" && ( + res.json()).then((data)=>data.urls);"]}> + setWallpaper("script", state)} /> + + )} + + ); + })} ); } diff --git a/src/utils/sep.ts b/src/utils/sep.ts new file mode 100644 index 0000000..cefd995 --- /dev/null +++ b/src/utils/sep.ts @@ -0,0 +1 @@ +export { sep as s } from "path"; diff --git a/yarn.lock b/yarn.lock index f1fbb19..cc5cbaf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1277,9 +1277,9 @@ __metadata: languageName: node linkType: hard -"qqntim-plugin-template@workspace:.": +"qqntim-plugin-wallpaper@workspace:.": version: 0.0.0-use.local - resolution: "qqntim-plugin-template@workspace:." + resolution: "qqntim-plugin-wallpaper@workspace:." dependencies: "@flysoftbeta/qqntim-typings": ^3.1.2 "@types/node": ^20.4.2