Skip to content
This repository has been archived by the owner on Jul 25, 2023. It is now read-only.

Commit

Permalink
release 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
FlysoftBeta committed Jul 20, 2023
1 parent 4240454 commit 69d3ac9
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
6 changes: 3 additions & 3 deletions publish/qqntim.json
Original file line number Diff line number Diff line change
@@ -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": [
Expand Down
30 changes: 28 additions & 2 deletions publish/style.css
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;
}
23 changes: 14 additions & 9 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -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<PluginConfig>;
Expand Down
70 changes: 66 additions & 4 deletions src/renderer.ts
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();
});
}
}
154 changes: 130 additions & 24 deletions src/settings.tsx
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>
);
})}
</>
);
}
1 change: 1 addition & 0 deletions src/utils/sep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { sep as s } from "path";
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 69d3ac9

Please sign in to comment.