This repository has been archived by the owner on Jul 25, 2023. It is now read-only.
generated from Flysoft-Studio/QQNTim-Plugin-Template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4240454
commit 69d3ac9
Showing
9 changed files
with
247 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 代码(可以是 `<svg>`, `<img>` 等等)。 | ||
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 ( | ||
<> | ||
<SettingsSection title="插件设置"> | ||
<SettingsSection | ||
title="插件设置" | ||
buttons={[ | ||
<Button | ||
onClick={() => { | ||
setPluginConfig("wallpapers", [...pluginConfig.wallpapers, { source: "none", files: [], dirs: [], urls: [], script: "" }]); | ||
}} | ||
primary={false} | ||
small={true} | ||
> | ||
增加新壁纸源 | ||
</Button>, | ||
]} | ||
> | ||
<SettingsBox> | ||
<SettingsBoxItem title="当前生效的插件配置:" description={[currentPluginConfigString]} /> | ||
<SettingsBoxItem title="开关" description={["这是一个开关。", `当前状态为:${pluginConfig.switchConfigItem ? "开" : "关"}`]}> | ||
<Switch checked={pluginConfig.switchConfigItem} onToggle={(state) => setPluginConfig("switchConfigItem", state)} /> | ||
</SettingsBoxItem> | ||
{pluginConfig.switchConfigItem && ( | ||
<SettingsBoxItem title="另一个开关" description={["这是另一个开关。", `当前状态为:${pluginConfig.anotherSwitchConfigItem ? "开" : "关"}`]}> | ||
<Switch checked={pluginConfig.anotherSwitchConfigItem} onToggle={(state) => setPluginConfig("anotherSwitchConfigItem", state)} /> | ||
</SettingsBoxItem> | ||
)} | ||
<SettingsBoxItem title="下拉菜单" description={["这是一个下拉菜单。", `当前状态为:${pluginConfig.dropdownConfigItem}`]}> | ||
<SettingsBoxItem title="位置" description={["指定壁纸的定位方式。"]}> | ||
<Dropdown | ||
items={[ | ||
["A" as const, "我是 A 选项"], | ||
["B" as const, "我是 B 选项"], | ||
["C" as const, "我是 C 选项"], | ||
["fit" as const, "适应"], | ||
["tile" as const, "平铺"], | ||
["center" as const, "居中"], | ||
["fill" as const, "填充"], | ||
["stretch" as const, "拉伸"], | ||
]} | ||
selected={pluginConfig.dropdownConfigItem} | ||
onChange={(state) => setPluginConfig("dropdownConfigItem", state)} | ||
selected={pluginConfig.position} | ||
onChange={(state) => setPluginConfig("position", state)} | ||
width="150px" | ||
/> | ||
</SettingsBoxItem> | ||
<SettingsBoxItem title="输入框" description={["这是一个输入框。", `当前状态为:${pluginConfig.inputConfigItem}`]} isLast={true}> | ||
<Input value={pluginConfig.inputConfigItem} onChange={(state) => setPluginConfig("inputConfigItem", state)} /> | ||
<SettingsBoxItem title="更换间隔" description={["指定壁纸的切换间隔(如果存在多个壁纸)。"]}> | ||
<Dropdown | ||
items={[ | ||
[30 as const, "30 秒钟"], | ||
[60 as const, "1 分钟"], | ||
[120 as const, "2 分钟"], | ||
[300 as const, "5 分钟"], | ||
[600 as const, "10 分钟"], | ||
[1800 as const, "30 分钟"], | ||
[3600 as const, "1 小时"], | ||
]} | ||
selected={pluginConfig.duration} | ||
onChange={(state) => setPluginConfig("duration", state)} | ||
width="150px" | ||
/> | ||
</SettingsBoxItem> | ||
</SettingsBox> | ||
</SettingsSection> | ||
{pluginConfig.wallpapers.map((wallpaper, idx) => { | ||
const setWallpaper = <T extends keyof Wallpaper>(key: T, value: Wallpaper[T]) => | ||
setPluginConfig( | ||
"wallpapers", | ||
pluginConfig.wallpapers.map((currentWallpaper, currentIdx) => (currentIdx == idx ? { ...currentWallpaper, [key]: value } : currentWallpaper)), | ||
); | ||
return ( | ||
<SettingsSection | ||
// rome-ignore lint/suspicious/noArrayIndexKey: <explanation> | ||
key={idx} | ||
title={`壁纸 ${idx + 1}`} | ||
buttons={[ | ||
<Button | ||
onClick={() => | ||
setPluginConfig( | ||
"wallpapers", | ||
pluginConfig.wallpapers.filter((currentWallpaper) => currentWallpaper != wallpaper), | ||
) | ||
} | ||
primary={false} | ||
small={true} | ||
> | ||
删除此壁纸源 | ||
</Button>, | ||
]} | ||
> | ||
<SettingsBoxItem title="来源" description={["指定此插件应从何处获取壁纸。"]}> | ||
<Dropdown | ||
items={[ | ||
["none" as const, "无"], | ||
["file" as const, "文件"], | ||
["dir" as const, "目录"], | ||
["url" as const, "网址"], | ||
["script" as const, "自定义脚本"], | ||
]} | ||
selected={wallpaper.source} | ||
onChange={(state) => setWallpaper("source", state)} | ||
width="150px" | ||
/> | ||
</SettingsBoxItem> | ||
{wallpaper.source == "file" && ( | ||
<SettingsBoxItem title="文件" description={["指定壁纸文件(支持多选)。", `当前文件:${wallpaper.files.join(", ") || "无"}`]}> | ||
<Button | ||
onClick={() => { | ||
dialog.openDialog({ title: "打开图片", filters: [{ name: "支持的图片", extensions: ["jpg", "jpeg", "png", "gif", "svg", "bmp", "ico", "webp"] }], properties: ["openFile", "multiSelections"] }).then((ret) => { | ||
if (!ret.canceled) setWallpaper("files", [...wallpaper.files, ...ret.filePaths]); | ||
}); | ||
}} | ||
primary={true} | ||
small={true} | ||
> | ||
浏览 | ||
</Button> | ||
<Button onClick={() => setWallpaper("files", [])} primary={false} small={true}> | ||
清空 | ||
</Button> | ||
</SettingsBoxItem> | ||
)} | ||
{wallpaper.source == "dir" && ( | ||
<SettingsBoxItem title="文件" description={["指定包含壁纸文件的目录(支持多选)。", `当前目录:${wallpaper.files.join(", ") || "无"}`]}> | ||
<Button | ||
onClick={() => { | ||
dialog.openDialog({ title: "打开目录", properties: ["openDirectory", "multiSelections"] }).then((ret) => { | ||
if (!ret.canceled) setWallpaper("dirs", [...wallpaper.files, ...ret.filePaths]); | ||
}); | ||
}} | ||
primary={true} | ||
small={true} | ||
> | ||
浏览 | ||
</Button> | ||
<Button onClick={() => setWallpaper("dirs", [])} primary={false} small={true}> | ||
清空 | ||
</Button> | ||
</SettingsBoxItem> | ||
)} | ||
{wallpaper.source == "url" && ( | ||
<SettingsBoxItem title="URL" description={["指定包含壁纸文件的 URL(使用换行区分多个 URL)。"]}> | ||
<Input value={wallpaper.urls.join("\n")} onChange={(state) => setWallpaper("urls", state.split("\n"))} /> | ||
</SettingsBoxItem> | ||
)} | ||
{wallpaper.source == "script" && ( | ||
<SettingsBoxItem title="自定义脚本" description={["指定一个函数,该函数应返回一个返回网址数组的 Promise。示例:", 'return fetch("https://my-wallpaper-source.com/api.json")', " .then((res)=>res.json()).then((data)=>data.urls);"]}> | ||
<Input value={wallpaper.script} onChange={(state) => setWallpaper("script", state)} /> | ||
</SettingsBoxItem> | ||
)} | ||
</SettingsSection> | ||
); | ||
})} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { sep as s } from "path"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters