Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68e0858177 | ||
|
|
9a44550e2e | ||
|
|
916389ca55 | ||
|
|
c71ed9a982 | ||
|
|
c7ad45ebbb | ||
|
|
56ccc04f2a | ||
|
|
be030c2ae9 | ||
|
|
b8f1b81c0f | ||
|
|
31fcf4ea83 | ||
|
|
5a48735f36 | ||
|
|
97fb9014f3 | ||
|
|
6580f1d261 | ||
|
|
21d4c33460 | ||
|
|
ba2cd4d5a3 | ||
|
|
c91f67944d | ||
|
|
5a0769e91b | ||
|
|
dc5d53a953 | ||
|
|
ac40bee45e | ||
|
|
c9df5b2317 | ||
|
|
cd10769d5d | ||
|
|
989aaf73a8 | ||
|
|
08b61c9779 | ||
|
|
9ce56708cd |
@@ -0,0 +1,46 @@
|
|||||||
|
# Wallitor
|
||||||
|
|
||||||
|
A dynamic wallpaper software build with tauri.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
This project has two parts, core and GUI.
|
||||||
|
|
||||||
|
### Core
|
||||||
|
|
||||||
|
Build solution with *MSVC*, you'll get a dynamic library.
|
||||||
|
|
||||||
|
### GUI
|
||||||
|
|
||||||
|
GUI is build with *tauri* and *vite+vue*, using *pnpm* as package manager.
|
||||||
|
|
||||||
|
1. Install node packages.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
2. Build project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm tauri build --no-bundle
|
||||||
|
```
|
||||||
|
|
||||||
|
### Combination
|
||||||
|
|
||||||
|
Copy libracy and place in the same directory with executable file.
|
||||||
|
|
||||||
|
## Releases
|
||||||
|
|
||||||
|
See [Release](https://github.com/RogerChen2005/wallitor/releases)
|
||||||
|
|
||||||
|
## Contributions
|
||||||
|
|
||||||
|
Welcome Issues and PRs!
|
||||||
|
|
||||||
|
## Acknowledgement
|
||||||
|
|
||||||
|
Wallitor was based on these projects:
|
||||||
|
|
||||||
|
* [tauri-apps/tauri](https://github.com/tauri-apps/tauri): Build smaller, faster, and more secure desktop applications with a web frontend.
|
||||||
|
* [vitejs/vite](https://github.com/vitejs/vite): Next generation frontend tooling. It's fast!
|
||||||
|
* [vuejs/vue](https://github.com/vuejs/vue): Vue is a **progressive framework** for building user interfaces.
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#include "pch.h"
|
|
||||||
#include "conFig.h"
|
|
||||||
|
|
||||||
conFig::conFig(const char* ffpath,const char* videoPath, BOOL mute) {
|
|
||||||
std::string tmp =ffpath;
|
|
||||||
this->ffpath = std::wstring(tmp.begin(), tmp.end());
|
|
||||||
tmp = videoPath;
|
|
||||||
this->videoPath = std::wstring(tmp.begin(), tmp.end());
|
|
||||||
this->mute = mute;
|
|
||||||
}
|
|
||||||
|
|
||||||
conFig::conFig(const conFig& config) {
|
|
||||||
this->ffpath = config.ffpath;
|
|
||||||
this->mute = config.mute;
|
|
||||||
this->videoPath = config.videoPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
conFig::conFig() {
|
|
||||||
this->ffpath = L"";
|
|
||||||
this->mute = TRUE;
|
|
||||||
this->videoPath = L"";
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
class conFig
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::wstring ffpath;
|
|
||||||
std::wstring videoPath;
|
|
||||||
BOOL mute;
|
|
||||||
conFig(const char* ffpath, const char* videoPath,BOOL mute);
|
|
||||||
conFig(const conFig& config);
|
|
||||||
conFig();
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -18,14 +18,10 @@ BOOL APIENTRY DllMain( HMODULE hModule,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerInstance* player_instance = NULL;
|
extern "C" __declspec(dllexport) BOOL set_wallpaper(const char* window_title) {
|
||||||
|
return set_as_wallpaper(window_title);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" __declspec(dllexport) BOOL init(const char* ffpath,const char* videoPath, BOOL mute) {
|
extern "C" __declspec(dllexport) BOOL any_maximized() {
|
||||||
player_instance = new playerInstance(conFig(ffpath, videoPath, mute));
|
return !detectWindowMaximized();
|
||||||
return player_instance->generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" __declspec(dllexport) void destroy() {
|
|
||||||
player_instance->exit();
|
|
||||||
delete player_instance;
|
|
||||||
}
|
}
|
||||||
@@ -1,115 +1,64 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "playerInstance.h"
|
#include "playerInstance.h"
|
||||||
#include <chrono>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
playerInstance::playerInstance(const conFig& config) {
|
HWND hWorkerw = NULL;
|
||||||
this->config = config;
|
|
||||||
this->hFfplay = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL CALLBACK EnumWindowsProc(_In_ HWND hwnd, _In_ LPARAM Lparam) {
|
static BOOL CALLBACK EnumWindowsProc(_In_ HWND hwnd, _In_ LPARAM Lparam) {
|
||||||
HWND hDefView = FindWindowEx(hwnd, 0, L"SHELLDLL_DefView", 0);
|
HWND hDefView = FindWindowEx(hwnd, 0, L"SHELLDLL_DefView", 0);
|
||||||
if (hDefView != 0) {
|
if (hDefView != 0) {
|
||||||
HWND hWorkerw = FindWindowEx(0, hwnd, L"WorkerW", 0);
|
hWorkerw = FindWindowEx(0, hwnd, L"WorkerW", 0);
|
||||||
ShowWindow(hWorkerw, SW_HIDE);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND findWindowTimeOut(const wchar_t* name, int timeoutMillis) {
|
BOOL try_find_worker(HWND hProgman,HWND hPlayer) {
|
||||||
auto start = std::chrono::steady_clock::now();
|
HWND hWorkerW = FindWindowEx(hProgman, 0, L"WorkerW", 0);
|
||||||
HWND hwnd = nullptr;
|
if (hWorkerW != NULL) {
|
||||||
|
SetParent(hPlayer, hWorkerW);
|
||||||
while (true) {
|
|
||||||
// 使用 FindWindowW 查找窗口
|
|
||||||
hwnd = FindWindowW(name, 0);
|
|
||||||
|
|
||||||
// 如果找到窗口,则返回
|
|
||||||
if (hwnd != nullptr) {
|
|
||||||
return hwnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算当前经过的时间
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
|
||||||
int elapsedMillis = std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
|
|
||||||
|
|
||||||
// 如果超时,则返回 nullptr
|
|
||||||
if (elapsedMillis > timeoutMillis) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 等待一段时间(例如100毫秒)再尝试查找
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL playerInstance::showWindow(LPCWSTR lpParameter) {
|
|
||||||
if (this->hFfplay != NULL) {
|
|
||||||
DWORD dwPID = 0;
|
|
||||||
GetWindowThreadProcessId(hFfplay, &dwPID);
|
|
||||||
char strCmd[MAX_PATH] = { 0 };
|
|
||||||
sprintf_s(strCmd, "taskkill /pid %d -f", dwPID);
|
|
||||||
system(strCmd);
|
|
||||||
}
|
|
||||||
STARTUPINFO si{ 0 };
|
|
||||||
//si.dwFlags = STARTF_USESHOWWINDOW;
|
|
||||||
//si.wShowWindow = SW_HIDE;
|
|
||||||
PROCESS_INFORMATION pi{ 0 };
|
|
||||||
if (CreateProcess(this->config.ffpath.c_str(), (LPWSTR)lpParameter, 0, 0, 0, CREATE_NO_WINDOW, 0, 0, &si, &pi)) {
|
|
||||||
//Sleep(600);//等待视频播放器启动完成
|
|
||||||
//HWND hProgman = FindWindow(L"Progman", 0);// 找到PI窗口
|
|
||||||
HWND hProgman = findWindowTimeOut(L"Progman",2000);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
|
||||||
if (hProgman == nullptr) return FALSE;
|
|
||||||
SendMessageTimeout(hProgman, 0x052c, 0, 0, 0, 300, 0);// 给它发特殊消息
|
|
||||||
//this->hFfplay = FindWindowW(L"SDL_app", 0);// 找到视频窗口
|
|
||||||
this->hFfplay = findWindowTimeOut(L"SDL_app", 2000);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
|
||||||
if (this->hFfplay == nullptr) return FALSE;
|
|
||||||
SetParent(hFfplay, hProgman);// 将视频窗口设苦为PM的子窗口
|
|
||||||
int systemWidth = GetSystemMetrics(0);
|
|
||||||
int systemHeight = GetSystemMetrics(1);
|
|
||||||
RECT cRct;
|
|
||||||
GetWindowRect(hFfplay, &cRct);
|
|
||||||
//if (horw) {
|
|
||||||
int width = cRct.right - cRct.left;
|
|
||||||
int x = (systemWidth - width) / 2;
|
|
||||||
MoveWindow(hFfplay, 0, 0, systemWidth, systemHeight, 1);
|
|
||||||
/* }
|
|
||||||
else {
|
|
||||||
int height = cRct.bottom - cRct.top;
|
|
||||||
int x = (sheight - height) / 2;
|
|
||||||
MoveWindow(hFfplay, 0, x, cRct.right - cRct.left, cRct.bottom - cRct.top, 0);
|
|
||||||
}*/
|
|
||||||
EnumWindows(EnumWindowsProc, 0);// 找到第二个workerw窗口并隐藏它
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
CloseHandle(pi.hProcess);
|
else return FALSE;
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL playerInstance::generate() {
|
HWND shell_in_progman(HWND hProgman) {
|
||||||
std::wstring fcmd = L" \"";
|
HWND hShell = FindWindowEx(hProgman, 0, L"SHELLDLL_DefView", 0);
|
||||||
fcmd += this->config.videoPath + L"\"";
|
return hShell;
|
||||||
fcmd += L" -noborder -loop 0";
|
|
||||||
if (this->config.mute) {
|
|
||||||
fcmd += L" -an";
|
|
||||||
}
|
|
||||||
fcmd += L" -fs";
|
|
||||||
return this->showWindow(fcmd.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void playerInstance::exit() {
|
BOOL set_as_wallpaper(const char* window_title) {
|
||||||
if (this->hFfplay != NULL) {
|
HWND hProgman = FindWindow(L"Progman", 0);// 找到PI窗口
|
||||||
DWORD dwPID = 0;
|
SendMessageTimeout(hProgman, 0x052c, 0, 0, SMTO_NORMAL, 0x3e8, 0);// 给它发特殊消息
|
||||||
GetWindowThreadProcessId(this->hFfplay, &dwPID);
|
std::string tmp = window_title;
|
||||||
char strCmd[MAX_PATH] = { 0 };
|
HWND hPlayer = FindWindowW(0, std::wstring(tmp.begin(), tmp.end()).c_str());// 找到视频窗口
|
||||||
sprintf_s(strCmd, "taskkill /pid %d -f", dwPID);
|
if (hPlayer == NULL) return FALSE;
|
||||||
system(strCmd);
|
HWND hDefView = shell_in_progman(hProgman);
|
||||||
|
if (hDefView!=NULL) {
|
||||||
|
if (try_find_worker(hProgman, hPlayer)) {
|
||||||
|
ShowWindow(hDefView, SW_HIDE);
|
||||||
|
Sleep(0);
|
||||||
|
ShowWindow(hDefView, SW_SHOWNORMAL);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else return FALSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SetParent(hPlayer, hProgman);// 将视频窗口设苦为PM的子窗口
|
||||||
|
EnumWindows(EnumWindowsProc, 0);// 找到第二个workerw窗口并隐藏它
|
||||||
|
if (hWorkerw) {
|
||||||
|
ShowWindow(hWorkerw, SW_HIDE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL CALLBACK CheckMaximized(_In_ HWND hwnd, _In_ LPARAM Lparam) {
|
||||||
|
BOOL isMaximized = IsZoomed(hwnd);
|
||||||
|
if (isMaximized) return FALSE;
|
||||||
|
else return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL detectWindowMaximized() {
|
||||||
|
return EnumWindows(CheckMaximized, 0);
|
||||||
|
}
|
||||||
@@ -1,15 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "conFig.h"
|
|
||||||
class playerInstance
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
HWND hFfplay;
|
|
||||||
conFig config;
|
|
||||||
public:
|
|
||||||
playerInstance(const conFig& config);
|
|
||||||
BOOL showWindow(LPCWSTR lpParameter);
|
|
||||||
BOOL generate();
|
|
||||||
void exit();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
BOOL set_as_wallpaper(const char* window_title);
|
||||||
|
BOOL detectWindowMaximized();
|
||||||
@@ -5,8 +5,6 @@ VisualStudioVersion = 17.9.34622.214
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wallitor-core", "wallitor-core.vcxproj", "{36591862-6F9C-4A1D-BBAD-4B1CBB1EC24B}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wallitor-core", "wallitor-core.vcxproj", "{36591862-6F9C-4A1D-BBAD-4B1CBB1EC24B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wallitor-cmd", "..\wallitor-cmd\wallitor-cmd.vcxproj", "{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
@@ -23,14 +21,6 @@ Global
|
|||||||
{36591862-6F9C-4A1D-BBAD-4B1CBB1EC24B}.Release|x64.Build.0 = Release|x64
|
{36591862-6F9C-4A1D-BBAD-4B1CBB1EC24B}.Release|x64.Build.0 = Release|x64
|
||||||
{36591862-6F9C-4A1D-BBAD-4B1CBB1EC24B}.Release|x86.ActiveCfg = Release|Win32
|
{36591862-6F9C-4A1D-BBAD-4B1CBB1EC24B}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{36591862-6F9C-4A1D-BBAD-4B1CBB1EC24B}.Release|x86.Build.0 = Release|Win32
|
{36591862-6F9C-4A1D-BBAD-4B1CBB1EC24B}.Release|x86.Build.0 = Release|Win32
|
||||||
{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}.Release|x64.Build.0 = Release|x64
|
|
||||||
{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{5675A6E4-1AEF-4AA3-A366-0D975C311AAF}.Release|x86.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -142,13 +142,11 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="conFig.h" />
|
|
||||||
<ClInclude Include="framework.h" />
|
<ClInclude Include="framework.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="playerInstance.h" />
|
<ClInclude Include="playerInstance.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="conFig.cpp" />
|
|
||||||
<ClCompile Include="dllmain.cpp" />
|
<ClCompile Include="dllmain.cpp" />
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
<ClInclude Include="playerInstance.h">
|
<ClInclude Include="playerInstance.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="conFig.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="dllmain.cpp">
|
<ClCompile Include="dllmain.cpp">
|
||||||
@@ -38,8 +35,5 @@
|
|||||||
<ClCompile Include="playerInstance.cpp">
|
<ClCompile Include="playerInstance.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="conFig.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -16,6 +16,7 @@ coverage
|
|||||||
|
|
||||||
/cypress/videos/
|
/cypress/videos/
|
||||||
/cypress/screenshots/
|
/cypress/screenshots/
|
||||||
|
target/
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
# wallitor-gui
|
|
||||||
|
|
||||||
This template should help get you started developing with Vue 3 in Vite.
|
|
||||||
|
|
||||||
## Recommended IDE Setup
|
|
||||||
|
|
||||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
|
||||||
|
|
||||||
## Type Support for `.vue` Imports in TS
|
|
||||||
|
|
||||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
|
||||||
|
|
||||||
## Customize configuration
|
|
||||||
|
|
||||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
|
||||||
|
|
||||||
## Project Setup
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pnpm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compile and Hot-Reload for Development
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pnpm dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Type-Check, Compile and Minify for Production
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pnpm build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lint with [ESLint](https://eslint.org/)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pnpm lint
|
|
||||||
```
|
|
||||||
@@ -14,8 +14,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "2.0.0-rc.0",
|
"@tauri-apps/api": "2.0.0-rc.0",
|
||||||
|
"@tauri-apps/plugin-autostart": "^2.0.0",
|
||||||
|
"@tauri-apps/plugin-dialog": "^2.0.0",
|
||||||
|
"@tauri-apps/plugin-fs": "2.0.0-rc.2",
|
||||||
|
"element-plus": "^2.8.5",
|
||||||
|
"unplugin-element-plus": "^0.8.0",
|
||||||
"vue": "^3.4.29",
|
"vue": "^3.4.29",
|
||||||
"vue-router": "^4.3.3"
|
"vue-router": "^4.3.3",
|
||||||
|
"vuex": "^4.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.8.0",
|
"@rushstack/eslint-patch": "^1.8.0",
|
||||||
|
|||||||
@@ -11,12 +11,30 @@ importers:
|
|||||||
'@tauri-apps/api':
|
'@tauri-apps/api':
|
||||||
specifier: 2.0.0-rc.0
|
specifier: 2.0.0-rc.0
|
||||||
version: 2.0.0-rc.0
|
version: 2.0.0-rc.0
|
||||||
|
'@tauri-apps/plugin-autostart':
|
||||||
|
specifier: ^2.0.0
|
||||||
|
version: 2.0.0
|
||||||
|
'@tauri-apps/plugin-dialog':
|
||||||
|
specifier: ^2.0.0
|
||||||
|
version: 2.0.0
|
||||||
|
'@tauri-apps/plugin-fs':
|
||||||
|
specifier: 2.0.0-rc.2
|
||||||
|
version: 2.0.0-rc.2
|
||||||
|
element-plus:
|
||||||
|
specifier: ^2.8.5
|
||||||
|
version: 2.8.5(vue@3.5.8(typescript@5.4.5))
|
||||||
|
unplugin-element-plus:
|
||||||
|
specifier: ^0.8.0
|
||||||
|
version: 0.8.0(rollup@4.22.4)
|
||||||
vue:
|
vue:
|
||||||
specifier: ^3.4.29
|
specifier: ^3.4.29
|
||||||
version: 3.5.8(typescript@5.4.5)
|
version: 3.5.8(typescript@5.4.5)
|
||||||
vue-router:
|
vue-router:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.4.5(vue@3.5.8(typescript@5.4.5))
|
version: 4.4.5(vue@3.5.8(typescript@5.4.5))
|
||||||
|
vuex:
|
||||||
|
specifier: ^4.0.2
|
||||||
|
version: 4.0.2(vue@3.5.8(typescript@5.4.5))
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@rushstack/eslint-patch':
|
'@rushstack/eslint-patch':
|
||||||
specifier: ^1.8.0
|
specifier: ^1.8.0
|
||||||
@@ -223,6 +241,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==}
|
resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@ctrl/tinycolor@3.6.1':
|
||||||
|
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
'@element-plus/icons-vue@2.3.1':
|
||||||
|
resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.2.0
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.21.5':
|
'@esbuild/aix-ppc64@0.21.5':
|
||||||
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
|
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -379,6 +406,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
|
resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
|
||||||
|
'@floating-ui/core@1.6.8':
|
||||||
|
resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==}
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.6.11':
|
||||||
|
resolution: {integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==}
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.8':
|
||||||
|
resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==}
|
||||||
|
|
||||||
'@humanwhocodes/config-array@0.13.0':
|
'@humanwhocodes/config-array@0.13.0':
|
||||||
resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==}
|
resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==}
|
||||||
engines: {node: '>=10.10.0'}
|
engines: {node: '>=10.10.0'}
|
||||||
@@ -530,10 +566,19 @@ packages:
|
|||||||
'@rushstack/eslint-patch@1.10.4':
|
'@rushstack/eslint-patch@1.10.4':
|
||||||
resolution: {integrity: sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==}
|
resolution: {integrity: sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==}
|
||||||
|
|
||||||
|
'@sxzz/popperjs-es@2.11.7':
|
||||||
|
resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
|
||||||
|
|
||||||
'@tauri-apps/api@2.0.0-rc.0':
|
'@tauri-apps/api@2.0.0-rc.0':
|
||||||
resolution: {integrity: sha512-v454Qs3REHc3Za59U+/eSmBsdmF+3NE5+76+lFDaitVqN4ZglDHENDaMARYKGJVZuxiSkzyqG0SeG7lLQjVkPA==}
|
resolution: {integrity: sha512-v454Qs3REHc3Za59U+/eSmBsdmF+3NE5+76+lFDaitVqN4ZglDHENDaMARYKGJVZuxiSkzyqG0SeG7lLQjVkPA==}
|
||||||
engines: {node: '>= 18.18', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
engines: {node: '>= 18.18', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||||
|
|
||||||
|
'@tauri-apps/api@2.0.0-rc.6':
|
||||||
|
resolution: {integrity: sha512-oENxL0C5WqHNSXWjZEbjnzoBwFFyn8do5S0elOg0ME1cLvWJOAKmqdCnWPpAwtzHQZ+xAzMU0/k8nPpJq4OQYA==}
|
||||||
|
|
||||||
|
'@tauri-apps/api@2.0.2':
|
||||||
|
resolution: {integrity: sha512-3wSwmG+1kr6WrgAFKK5ijkNFPp8TT3FLj3YHUb5EwMO+3FxX4uWlfSWkeeBy+Kc1RsKzugtYLuuya+98Flj+3w==}
|
||||||
|
|
||||||
'@tauri-apps/cli-darwin-arm64@2.0.0-rc.16':
|
'@tauri-apps/cli-darwin-arm64@2.0.0-rc.16':
|
||||||
resolution: {integrity: sha512-lISZU4gG0c9PbY7h/j/gW7nJLxZEygNBrYEET6zN8R99Znf5rSO+CfjenaMcJUUj6yTAd8gzdakRpLqNSAWegA==}
|
resolution: {integrity: sha512-lISZU4gG0c9PbY7h/j/gW7nJLxZEygNBrYEET6zN8R99Znf5rSO+CfjenaMcJUUj6yTAd8gzdakRpLqNSAWegA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
@@ -603,6 +648,15 @@ packages:
|
|||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
'@tauri-apps/plugin-autostart@2.0.0':
|
||||||
|
resolution: {integrity: sha512-NEwOQWVasZ8RczXkMLNJokRDujneuMH/UFA5t84DLkbNZUmiD3G7HZWhgSd1YQ0BFU9h9w+h2B/py3y6bzWg4Q==}
|
||||||
|
|
||||||
|
'@tauri-apps/plugin-dialog@2.0.0':
|
||||||
|
resolution: {integrity: sha512-ApNkejXP2jpPBSifznPPcHTXxu9/YaRW+eJ+8+nYwqp0lLUtebFHG4QhxitM43wwReHE81WAV1DQ/b+2VBftOA==}
|
||||||
|
|
||||||
|
'@tauri-apps/plugin-fs@2.0.0-rc.2':
|
||||||
|
resolution: {integrity: sha512-TFjCfso3tN4b5s2EBjqP8N2gYrPh93Ds3VNKj8pCXv4wbvnItyfG0aHO0haUsedBOHQryDwv9vDAdPX6/T0a+g==}
|
||||||
|
|
||||||
'@trysound/sax@0.2.0':
|
'@trysound/sax@0.2.0':
|
||||||
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
|
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
@@ -616,12 +670,21 @@ packages:
|
|||||||
'@types/estree@1.0.6':
|
'@types/estree@1.0.6':
|
||||||
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
|
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
|
||||||
|
|
||||||
|
'@types/lodash-es@4.17.12':
|
||||||
|
resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
|
||||||
|
|
||||||
|
'@types/lodash@4.17.10':
|
||||||
|
resolution: {integrity: sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==}
|
||||||
|
|
||||||
'@types/node@20.16.7':
|
'@types/node@20.16.7':
|
||||||
resolution: {integrity: sha512-QkDQjAY3gkvJNcZOWwzy3BN34RweT0OQ9zJyvLCU0kSK22dO2QYh/NHGfbEAYylPYzRB1/iXcojS79wOg5gFSw==}
|
resolution: {integrity: sha512-QkDQjAY3gkvJNcZOWwzy3BN34RweT0OQ9zJyvLCU0kSK22dO2QYh/NHGfbEAYylPYzRB1/iXcojS79wOg5gFSw==}
|
||||||
|
|
||||||
'@types/svgo@2.6.4':
|
'@types/svgo@2.6.4':
|
||||||
resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==}
|
resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==}
|
||||||
|
|
||||||
|
'@types/web-bluetooth@0.0.16':
|
||||||
|
resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==}
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@7.18.0':
|
'@typescript-eslint/eslint-plugin@7.18.0':
|
||||||
resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==}
|
resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==}
|
||||||
engines: {node: ^18.18.0 || >=20.0.0}
|
engines: {node: ^18.18.0 || >=20.0.0}
|
||||||
@@ -789,6 +852,15 @@ packages:
|
|||||||
'@vue/tsconfig@0.5.1':
|
'@vue/tsconfig@0.5.1':
|
||||||
resolution: {integrity: sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==}
|
resolution: {integrity: sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==}
|
||||||
|
|
||||||
|
'@vueuse/core@9.13.0':
|
||||||
|
resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
|
||||||
|
|
||||||
|
'@vueuse/metadata@9.13.0':
|
||||||
|
resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==}
|
||||||
|
|
||||||
|
'@vueuse/shared@9.13.0':
|
||||||
|
resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
|
||||||
|
|
||||||
acorn-jsx@5.3.2:
|
acorn-jsx@5.3.2:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -861,6 +933,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==}
|
resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
async-validator@4.2.5:
|
||||||
|
resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
|
||||||
|
|
||||||
atob@2.1.2:
|
atob@2.1.2:
|
||||||
resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==}
|
resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==}
|
||||||
engines: {node: '>= 4.5.0'}
|
engines: {node: '>= 4.5.0'}
|
||||||
@@ -1031,6 +1106,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
|
resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
dayjs@1.11.13:
|
||||||
|
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
|
||||||
|
|
||||||
de-indent@1.0.2:
|
de-indent@1.0.2:
|
||||||
resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
|
resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
|
||||||
|
|
||||||
@@ -1126,6 +1204,11 @@ packages:
|
|||||||
electron-to-chromium@1.5.28:
|
electron-to-chromium@1.5.28:
|
||||||
resolution: {integrity: sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==}
|
resolution: {integrity: sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==}
|
||||||
|
|
||||||
|
element-plus@2.8.5:
|
||||||
|
resolution: {integrity: sha512-Px+kPbRTVvn5oa5+9saa7QEOnUweKXm0JVI7yJHzKF/doQGixwcFMsQEF2+3Fy62EA/7dRRKVuhsNGGZYNk3cw==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.2.0
|
||||||
|
|
||||||
emojis-list@3.0.0:
|
emojis-list@3.0.0:
|
||||||
resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==}
|
resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
@@ -1155,6 +1238,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
es-module-lexer@1.5.4:
|
||||||
|
resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
|
||||||
|
|
||||||
es-object-atoms@1.0.0:
|
es-object-atoms@1.0.0:
|
||||||
resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
|
resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -1176,6 +1262,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
escape-html@1.0.3:
|
||||||
|
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
||||||
|
|
||||||
escape-string-regexp@1.0.5:
|
escape-string-regexp@1.0.5:
|
||||||
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
|
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
|
||||||
engines: {node: '>=0.8.0'}
|
engines: {node: '>=0.8.0'}
|
||||||
@@ -1732,6 +1821,16 @@ packages:
|
|||||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
lodash-es@4.17.21:
|
||||||
|
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
|
||||||
|
|
||||||
|
lodash-unified@1.0.3:
|
||||||
|
resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/lodash-es': '*'
|
||||||
|
lodash: '*'
|
||||||
|
lodash-es: '*'
|
||||||
|
|
||||||
lodash.merge@4.6.2:
|
lodash.merge@4.6.2:
|
||||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||||
|
|
||||||
@@ -1755,6 +1854,9 @@ packages:
|
|||||||
mdn-data@2.0.14:
|
mdn-data@2.0.14:
|
||||||
resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
|
resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
|
||||||
|
|
||||||
|
memoize-one@6.0.0:
|
||||||
|
resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
|
||||||
|
|
||||||
memorystream@0.3.1:
|
memorystream@0.3.1:
|
||||||
resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==}
|
resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==}
|
||||||
engines: {node: '>= 0.10.0'}
|
engines: {node: '>= 0.10.0'}
|
||||||
@@ -1827,6 +1929,9 @@ packages:
|
|||||||
node-releases@2.0.18:
|
node-releases@2.0.18:
|
||||||
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
|
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
|
||||||
|
|
||||||
|
normalize-wheel-es@1.2.0:
|
||||||
|
resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
|
||||||
|
|
||||||
npm-normalize-package-bin@3.0.1:
|
npm-normalize-package-bin@3.0.1:
|
||||||
resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==}
|
resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==}
|
||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||||
@@ -2338,6 +2443,19 @@ packages:
|
|||||||
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
|
|
||||||
|
unplugin-element-plus@0.8.0:
|
||||||
|
resolution: {integrity: sha512-jByUGY3FG2B8RJKFryqxx4eNtSTj+Hjlo8edcOdJymewndDQjThZ1pRUQHRjQsbKhTV2jEctJV7t7RJ405UL4g==}
|
||||||
|
engines: {node: '>=14.19.0'}
|
||||||
|
|
||||||
|
unplugin@1.14.1:
|
||||||
|
resolution: {integrity: sha512-lBlHbfSFPToDYp9pjXlUEFVxYLaue9f9T1HC+4OHlmj+HnMDdz9oZY+erXfoCe/5V/7gKUSY2jpXPb9S7f0f/w==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
webpack-sources: ^3
|
||||||
|
peerDependenciesMeta:
|
||||||
|
webpack-sources:
|
||||||
|
optional: true
|
||||||
|
|
||||||
unset-value@1.0.0:
|
unset-value@1.0.0:
|
||||||
resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==}
|
resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -2431,6 +2549,17 @@ packages:
|
|||||||
vscode-uri@3.0.8:
|
vscode-uri@3.0.8:
|
||||||
resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
|
resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
|
||||||
|
|
||||||
|
vue-demi@0.14.10:
|
||||||
|
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@vue/composition-api': ^1.0.0-rc.1
|
||||||
|
vue: ^3.0.0-0 || ^2.6.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@vue/composition-api':
|
||||||
|
optional: true
|
||||||
|
|
||||||
vue-eslint-parser@9.4.3:
|
vue-eslint-parser@9.4.3:
|
||||||
resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==}
|
resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==}
|
||||||
engines: {node: ^14.17.0 || >=16.0.0}
|
engines: {node: ^14.17.0 || >=16.0.0}
|
||||||
@@ -2456,6 +2585,14 @@ packages:
|
|||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
vuex@4.0.2:
|
||||||
|
resolution: {integrity: sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0.2
|
||||||
|
|
||||||
|
webpack-virtual-modules@0.6.2:
|
||||||
|
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
|
||||||
|
|
||||||
which-boxed-primitive@1.0.2:
|
which-boxed-primitive@1.0.2:
|
||||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||||
|
|
||||||
@@ -2698,6 +2835,12 @@ snapshots:
|
|||||||
'@babel/helper-validator-identifier': 7.24.7
|
'@babel/helper-validator-identifier': 7.24.7
|
||||||
to-fast-properties: 2.0.0
|
to-fast-properties: 2.0.0
|
||||||
|
|
||||||
|
'@ctrl/tinycolor@3.6.1': {}
|
||||||
|
|
||||||
|
'@element-plus/icons-vue@2.3.1(vue@3.5.8(typescript@5.4.5))':
|
||||||
|
dependencies:
|
||||||
|
vue: 3.5.8(typescript@5.4.5)
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.21.5':
|
'@esbuild/aix-ppc64@0.21.5':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -2790,6 +2933,17 @@ snapshots:
|
|||||||
|
|
||||||
'@eslint/js@8.57.1': {}
|
'@eslint/js@8.57.1': {}
|
||||||
|
|
||||||
|
'@floating-ui/core@1.6.8':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/utils': 0.2.8
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.6.11':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/core': 1.6.8
|
||||||
|
'@floating-ui/utils': 0.2.8
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.8': {}
|
||||||
|
|
||||||
'@humanwhocodes/config-array@0.13.0':
|
'@humanwhocodes/config-array@0.13.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@humanwhocodes/object-schema': 2.0.3
|
'@humanwhocodes/object-schema': 2.0.3
|
||||||
@@ -2893,8 +3047,14 @@ snapshots:
|
|||||||
|
|
||||||
'@rushstack/eslint-patch@1.10.4': {}
|
'@rushstack/eslint-patch@1.10.4': {}
|
||||||
|
|
||||||
|
'@sxzz/popperjs-es@2.11.7': {}
|
||||||
|
|
||||||
'@tauri-apps/api@2.0.0-rc.0': {}
|
'@tauri-apps/api@2.0.0-rc.0': {}
|
||||||
|
|
||||||
|
'@tauri-apps/api@2.0.0-rc.6': {}
|
||||||
|
|
||||||
|
'@tauri-apps/api@2.0.2': {}
|
||||||
|
|
||||||
'@tauri-apps/cli-darwin-arm64@2.0.0-rc.16':
|
'@tauri-apps/cli-darwin-arm64@2.0.0-rc.16':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -2938,6 +3098,18 @@ snapshots:
|
|||||||
'@tauri-apps/cli-win32-ia32-msvc': 2.0.0-rc.16
|
'@tauri-apps/cli-win32-ia32-msvc': 2.0.0-rc.16
|
||||||
'@tauri-apps/cli-win32-x64-msvc': 2.0.0-rc.16
|
'@tauri-apps/cli-win32-x64-msvc': 2.0.0-rc.16
|
||||||
|
|
||||||
|
'@tauri-apps/plugin-autostart@2.0.0':
|
||||||
|
dependencies:
|
||||||
|
'@tauri-apps/api': 2.0.2
|
||||||
|
|
||||||
|
'@tauri-apps/plugin-dialog@2.0.0':
|
||||||
|
dependencies:
|
||||||
|
'@tauri-apps/api': 2.0.2
|
||||||
|
|
||||||
|
'@tauri-apps/plugin-fs@2.0.0-rc.2':
|
||||||
|
dependencies:
|
||||||
|
'@tauri-apps/api': 2.0.0-rc.6
|
||||||
|
|
||||||
'@trysound/sax@0.2.0': {}
|
'@trysound/sax@0.2.0': {}
|
||||||
|
|
||||||
'@tsconfig/node20@20.1.4': {}
|
'@tsconfig/node20@20.1.4': {}
|
||||||
@@ -2946,6 +3118,12 @@ snapshots:
|
|||||||
|
|
||||||
'@types/estree@1.0.6': {}
|
'@types/estree@1.0.6': {}
|
||||||
|
|
||||||
|
'@types/lodash-es@4.17.12':
|
||||||
|
dependencies:
|
||||||
|
'@types/lodash': 4.17.10
|
||||||
|
|
||||||
|
'@types/lodash@4.17.10': {}
|
||||||
|
|
||||||
'@types/node@20.16.7':
|
'@types/node@20.16.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.19.8
|
undici-types: 6.19.8
|
||||||
@@ -2954,6 +3132,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.16.7
|
'@types/node': 20.16.7
|
||||||
|
|
||||||
|
'@types/web-bluetooth@0.0.16': {}
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1)(typescript@5.4.5)':
|
'@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.4.5))(eslint@8.57.1)(typescript@5.4.5)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.11.1
|
'@eslint-community/regexpp': 4.11.1
|
||||||
@@ -3207,6 +3387,25 @@ snapshots:
|
|||||||
|
|
||||||
'@vue/tsconfig@0.5.1': {}
|
'@vue/tsconfig@0.5.1': {}
|
||||||
|
|
||||||
|
'@vueuse/core@9.13.0(vue@3.5.8(typescript@5.4.5))':
|
||||||
|
dependencies:
|
||||||
|
'@types/web-bluetooth': 0.0.16
|
||||||
|
'@vueuse/metadata': 9.13.0
|
||||||
|
'@vueuse/shared': 9.13.0(vue@3.5.8(typescript@5.4.5))
|
||||||
|
vue-demi: 0.14.10(vue@3.5.8(typescript@5.4.5))
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@vue/composition-api'
|
||||||
|
- vue
|
||||||
|
|
||||||
|
'@vueuse/metadata@9.13.0': {}
|
||||||
|
|
||||||
|
'@vueuse/shared@9.13.0(vue@3.5.8(typescript@5.4.5))':
|
||||||
|
dependencies:
|
||||||
|
vue-demi: 0.14.10(vue@3.5.8(typescript@5.4.5))
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@vue/composition-api'
|
||||||
|
- vue
|
||||||
|
|
||||||
acorn-jsx@5.3.2(acorn@8.12.1):
|
acorn-jsx@5.3.2(acorn@8.12.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.12.1
|
acorn: 8.12.1
|
||||||
@@ -3266,6 +3465,8 @@ snapshots:
|
|||||||
|
|
||||||
assign-symbols@1.0.0: {}
|
assign-symbols@1.0.0: {}
|
||||||
|
|
||||||
|
async-validator@4.2.5: {}
|
||||||
|
|
||||||
atob@2.1.2: {}
|
atob@2.1.2: {}
|
||||||
|
|
||||||
available-typed-arrays@1.0.7:
|
available-typed-arrays@1.0.7:
|
||||||
@@ -3468,6 +3669,8 @@ snapshots:
|
|||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
is-data-view: 1.0.1
|
is-data-view: 1.0.1
|
||||||
|
|
||||||
|
dayjs@1.11.13: {}
|
||||||
|
|
||||||
de-indent@1.0.2: {}
|
de-indent@1.0.2: {}
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
@@ -3560,6 +3763,27 @@ snapshots:
|
|||||||
|
|
||||||
electron-to-chromium@1.5.28: {}
|
electron-to-chromium@1.5.28: {}
|
||||||
|
|
||||||
|
element-plus@2.8.5(vue@3.5.8(typescript@5.4.5)):
|
||||||
|
dependencies:
|
||||||
|
'@ctrl/tinycolor': 3.6.1
|
||||||
|
'@element-plus/icons-vue': 2.3.1(vue@3.5.8(typescript@5.4.5))
|
||||||
|
'@floating-ui/dom': 1.6.11
|
||||||
|
'@popperjs/core': '@sxzz/popperjs-es@2.11.7'
|
||||||
|
'@types/lodash': 4.17.10
|
||||||
|
'@types/lodash-es': 4.17.12
|
||||||
|
'@vueuse/core': 9.13.0(vue@3.5.8(typescript@5.4.5))
|
||||||
|
async-validator: 4.2.5
|
||||||
|
dayjs: 1.11.13
|
||||||
|
escape-html: 1.0.3
|
||||||
|
lodash: 4.17.21
|
||||||
|
lodash-es: 4.17.21
|
||||||
|
lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21)
|
||||||
|
memoize-one: 6.0.0
|
||||||
|
normalize-wheel-es: 1.2.0
|
||||||
|
vue: 3.5.8(typescript@5.4.5)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@vue/composition-api'
|
||||||
|
|
||||||
emojis-list@3.0.0: {}
|
emojis-list@3.0.0: {}
|
||||||
|
|
||||||
entities@1.1.2: {}
|
entities@1.1.2: {}
|
||||||
@@ -3625,6 +3849,8 @@ snapshots:
|
|||||||
|
|
||||||
es-errors@1.3.0: {}
|
es-errors@1.3.0: {}
|
||||||
|
|
||||||
|
es-module-lexer@1.5.4: {}
|
||||||
|
|
||||||
es-object-atoms@1.0.0:
|
es-object-atoms@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
@@ -3669,6 +3895,8 @@ snapshots:
|
|||||||
|
|
||||||
escalade@3.2.0: {}
|
escalade@3.2.0: {}
|
||||||
|
|
||||||
|
escape-html@1.0.3: {}
|
||||||
|
|
||||||
escape-string-regexp@1.0.5: {}
|
escape-string-regexp@1.0.5: {}
|
||||||
|
|
||||||
escape-string-regexp@4.0.0: {}
|
escape-string-regexp@4.0.0: {}
|
||||||
@@ -4249,6 +4477,14 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-locate: 5.0.0
|
p-locate: 5.0.0
|
||||||
|
|
||||||
|
lodash-es@4.17.21: {}
|
||||||
|
|
||||||
|
lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21):
|
||||||
|
dependencies:
|
||||||
|
'@types/lodash-es': 4.17.12
|
||||||
|
lodash: 4.17.21
|
||||||
|
lodash-es: 4.17.21
|
||||||
|
|
||||||
lodash.merge@4.6.2: {}
|
lodash.merge@4.6.2: {}
|
||||||
|
|
||||||
lodash@4.17.21: {}
|
lodash@4.17.21: {}
|
||||||
@@ -4269,6 +4505,8 @@ snapshots:
|
|||||||
|
|
||||||
mdn-data@2.0.14: {}
|
mdn-data@2.0.14: {}
|
||||||
|
|
||||||
|
memoize-one@6.0.0: {}
|
||||||
|
|
||||||
memorystream@0.3.1: {}
|
memorystream@0.3.1: {}
|
||||||
|
|
||||||
merge-options@1.0.1:
|
merge-options@1.0.1:
|
||||||
@@ -4351,6 +4589,8 @@ snapshots:
|
|||||||
|
|
||||||
node-releases@2.0.18: {}
|
node-releases@2.0.18: {}
|
||||||
|
|
||||||
|
normalize-wheel-es@1.2.0: {}
|
||||||
|
|
||||||
npm-normalize-package-bin@3.0.1: {}
|
npm-normalize-package-bin@3.0.1: {}
|
||||||
|
|
||||||
npm-run-all2@6.2.3:
|
npm-run-all2@6.2.3:
|
||||||
@@ -4913,6 +5153,21 @@ snapshots:
|
|||||||
|
|
||||||
universalify@2.0.1: {}
|
universalify@2.0.1: {}
|
||||||
|
|
||||||
|
unplugin-element-plus@0.8.0(rollup@4.22.4):
|
||||||
|
dependencies:
|
||||||
|
'@rollup/pluginutils': 5.1.2(rollup@4.22.4)
|
||||||
|
es-module-lexer: 1.5.4
|
||||||
|
magic-string: 0.30.11
|
||||||
|
unplugin: 1.14.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- rollup
|
||||||
|
- webpack-sources
|
||||||
|
|
||||||
|
unplugin@1.14.1:
|
||||||
|
dependencies:
|
||||||
|
acorn: 8.12.1
|
||||||
|
webpack-virtual-modules: 0.6.2
|
||||||
|
|
||||||
unset-value@1.0.0:
|
unset-value@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-value: 0.3.1
|
has-value: 0.3.1
|
||||||
@@ -5012,6 +5267,10 @@ snapshots:
|
|||||||
|
|
||||||
vscode-uri@3.0.8: {}
|
vscode-uri@3.0.8: {}
|
||||||
|
|
||||||
|
vue-demi@0.14.10(vue@3.5.8(typescript@5.4.5)):
|
||||||
|
dependencies:
|
||||||
|
vue: 3.5.8(typescript@5.4.5)
|
||||||
|
|
||||||
vue-eslint-parser@9.4.3(eslint@8.57.1):
|
vue-eslint-parser@9.4.3(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
@@ -5047,6 +5306,13 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.4.5
|
typescript: 5.4.5
|
||||||
|
|
||||||
|
vuex@4.0.2(vue@3.5.8(typescript@5.4.5)):
|
||||||
|
dependencies:
|
||||||
|
'@vue/devtools-api': 6.6.4
|
||||||
|
vue: 3.5.8(typescript@5.4.5)
|
||||||
|
|
||||||
|
webpack-virtual-modules@0.6.2: {}
|
||||||
|
|
||||||
which-boxed-primitive@1.0.2:
|
which-boxed-primitive@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-bigint: 1.0.4
|
is-bigint: 1.0.4
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
/target/
|
/target/
|
||||||
|
|
||||||
|
# Generated by Tauri
|
||||||
|
# will have schema files for capabilities auto-completion
|
||||||
|
/gen/schemas
|
||||||
|
resource/
|
||||||
|
wallitor-core.dll
|
||||||
|
settings.json
|
||||||
@@ -1,27 +1,34 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "app"
|
name = "wallitor-gui"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "A Tauri App"
|
description = "A Tauri App"
|
||||||
authors = ["you"]
|
authors = ["you"]
|
||||||
license = ""
|
|
||||||
repository = ""
|
|
||||||
default-run = "app"
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.60"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "wallitor_gui_lib"
|
||||||
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "2.0.0-rc", features = [] }
|
tauri-build = { version = "2.0.0-rc", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_json = "1.0"
|
tauri = { version = "2.0.0-rc", features = ["unstable", "tray-icon"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
tauri-plugin-shell = "2.0.0-rc"
|
||||||
tauri = { version = "2.0.0-rc", features = [] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
window-vibrancy = "0.5.2"
|
window-vibrancy = "0.5.2"
|
||||||
|
tauri-plugin-fs = "2.0.0-rc"
|
||||||
|
tauri-plugin-dialog = "2.0.0-rc"
|
||||||
|
chrono = "0.4.38"
|
||||||
|
libloading = "0.8.5"
|
||||||
|
lazy_static = "1.5.0"
|
||||||
|
|
||||||
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
|
tauri-plugin-autostart = "2.0.0-rc"
|
||||||
|
tauri-plugin-single-instance = "2.0.0-rc"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
|
||||||
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
|
||||||
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
|
|
||||||
# DO NOT REMOVE!!
|
|
||||||
custom-protocol = [ "tauri/custom-protocol" ]
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
tauri_build::build()
|
tauri_build::build()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
|
"identifier": "default",
|
||||||
|
"description": "Capability for the main window",
|
||||||
|
"windows": ["main"],
|
||||||
|
"permissions": [
|
||||||
|
"core:default",
|
||||||
|
"shell:allow-open",
|
||||||
|
"dialog:allow-open",
|
||||||
|
"dialog:default",
|
||||||
|
"core:webview:allow-create-webview-window",
|
||||||
|
"core:window:allow-destroy",
|
||||||
|
"autostart:allow-enable",
|
||||||
|
"autostart:allow-disable",
|
||||||
|
"autostart:allow-is-enabled"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
|
"identifier": "video",
|
||||||
|
"description": "Capability for the main window",
|
||||||
|
"windows": ["wallitor_video_playback"],
|
||||||
|
"permissions": ["core:default", "shell:allow-open","core:window:allow-destroy"]
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-toggle-maximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-start-dragging"]}}
|
{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["main"],"permissions":["core:default","shell:allow-open","dialog:allow-open","dialog:default","core:webview:allow-create-webview-window","core:window:allow-destroy","autostart:allow-enable","autostart:allow-disable","autostart:allow-is-enabled"]},"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-toggle-maximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-start-dragging"]},"video":{"identifier":"video","description":"Capability for the main window","local":true,"windows":["wallitor_video_playback"],"permissions":["core:default","shell:allow-open","core:window:allow-destroy"]}}
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 36 KiB |
@@ -0,0 +1,64 @@
|
|||||||
|
use crate::handler::get_absolute_path;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use libloading::{self, Library};
|
||||||
|
use std::{ffi::CString, ops::Deref, sync::Arc};
|
||||||
|
|
||||||
|
struct CoreModule {
|
||||||
|
_module: Arc<Library>,
|
||||||
|
pub set_wallpaper: libloading::os::windows::Symbol<unsafe extern "C" fn(*const i8) -> i8>,
|
||||||
|
pub any_maximized: libloading::os::windows::Symbol<unsafe extern "C" fn() -> i8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CoreModule {
|
||||||
|
fn new(library_path: &str) -> CoreModule {
|
||||||
|
let library_dir = get_absolute_path(&String::from(library_path));
|
||||||
|
// 首先加载动态库
|
||||||
|
let _module = Arc::new(unsafe { Library::new(library_dir).unwrap() });
|
||||||
|
// 然后获取符号
|
||||||
|
let set_wallpaper: libloading::os::windows::Symbol<unsafe extern "C" fn(*const i8) -> i8> = unsafe {
|
||||||
|
_module
|
||||||
|
.get::<unsafe extern "C" fn(*const i8) -> i8>(b"set_wallpaper\0")
|
||||||
|
.unwrap()
|
||||||
|
.into_raw()
|
||||||
|
};
|
||||||
|
let any_maximized: libloading::os::windows::Symbol<unsafe extern "C" fn() -> i8> = unsafe {
|
||||||
|
_module
|
||||||
|
.get::<unsafe extern "C" fn() -> i8>(b"any_maximized\0")
|
||||||
|
.unwrap()
|
||||||
|
.into_raw()
|
||||||
|
};
|
||||||
|
// 返回初始化的结构体
|
||||||
|
CoreModule {
|
||||||
|
_module,
|
||||||
|
set_wallpaper,
|
||||||
|
any_maximized,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref core_module: CoreModule = CoreModule::new("wallitor-core.dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn set_wallpaper(title: String) -> bool {
|
||||||
|
let title = CString::new(title.to_string()).unwrap();
|
||||||
|
unsafe {
|
||||||
|
let res = core_module.set_wallpaper.deref()(title.as_ptr());
|
||||||
|
if res == 0 {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn any_zoomed() -> bool {
|
||||||
|
unsafe {
|
||||||
|
let res = core_module.any_maximized.deref()();
|
||||||
|
if res == 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
use crate::handler::get_absolute_path;
|
||||||
|
use crate::{reader, VERSION};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::json;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use tauri::ipc::Response;
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_file(path: String) -> Response {
|
||||||
|
let p = get_absolute_path(&path);
|
||||||
|
if let Ok(true) = fs::exists(&p) {
|
||||||
|
let data: Vec<u8> = fs::read(&p).unwrap();
|
||||||
|
return tauri::ipc::Response::new(data);
|
||||||
|
}
|
||||||
|
tauri::ipc::Response::new(String::from(""))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn read_resource_dir() -> String {
|
||||||
|
let mut file_map = reader::FileMap::new();
|
||||||
|
let path = get_absolute_path(&String::from(".\\resource"));
|
||||||
|
if let Ok(false) = fs::exists(&path) {
|
||||||
|
fs::create_dir(&path).expect("Can't create dir");
|
||||||
|
}
|
||||||
|
file_map
|
||||||
|
.read_resourse_directory(&path)
|
||||||
|
.expect("Can't read dir");
|
||||||
|
serde_json::to_string(&file_map).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn del_folder(path: String) -> bool {
|
||||||
|
let p = Path::new(&path);
|
||||||
|
if p.starts_with(".\\") {
|
||||||
|
let folder_path = get_absolute_path(&path);
|
||||||
|
if folder_path.is_dir() {
|
||||||
|
if let Ok(true) = fs::exists(&folder_path) {
|
||||||
|
if fs::remove_dir_all(&folder_path).is_ok() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Settings {
|
||||||
|
title_bar: String,
|
||||||
|
auto_start: bool,
|
||||||
|
auto_pause: bool,
|
||||||
|
version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Settings {
|
||||||
|
fn new() -> Settings {
|
||||||
|
Settings {
|
||||||
|
title_bar: String::from("win"),
|
||||||
|
auto_start: false,
|
||||||
|
auto_pause: true,
|
||||||
|
version: String::from(VERSION),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SETTING_PATH: &str = "./settings.json";
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_settings() -> String {
|
||||||
|
let setting_path = get_absolute_path(&String::from(SETTING_PATH));
|
||||||
|
if let Ok(file) = fs::read(setting_path) {
|
||||||
|
let mut settings: Settings = serde_json::from_slice(&file).unwrap();
|
||||||
|
settings.version = String::from(VERSION);
|
||||||
|
return json!(settings).to_string();
|
||||||
|
} else {
|
||||||
|
set_settings(Settings::new()).await;
|
||||||
|
return json!(Settings::new()).to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn set_settings(settings: Settings) -> bool {
|
||||||
|
let setting_path = get_absolute_path(&String::from(SETTING_PATH));
|
||||||
|
if fs::write(setting_path, json!(settings).to_string()).is_ok() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
pub mod apply;
|
||||||
|
pub mod file;
|
||||||
|
pub mod wallpaper;
|
||||||
|
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
pub fn get_absolute_path(path: &String) -> PathBuf {
|
||||||
|
let binding = std::env::current_exe().unwrap();
|
||||||
|
let base_dir = binding.parent().unwrap();
|
||||||
|
return base_dir.join(Path::new(path));
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
use crate::handler::get_absolute_path;
|
||||||
|
use chrono::Local;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::{self, json};
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct AddInfo {
|
||||||
|
name: String,
|
||||||
|
preview: String,
|
||||||
|
media: String,
|
||||||
|
description: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Info {
|
||||||
|
media_type: String,
|
||||||
|
description: String,
|
||||||
|
created: i64,
|
||||||
|
entry_point: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Opt {
|
||||||
|
mute: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
name: String,
|
||||||
|
info: Info,
|
||||||
|
option: Opt,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn new_wallpaper(info: AddInfo) -> String {
|
||||||
|
let base_path = get_absolute_path(&String::from("./resource"));
|
||||||
|
let base_url = base_path.to_str().unwrap();
|
||||||
|
let current_time: i64 = Local::now().timestamp();
|
||||||
|
let folder = format!("{}/{}", base_url, current_time);
|
||||||
|
if fs::create_dir_all(Path::new(&folder)).is_err() {
|
||||||
|
return String::from("Error creating folder.");
|
||||||
|
}
|
||||||
|
if !info.preview.is_empty() {
|
||||||
|
if let Ok(false) = fs::exists(Path::new(&info.preview)) {
|
||||||
|
return String::from("Source Image doesn't exist.");
|
||||||
|
}
|
||||||
|
let preview = Path::new(&info.preview);
|
||||||
|
if let Some(ext) = preview.extension().and_then(|f| f.to_str()) {
|
||||||
|
if fs::copy(
|
||||||
|
Path::new(&info.preview),
|
||||||
|
Path::new(&format!("{}/preview.{}", folder, ext)),
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
return String::from("Error copy image.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return String::from("Invalid Image Path.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fs::create_dir(Path::new(&format!("{}/res", folder))).is_err() {
|
||||||
|
return String::from("Error creating res folder.");
|
||||||
|
}
|
||||||
|
let media = Path::new(&info.media);
|
||||||
|
if let Some(filename) = media.file_name().and_then(|f| f.to_str()) {
|
||||||
|
if fs::copy(
|
||||||
|
Path::new(&info.media),
|
||||||
|
Path::new(&format!("{}/res/{}", folder, filename)),
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
return String::from("Error copy media.");
|
||||||
|
}
|
||||||
|
let config = json!(Config {
|
||||||
|
name: info.name,
|
||||||
|
info: Info {
|
||||||
|
media_type: String::from("video"),
|
||||||
|
description: info.description,
|
||||||
|
created: current_time,
|
||||||
|
entry_point: String::from(filename)
|
||||||
|
},
|
||||||
|
option: Opt { mute: true }
|
||||||
|
});
|
||||||
|
if fs::write(
|
||||||
|
Path::new(&format!("{}/config.json", folder)),
|
||||||
|
config.to_string(),
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
return String::from("Error write config.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return String::from("Invalid media path.");
|
||||||
|
}
|
||||||
|
String::from("Success")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct EditInfo {
|
||||||
|
path: String,
|
||||||
|
name: String,
|
||||||
|
preview: String,
|
||||||
|
description: String,
|
||||||
|
mute: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_preview(target_dir: &String) -> bool {
|
||||||
|
if let Ok(entries) = fs::read_dir(target_dir) {
|
||||||
|
for entry in entries {
|
||||||
|
if let Ok(entry) = entry {
|
||||||
|
let path = entry.path();
|
||||||
|
if let Some(file_name) = path.file_stem().and_then(|s| s.to_str()) {
|
||||||
|
if file_name == "preview" {
|
||||||
|
if fs::remove_file(path).is_err() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_preview(source_file: &String, target_dir: &String) -> bool {
|
||||||
|
let preview_path = Path::new(source_file);
|
||||||
|
if let Ok(true) = fs::exists(preview_path) {
|
||||||
|
if delete_preview(target_dir) {
|
||||||
|
if let Some(ext) = preview_path.extension().and_then(|f| f.to_str()) {
|
||||||
|
if fs::copy(
|
||||||
|
preview_path,
|
||||||
|
Path::new(&format!("{}/preview.{}", target_dir, ext)),
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn edit_wallpaper(info: EditInfo) -> bool {
|
||||||
|
let folder_path = &get_absolute_path(&info.path);
|
||||||
|
if let Ok(true) = fs::exists(folder_path) {
|
||||||
|
let config_path_str = format!("{}/config.json", info.path);
|
||||||
|
let config_path = &get_absolute_path(&config_path_str);
|
||||||
|
if let Ok(file) = fs::read(config_path) {
|
||||||
|
let mut config: Config = serde_json::from_slice(&file).unwrap();
|
||||||
|
config.info.description = info.description;
|
||||||
|
config.name = info.name;
|
||||||
|
config.option.mute = info.mute;
|
||||||
|
if let Ok(()) = fs::write(config_path, json!(config).to_string()) {
|
||||||
|
if !info.preview.is_empty() {
|
||||||
|
return copy_preview(&info.preview, &info.path);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
mod handler;
|
||||||
|
mod reader;
|
||||||
|
mod setup;
|
||||||
|
extern crate lazy_static;
|
||||||
|
use tauri::Manager;
|
||||||
|
use tauri_plugin_autostart::MacosLauncher;
|
||||||
|
|
||||||
|
static VERSION: &str = "1.0.0";
|
||||||
|
|
||||||
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
|
pub fn run() {
|
||||||
|
tauri::Builder::default()
|
||||||
|
.setup(setup::init)
|
||||||
|
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
||||||
|
let window = app.get_webview_window("main").expect("no main window");
|
||||||
|
if let Ok(true) = window.is_minimized() {
|
||||||
|
let _ = window.unminimize();
|
||||||
|
}
|
||||||
|
if let Ok(false) = window.is_visible() {
|
||||||
|
let _ = window.show();
|
||||||
|
}
|
||||||
|
let _ = window.set_focus();
|
||||||
|
}))
|
||||||
|
.plugin(tauri_plugin_fs::init())
|
||||||
|
.plugin(tauri_plugin_dialog::init())
|
||||||
|
.plugin(tauri_plugin_autostart::init(
|
||||||
|
MacosLauncher::LaunchAgent,
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
handler::file::get_file,
|
||||||
|
handler::file::read_resource_dir,
|
||||||
|
handler::file::del_folder,
|
||||||
|
handler::wallpaper::new_wallpaper,
|
||||||
|
handler::apply::set_wallpaper,
|
||||||
|
handler::wallpaper::edit_wallpaper,
|
||||||
|
handler::apply::any_zoomed,
|
||||||
|
handler::file::get_settings,
|
||||||
|
handler::file::set_settings,
|
||||||
|
])
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("error while running tauri application");
|
||||||
|
}
|
||||||
@@ -1,18 +1,6 @@
|
|||||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
mod setup;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
wallitor_gui_lib::run()
|
||||||
.setup(setup::init)
|
|
||||||
.invoke_handler(tauri::generate_handler![test_command])
|
|
||||||
.run(tauri::generate_context!())
|
|
||||||
.expect("error while running tauri application");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn test_command() -> String {
|
|
||||||
return String::from("Hello World");
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
use serde::{Serialize, Serializer};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
enum FileType {
|
||||||
|
File(String),
|
||||||
|
Directory(HashMap<String, FileType>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for FileType {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
FileType::File(file) => serializer.serialize_str(file), // 文件只序列化路径
|
||||||
|
FileType::Directory(dir) => dir.serialize(serializer), // 目录序列化为HashMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct FileMap {
|
||||||
|
files: HashMap<String, FileType>, // 用于存储文件名和路径
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileMap {
|
||||||
|
pub fn new() -> FileMap {
|
||||||
|
FileMap {
|
||||||
|
files: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_resource(&self, p: &Path) -> std::io::Result<HashMap<String, FileType>> {
|
||||||
|
let mut files: HashMap<String, FileType> = HashMap::new();
|
||||||
|
for entry in fs::read_dir(p)? {
|
||||||
|
let dir = entry?;
|
||||||
|
let path = dir.path();
|
||||||
|
if path.is_file() {
|
||||||
|
files.insert(
|
||||||
|
path.file_name().unwrap().to_string_lossy().to_string(),
|
||||||
|
FileType::File(path.to_string_lossy().to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_resourse_directory(&mut self, p: &Path) -> std::io::Result<()> {
|
||||||
|
for entry in fs::read_dir(p)? {
|
||||||
|
let dir = entry?;
|
||||||
|
let path = dir.path();
|
||||||
|
if path.is_dir() {
|
||||||
|
let resource = self.read_resource(path.as_path())?;
|
||||||
|
self.files.insert(
|
||||||
|
path.to_string_lossy().to_string(),
|
||||||
|
FileType::Directory(resource),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,57 @@
|
|||||||
|
use tauri::{
|
||||||
|
menu::{Menu, MenuItem},
|
||||||
|
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
|
||||||
|
};
|
||||||
use tauri::{App, Manager};
|
use tauri::{App, Manager};
|
||||||
use window_vibrancy::{self, NSVisualEffectMaterial};
|
#[cfg(target_os = "windows")]
|
||||||
|
use window_vibrancy;
|
||||||
|
|
||||||
/// setup
|
/// setup
|
||||||
pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||||
let win = app.get_webview_window("main").unwrap();
|
let win = app.get_webview_window("main").unwrap();
|
||||||
// 仅在 macOS 下执行
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
window_vibrancy::apply_vibrancy(&win, NSVisualEffectMaterial::FullScreenUI)
|
|
||||||
.expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS");
|
|
||||||
|
|
||||||
// 仅在 windows 下执行
|
// 仅在 windows 下执行
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
if let Err(_) = window_vibrancy::apply_mica(&win, None){
|
if let Err(_) = window_vibrancy::apply_mica(&win, None) {
|
||||||
window_vibrancy::apply_acrylic(&win, Some((10,10,10,210))).expect("Unsupport Blur Effect!")
|
window_vibrancy::apply_acrylic(&win, Some((10, 10, 10, 210)))
|
||||||
|
.expect("Unsupport Blur Effect!")
|
||||||
}
|
}
|
||||||
|
let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
|
||||||
|
let menu = Menu::with_items(app, &[&quit_i])?;
|
||||||
|
TrayIconBuilder::new()
|
||||||
|
.icon(app.default_window_icon().unwrap().clone())
|
||||||
|
.menu(&menu)
|
||||||
|
.on_menu_event(|app, event| match event.id.as_ref() {
|
||||||
|
"quit" => {
|
||||||
|
app.exit(0);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
})
|
||||||
|
.on_tray_icon_event(move |tray, event| match event {
|
||||||
|
TrayIconEvent::Click {
|
||||||
|
button: MouseButton::Left,
|
||||||
|
button_state: MouseButtonState::Up,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
| TrayIconEvent::DoubleClick {
|
||||||
|
button: MouseButton::Left,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let app = tray.app_handle();
|
||||||
|
if let Some(window) = app.get_webview_window("main") {
|
||||||
|
let _ = window.show();
|
||||||
|
let _ = window.set_focus();
|
||||||
|
let _ = window.unminimize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TrayIconEvent::Click {
|
||||||
|
button: MouseButton::Right,
|
||||||
|
button_state: MouseButtonState::Up,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let _ = menu.app_handle().show_menu();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
})
|
||||||
|
.build(app)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1,64 +1,37 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
"$schema": "https://schema.tauri.app/config/2.0.0-rc",
|
||||||
"build": {
|
|
||||||
"beforeBuildCommand": "npm run build",
|
|
||||||
"beforeDevCommand": "npm run dev",
|
|
||||||
"frontendDist": "../dist",
|
|
||||||
"devUrl": "http://localhost:5173"
|
|
||||||
},
|
|
||||||
"bundle": {
|
|
||||||
"active": true,
|
|
||||||
"category": "DeveloperTool",
|
|
||||||
"copyright": "",
|
|
||||||
"targets": "all",
|
|
||||||
"externalBin": [],
|
|
||||||
"icon": [
|
|
||||||
"icons/32x32.png",
|
|
||||||
"icons/128x128.png",
|
|
||||||
"icons/128x128@2x.png",
|
|
||||||
"icons/icon.icns",
|
|
||||||
"icons/icon.ico"
|
|
||||||
],
|
|
||||||
"windows": {
|
|
||||||
"certificateThumbprint": null,
|
|
||||||
"digestAlgorithm": "sha256",
|
|
||||||
"timestampUrl": ""
|
|
||||||
},
|
|
||||||
"longDescription": "",
|
|
||||||
"macOS": {
|
|
||||||
"entitlements": null,
|
|
||||||
"exceptionDomain": "",
|
|
||||||
"frameworks": [],
|
|
||||||
"providerShortName": null,
|
|
||||||
"signingIdentity": null
|
|
||||||
},
|
|
||||||
"resources": [],
|
|
||||||
"shortDescription": "",
|
|
||||||
"linux": {
|
|
||||||
"deb": {
|
|
||||||
"depends": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"productName": "wallitor-gui",
|
"productName": "wallitor-gui",
|
||||||
"mainBinaryName": "wallitor-gui",
|
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"identifier": "com.tauri.dev",
|
"identifier": "com.wallitor-gui.app",
|
||||||
"plugins": {},
|
"build": {
|
||||||
|
"beforeDevCommand": "pnpm dev",
|
||||||
|
"devUrl": "http://localhost:5173",
|
||||||
|
"beforeBuildCommand": "pnpm build",
|
||||||
|
"frontendDist": "../dist"
|
||||||
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
"fullscreen": false,
|
|
||||||
"resizable": true,
|
|
||||||
"title": "wallitor-gui",
|
"title": "wallitor-gui",
|
||||||
|
"width": 800,
|
||||||
|
"height": 600,
|
||||||
"transparent": true,
|
"transparent": true,
|
||||||
"width": 950,
|
|
||||||
"height": 750,
|
|
||||||
"decorations": false
|
"decorations": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
"csp": null
|
"csp": null
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"bundle": {
|
||||||
|
"active": true,
|
||||||
|
"targets": "all",
|
||||||
|
"icon": [
|
||||||
|
"icons/32x32.png",
|
||||||
|
"icons/128x128.png",
|
||||||
|
"icons/128x128@2x.png",
|
||||||
|
"icons/icon.icns",
|
||||||
|
"icons/icon.ico"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { onBeforeMount } from 'vue';
|
||||||
import TitleBar from './components/TitleBar.vue';
|
import TitleBar from './components/TitleBar.vue';
|
||||||
import { RouterLink, RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import { invoke } from "@tauri-apps/api"
|
import { useStore } from 'vuex';
|
||||||
|
|
||||||
const isDarkTheme = window.matchMedia("(prefers-color-scheme: dark)");
|
const isDarkTheme = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
const html_node = document.getElementsByTagName("html")[0]
|
const html_node = document.getElementsByTagName("html")[0]
|
||||||
@@ -14,9 +15,13 @@ isDarkTheme.addEventListener('change', (event) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
useStore().dispatch("get_settings");
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<title-bar mode="win"></title-bar>
|
<title-bar></title-bar>
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M11 13H5v-2h6V5h2v6h6v2h-6v6h-2z"/></svg>
|
||||||
|
After Width: | Height: | Size: 155 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1728872416760" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3377" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path fill="currentColor" d="M874.666667 241.066667h-202.666667V170.666667c0-40.533333-34.133333-74.666667-74.666667-74.666667h-170.666666c-40.533333 0-74.666667 34.133333-74.666667 74.666667v70.4H149.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h53.333334V853.333333c0 40.533333 34.133333 74.666667 74.666666 74.666667h469.333334c40.533333 0 74.666667-34.133333 74.666666-74.666667V305.066667H874.666667c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32zM416 170.666667c0-6.4 4.266667-10.666667 10.666667-10.666667h170.666666c6.4 0 10.666667 4.266667 10.666667 10.666667v70.4h-192V170.666667z m341.333333 682.666666c0 6.4-4.266667 10.666667-10.666666 10.666667H277.333333c-6.4 0-10.666667-4.266667-10.666666-10.666667V309.333333h490.666666V853.333333z" fill="currentColor" p-id="3378"></path><path d="M426.666667 736c17.066667 0 32-14.933333 32-32V490.666667c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v213.333333c0 17.066667 14.933333 32 32 32zM597.333333 736c17.066667 0 32-14.933333 32-32V490.666667c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v213.333333c0 17.066667 14.933333 32 32 32z" fill="currentColor" p-id="3379"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1729046702329" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3377" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M874.666667 480H224L514.133333 170.666667c12.8-12.8 10.666667-34.133333-2.133333-44.8s-32-10.666667-44.8 2.133333l-341.333333 362.666667c-2.133333 2.133333-4.266667 6.4-6.4 8.533333-2.133333 4.266667-2.133333 6.4-2.133334 10.666667s0 8.533333 2.133334 10.666666c2.133333 4.266667 4.266667 6.4 6.4 8.533334l341.333333 362.666666c6.4 6.4 14.933333 10.666667 23.466667 10.666667 8.533333 0 14.933333-2.133333 21.333333-8.533333 12.8-12.8 12.8-32 2.133333-44.8L224 544H874.666667c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32z" fill="currentColor" p-id="3378"></path></svg>
|
||||||
|
After Width: | Height: | Size: 907 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1729046722817" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3526" data-darkreader-inline-fill="" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M853.333333 501.333333c-17.066667 0-32 14.933333-32 32v320c0 6.4-4.266667 10.666667-10.666666 10.666667H170.666667c-6.4 0-10.666667-4.266667-10.666667-10.666667V213.333333c0-6.4 4.266667-10.666667 10.666667-10.666666h320c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32H170.666667c-40.533333 0-74.666667 34.133333-74.666667 74.666666v640c0 40.533333 34.133333 74.666667 74.666667 74.666667h640c40.533333 0 74.666667-34.133333 74.666666-74.666667V533.333333c0-17.066667-14.933333-32-32-32z" fill="#666666" p-id="3527" data-darkreader-inline-fill="" style="--darkreader-inline-fill: #4d5356;"></path><path d="M405.333333 484.266667l-32 125.866666c-2.133333 10.666667 0 23.466667 8.533334 29.866667 6.4 6.4 14.933333 8.533333 23.466666 8.533333h8.533334l125.866666-32c6.4-2.133333 10.666667-4.266667 14.933334-8.533333l300.8-300.8c38.4-38.4 38.4-102.4 0-140.8-38.4-38.4-102.4-38.4-140.8 0L413.866667 469.333333c-4.266667 4.266667-6.4 8.533333-8.533334 14.933334z m59.733334 23.466666L761.6 213.333333c12.8-12.8 36.266667-12.8 49.066667 0 12.8 12.8 12.8 36.266667 0 49.066667L516.266667 558.933333l-66.133334 17.066667 14.933334-68.266667z" fill="#666666" p-id="3528" data-darkreader-inline-fill="" style="--darkreader-inline-fill: #4d5356;"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m12 15.4l-6-6L7.4 8l4.6 4.6L16.6 8L18 9.4z"/></svg>
|
||||||
|
After Width: | Height: | Size: 165 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1728972948301" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3377" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M904.533333 422.4l-85.333333-14.933333-17.066667-38.4 49.066667-70.4c14.933333-21.333333 12.8-49.066667-6.4-68.266667l-53.333333-53.333333c-19.2-19.2-46.933333-21.333333-68.266667-6.4l-70.4 49.066666-38.4-17.066666-14.933333-85.333334c-2.133333-23.466667-23.466667-42.666667-49.066667-42.666666h-74.666667c-25.6 0-46.933333 19.2-53.333333 44.8l-14.933333 85.333333-38.4 17.066667L296.533333 170.666667c-21.333333-14.933333-49.066667-12.8-68.266666 6.4l-53.333334 53.333333c-19.2 19.2-21.333333 46.933333-6.4 68.266667l49.066667 70.4-17.066667 38.4-85.333333 14.933333c-21.333333 4.266667-40.533333 25.6-40.533333 51.2v74.666667c0 25.6 19.2 46.933333 44.8 53.333333l85.333333 14.933333 17.066667 38.4L170.666667 727.466667c-14.933333 21.333333-12.8 49.066667 6.4 68.266666l53.333333 53.333334c19.2 19.2 46.933333 21.333333 68.266667 6.4l70.4-49.066667 38.4 17.066667 14.933333 85.333333c4.266667 25.6 25.6 44.8 53.333333 44.8h74.666667c25.6 0 46.933333-19.2 53.333333-44.8l14.933334-85.333333 38.4-17.066667 70.4 49.066667c21.333333 14.933333 49.066667 12.8 68.266666-6.4l53.333334-53.333334c19.2-19.2 21.333333-46.933333 6.4-68.266666l-49.066667-70.4 17.066667-38.4 85.333333-14.933334c25.6-4.266667 44.8-25.6 44.8-53.333333v-74.666667c-4.266667-27.733333-23.466667-49.066667-49.066667-53.333333z m-19.2 117.333333l-93.866666 17.066667c-10.666667 2.133333-19.2 8.533333-23.466667 19.2l-29.866667 70.4c-4.266667 10.666667-2.133333 21.333333 4.266667 29.866667l53.333333 76.8-40.533333 40.533333-76.8-53.333333c-8.533333-6.4-21.333333-8.533333-29.866667-4.266667L576 768c-10.666667 4.266667-17.066667 12.8-19.2 23.466667l-17.066667 93.866666h-57.6l-17.066666-93.866666c-2.133333-10.666667-8.533333-19.2-19.2-23.466667l-70.4-29.866667c-10.666667-4.266667-21.333333-2.133333-29.866667 4.266667l-76.8 53.333333-40.533333-40.533333 53.333333-76.8c6.4-8.533333 8.533333-21.333333 4.266667-29.866667L256 576c-4.266667-10.666667-12.8-17.066667-23.466667-19.2l-93.866666-17.066667v-57.6l93.866666-17.066666c10.666667-2.133333 19.2-8.533333 23.466667-19.2l29.866667-70.4c4.266667-10.666667 2.133333-21.333333-4.266667-29.866667l-53.333333-76.8 40.533333-40.533333 76.8 53.333333c8.533333 6.4 21.333333 8.533333 29.866667 4.266667L448 256c10.666667-4.266667 17.066667-12.8 19.2-23.466667l17.066667-93.866666h57.6l17.066666 93.866666c2.133333 10.666667 8.533333 19.2 19.2 23.466667l70.4 29.866667c10.666667 4.266667 21.333333 2.133333 29.866667-4.266667l76.8-53.333333 40.533333 40.533333-53.333333 76.8c-6.4 8.533333-8.533333 21.333333-4.266667 29.866667L768 448c4.266667 10.666667 12.8 17.066667 23.466667 19.2l93.866666 17.066667v55.466666z" fill="currentColor" p-id="3378"></path><path d="M512 394.666667c-64 0-117.333333 53.333333-117.333333 117.333333s53.333333 117.333333 117.333333 117.333333 117.333333-53.333333 117.333333-117.333333-53.333333-117.333333-117.333333-117.333333z m0 170.666666c-29.866667 0-53.333333-23.466667-53.333333-53.333333s23.466667-53.333333 53.333333-53.333333 53.333333 23.466667 53.333333 53.333333-23.466667 53.333333-53.333333 53.333333z" fill="currentColor" p-id="3379"></path></svg>
|
||||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -1 +1 @@
|
|||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727275506845" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8495" data-darkreader-inline-fill="" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M563.8 512l262.5-312.9c4.4-5.2 0.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9c-4.4 5.2-0.7 13.1 6.1 13.1h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z" p-id="8496"></path></svg>
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727275506845" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8495" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path fill="currentColor" d="M563.8 512l262.5-312.9c4.4-5.2 0.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9c-4.4 5.2-0.7 13.1 6.1 13.1h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z" p-id="8496"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 710 B After Width: | Height: | Size: 699 B |
@@ -1 +1 @@
|
|||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727275608799" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15290" data-darkreader-inline-fill="" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32z m-40 728H184V184h656v656z" p-id="15291"></path></svg>
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727275608799" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15290" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path fill="currentColor" d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32z m-40 728H184V184h656v656z" p-id="15291"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 529 B After Width: | Height: | Size: 518 B |
@@ -0,0 +1,323 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="bg" class="item-add-bg" :class="{
|
||||||
|
'item-add-show': visible,
|
||||||
|
}">
|
||||||
|
<div class="item-add-content">
|
||||||
|
<header class="colbox item-add-header">
|
||||||
|
<div class="colbox item-add-header-icon item-add-header-item" @click="toggleVisible">
|
||||||
|
<template v-if="visible">
|
||||||
|
<SvgIcon name="keyboard-arrow-down" size="20px"></SvgIcon>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<SvgIcon name="add" size="20px"></SvgIcon>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="item-add-header-item item-add-header-title">
|
||||||
|
<div>添加</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main class="item-add-main">
|
||||||
|
<table class="item-add-form">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="item-add-form-title">标题</td>
|
||||||
|
<td><input type="text" v-model="addInfo.name" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="item-add-form-title">文件</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="image_src">
|
||||||
|
<img :src="image_src" class="item-add-image" @click="selectPreview">
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="item-add-preview" @click="selectPreview">
|
||||||
|
<div class="item-add-preview-text">
|
||||||
|
<SvgIcon name="add" size="20px"></SvgIcon>点击添加封面
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="colbox">
|
||||||
|
<button class="apply-button" @click="selectMedia">选择</button>
|
||||||
|
<div>{{ addInfo.media }}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="item-add-form-title">描述</td>
|
||||||
|
<td><textarea class="item-add-description" v-model="addInfo.description"></textarea></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><button class="apply-button" @click="handleAdd" ref="applyButton">添加</button></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { defineExpose, defineModel, ref } from 'vue';
|
||||||
|
import SvgIcon from './SvgIcon.vue';
|
||||||
|
import { open } from '@tauri-apps/plugin-dialog';
|
||||||
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
|
import { useStore } from 'vuex';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import type { AddInfo } from '@/ts/types';
|
||||||
|
|
||||||
|
const store = useStore();
|
||||||
|
const visible = defineModel<boolean>();
|
||||||
|
const bg = ref<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
const addInfo = ref<AddInfo>({
|
||||||
|
name: "",
|
||||||
|
preview: "",
|
||||||
|
media: "",
|
||||||
|
description: ""
|
||||||
|
})
|
||||||
|
const image_src = ref("");
|
||||||
|
const support_ext = [".mp4", ".mkv", ".flv", ".ts"];
|
||||||
|
const support_img_ext = [".jpg", ".png", ".gif", ".webp"];
|
||||||
|
const support_img_ext_map: { [key in (typeof support_img_ext)[number]]: string } = {
|
||||||
|
'.jpg': 'image/jpeg',
|
||||||
|
'.png': 'image/png',
|
||||||
|
'.gif': 'image/gif',
|
||||||
|
'.webp': 'image/webp'
|
||||||
|
}
|
||||||
|
const applyButton = ref<HTMLButtonElement | null>(null);
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
|
||||||
|
async function handleFileOpen() {
|
||||||
|
const file = await open({
|
||||||
|
multiple: false,
|
||||||
|
directory: false,
|
||||||
|
});
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectMedia() {
|
||||||
|
handleFileOpen().then((file) => {
|
||||||
|
if (file) {
|
||||||
|
let ext = file.substring(file.lastIndexOf("."));
|
||||||
|
if (support_ext.includes(ext)) {
|
||||||
|
addInfo.value.media = file;
|
||||||
|
} else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "文件格式不受支持"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectPreview() {
|
||||||
|
handleFileOpen().then((file) => {
|
||||||
|
if (file) {
|
||||||
|
let ext = file.substring(file.lastIndexOf("."));
|
||||||
|
if (support_img_ext.includes(ext)) {
|
||||||
|
addInfo.value.preview = file;
|
||||||
|
invoke("get_file", {
|
||||||
|
path: file
|
||||||
|
}).then((res) => {
|
||||||
|
let binary_data_arr = new Uint8Array(res as number[]);
|
||||||
|
const blob = new Blob([binary_data_arr], { type: support_img_ext_map[ext] });
|
||||||
|
const imageUrl = URL.createObjectURL(blob);
|
||||||
|
image_src.value = imageUrl;
|
||||||
|
})
|
||||||
|
} else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "文件格式不受支持"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleVisible() {
|
||||||
|
visible.value = !visible.value
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInfo(info: AddInfo) {
|
||||||
|
if (!info.name || !info.media) return false
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
if (checkInfo(addInfo.value)) {
|
||||||
|
if (applyButton.value) {
|
||||||
|
ElMessage({
|
||||||
|
type: "info",
|
||||||
|
message: "正在新建项目, 请勿重新点击或关闭程序"
|
||||||
|
})
|
||||||
|
applyButton.value.disabled = true;
|
||||||
|
invoke("new_wallpaper", {
|
||||||
|
info: addInfo.value
|
||||||
|
}).then((res) => {
|
||||||
|
if (applyButton.value) applyButton.value.disabled = false;
|
||||||
|
if (res as string == "Success") {
|
||||||
|
addInfo.value = {
|
||||||
|
name: "",
|
||||||
|
preview: "",
|
||||||
|
media: "",
|
||||||
|
description: ""
|
||||||
|
}
|
||||||
|
image_src.value = "";
|
||||||
|
store.commit("getWpList");
|
||||||
|
toggleVisible();
|
||||||
|
ElMessage({
|
||||||
|
type: "success",
|
||||||
|
message: "新建成功"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: `新建失败 ${res}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "请填写名称并选择媒体文件"
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes add-item-entry {
|
||||||
|
0% {
|
||||||
|
top: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: calc(100% - 60px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-bg {
|
||||||
|
border: solid var(--bd-color) 1px;
|
||||||
|
backdrop-filter: blur(30px) saturate(180%);
|
||||||
|
box-shadow: var(--shadow-edge-glow), var(--shadow);
|
||||||
|
background-color: var(--bg-color-alpha-darker);
|
||||||
|
border-radius: 8px;
|
||||||
|
left: 50%;
|
||||||
|
top: calc(100% - 60px);
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
position: absolute;
|
||||||
|
width: 85%;
|
||||||
|
height: calc(100% - 55px);
|
||||||
|
transition: .8s cubic-bezier(0.9, 0, 0, 1.1);
|
||||||
|
animation: add-item-entry .3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-show {
|
||||||
|
top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-content {
|
||||||
|
padding: 10px;
|
||||||
|
height: calc(100% - 20px);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-main {
|
||||||
|
margin: 10px;
|
||||||
|
height: calc(100% - 45px);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-main::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-header-icon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #3b93ff;
|
||||||
|
transition: .3s;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-header-icon:hover {
|
||||||
|
background-color: #1e5daa;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-header-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-header-title {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-main {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-preview {
|
||||||
|
background: linear-gradient(135deg, #0000000A 0%, #FFFFFF0A 100%);
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 400px;
|
||||||
|
height: 200px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: var(--shadow-edge-glow);
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-preview:hover {
|
||||||
|
background: var(--bg-hover-fill);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-preview:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-image {
|
||||||
|
background: linear-gradient(135deg, #0000001A 0%, #FFFFFF1A 100%);
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 400px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: var(--shadow-edge-glow);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-image:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-form {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-form td {
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-description {
|
||||||
|
width: 300px;
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-form-title {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-add-preview-text {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -4,9 +4,45 @@
|
|||||||
'apply-bar-left': position == 'left',
|
'apply-bar-left': position == 'left',
|
||||||
'apply-bar-right': position == 'right'
|
'apply-bar-right': position == 'right'
|
||||||
}">
|
}">
|
||||||
<div class="apply-bar-content">
|
<div class="apply-bar-content rowbox">
|
||||||
<img :src="config.img">
|
<img :src="cell.img" class="apply-bar-img">
|
||||||
{{ config.name }}
|
<div class="apply-bar-title">{{ cell.config.name }}</div>
|
||||||
|
<div class="apply-bar-info colbox" style="align-items: center;">
|
||||||
|
<div class="apply-bar-info-tag">
|
||||||
|
类型
|
||||||
|
</div>
|
||||||
|
<div class="apply-bar-info-main">
|
||||||
|
{{ cell.config.info.media_type }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="apply-bar-info rowbox">
|
||||||
|
<div class="apply-bar-info-tag">
|
||||||
|
描述
|
||||||
|
</div>
|
||||||
|
<div class="apply-bar-info-main">
|
||||||
|
{{ cell.config.info.description }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="apply-bar-info colbox" style="align-items: center;">
|
||||||
|
<div class="apply-bar-info-tag">
|
||||||
|
创建时间
|
||||||
|
</div>
|
||||||
|
<div class="apply-bar-info-main">
|
||||||
|
{{ (new Date(cell.config.info.created * 1000)).toLocaleString() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="apply-bar-info rowbox">
|
||||||
|
<div class="apply-bar-info-tag">
|
||||||
|
设置
|
||||||
|
</div>
|
||||||
|
<div class="apply-bar-info-main">
|
||||||
|
<div class="apply-bar-settings colbox">
|
||||||
|
<div>静音</div>
|
||||||
|
<div><input type="checkbox" v-model="cell.config.option.mute" /></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="apply-button" @click="apply">应用</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="apply-bar-close" @click="handleClose">
|
<div class="apply-bar-close" @click="handleClose">
|
||||||
<svg-icon name="close" color="var(--text-color)"></svg-icon>
|
<svg-icon name="close" color="var(--text-color)"></svg-icon>
|
||||||
@@ -16,12 +52,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps, defineExpose, defineEmits, defineModel, watch, ref, type PropType } from 'vue';
|
import { defineProps, defineExpose, defineEmits, defineModel, watch, ref, type PropType, computed } from 'vue';
|
||||||
type Position = "left" | "right";
|
type Position = "left" | "right";
|
||||||
interface Config {
|
import type { Cell, Settings } from '@/ts/types'
|
||||||
name: string,
|
import { useStore } from 'vuex';
|
||||||
img: string
|
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||||
}
|
const appWindow = getCurrentWebviewWindow();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
position: {
|
position: {
|
||||||
type: String as PropType<Position>,
|
type: String as PropType<Position>,
|
||||||
@@ -29,16 +65,30 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
|
|
||||||
})
|
})
|
||||||
|
const store = useStore();
|
||||||
|
const settings = computed<Settings>(() => store.state.settings)
|
||||||
const visible = defineModel<boolean>();
|
const visible = defineModel<boolean>();
|
||||||
const emit = defineEmits(["submit"]);
|
defineEmits(["submit"]);
|
||||||
const visible_ = ref(false);
|
const visible_ = ref(false);
|
||||||
const config = ref<Config>({
|
const cell = ref<Cell>({
|
||||||
name: "",
|
img: "",
|
||||||
img: ""
|
path: "",
|
||||||
|
config: {
|
||||||
|
name: "",
|
||||||
|
info: {
|
||||||
|
description: "",
|
||||||
|
created: 0,
|
||||||
|
media_type: "Video",
|
||||||
|
entry_point: ""
|
||||||
|
},
|
||||||
|
option: {
|
||||||
|
mute: true
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const bg = ref<HTMLDivElement | null>(null);
|
const bg = ref<HTMLDivElement | null>(null);
|
||||||
defineExpose({ open })
|
defineExpose({ open })
|
||||||
watch(() => visible.value, (val, _) => {
|
watch(() => visible.value, (val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
visible_.value = true;
|
visible_.value = true;
|
||||||
}
|
}
|
||||||
@@ -52,11 +102,22 @@ function handleClose() {
|
|||||||
visible.value = false;
|
visible.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function open(conFig: Config) {
|
function open(conFig: Cell) {
|
||||||
config.value = conFig;
|
cell.value = conFig;
|
||||||
console.log(conFig)
|
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function apply() {
|
||||||
|
let params: { [key: string]: string } = {
|
||||||
|
url: `${cell.value.path}\\res\\${cell.value.config.info.entry_point}`,
|
||||||
|
mute: `${cell.value.config.option.mute}`,
|
||||||
|
auto_pause: `${settings.value.auto_pause}`
|
||||||
|
}
|
||||||
|
store.dispatch("apply_wallpaper", {
|
||||||
|
url: `/video/?${(new URLSearchParams(params)).toString()}`,
|
||||||
|
title: "wallitor_video_playback"
|
||||||
|
}).then(() => appWindow.minimize())
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -105,7 +166,7 @@ function open(conFig: Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.apply-bar-mask {
|
.apply-bar-mask {
|
||||||
z-index: 500;
|
z-index: 200;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -115,7 +176,6 @@ function open(conFig: Config) {
|
|||||||
|
|
||||||
.apply-bar-bg {
|
.apply-bar-bg {
|
||||||
border: solid var(--bd-color) 1px;
|
border: solid var(--bd-color) 1px;
|
||||||
border: solid 1px var(--bd-color);
|
|
||||||
backdrop-filter: blur(30px) saturate(180%);
|
backdrop-filter: blur(30px) saturate(180%);
|
||||||
box-shadow: var(--shadow-edge-glow), var(--shadow);
|
box-shadow: var(--shadow-edge-glow), var(--shadow);
|
||||||
background-color: var(--bg-color-alpha-darker);
|
background-color: var(--bg-color-alpha-darker);
|
||||||
@@ -128,9 +188,16 @@ function open(conFig: Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.apply-bar-content {
|
.apply-bar-content {
|
||||||
padding: 20px;
|
padding: 20px 15% 0 15%;
|
||||||
height: calc(100% - 40px);
|
height: calc(100% - 40px);
|
||||||
|
width: 70%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.apply-bar-img {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.apply-bar-close {
|
.apply-bar-close {
|
||||||
@@ -150,4 +217,28 @@ function open(conFig: Config) {
|
|||||||
right: 10px;
|
right: 10px;
|
||||||
animation: apply-bar-appear-right .6s cubic-bezier(0, 0.6, 0.2, 1.0);
|
animation: apply-bar-appear-right .6s cubic-bezier(0, 0.6, 0.2, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.apply-bar-title {
|
||||||
|
font-size: 35px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apply-bar-info-tag {
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid var(--bd-color);
|
||||||
|
width: fit-content;
|
||||||
|
padding: 4px;
|
||||||
|
margin-top: 7px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 200;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apply-bar-info-main {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -5,9 +5,7 @@
|
|||||||
<slot name="content"></slot>
|
<slot name="content"></slot>
|
||||||
</div>
|
</div>
|
||||||
<div id="close" @click="handleClose">
|
<div id="close" @click="handleClose">
|
||||||
<el-icon :size="25">
|
<SvgIcon name="window-close" size="25px"></SvgIcon>
|
||||||
<Close />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -15,7 +13,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, nextTick } from 'vue'
|
import { defineComponent, nextTick } from 'vue'
|
||||||
import "@/style/cui.scss"
|
import "@/style/cui.css"
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "CDiaLog",
|
name: "CDiaLog",
|
||||||
@@ -63,16 +61,14 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
#mask {
|
#mask {
|
||||||
z-index: 500;
|
z-index: 200;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
animation: cui-dialog-blur .6s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#bg {
|
#bg {
|
||||||
@@ -87,6 +83,7 @@ export default defineComponent({
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
animation: cui-dialog-appear .6s cubic-bezier(0, 0.6, 0.2, 1.0);
|
animation: cui-dialog-appear .6s cubic-bezier(0, 0.6, 0.2, 1.0);
|
||||||
|
box-shadow: var(--shadow-edge-glow), var(--shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<div class="cui-rmenu-mask" @click.self="handleClose" @contextmenu.prevent="handleClose" v-if="visible">
|
||||||
|
<div ref="bg" class="cui-rmenu-bg">
|
||||||
|
<div class="cui-rmenu-content">
|
||||||
|
<slot name="content"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { defineProps, ref, defineEmits, defineExpose } from 'vue';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const emit = defineEmits(["update:visible"])
|
||||||
|
defineExpose({ handleOpen });
|
||||||
|
const bg = ref<HTMLDivElement | null>(null);
|
||||||
|
function handleClose() {
|
||||||
|
if (bg.value) bg.value.style.animation = "cui-rmenu-disappear .15s ease-in";
|
||||||
|
setTimeout(() => emit("update:visible", false), 150);
|
||||||
|
}
|
||||||
|
function handleOpen(x: number, y: number) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (bg.value) {
|
||||||
|
bg.value.style.top = `${y}px`;
|
||||||
|
bg.value.style.left = `${x}px`;
|
||||||
|
}
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes cui-rmenu-appear {
|
||||||
|
0% {
|
||||||
|
opacity: 0%;
|
||||||
|
transform: translate(-25%, -25%) scale(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 100%;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cui-rmenu-disappear {
|
||||||
|
0% {
|
||||||
|
opacity: 100%;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0%;
|
||||||
|
transform: translate(-25%, -25%) scale(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cui-rmenu-mask {
|
||||||
|
z-index: 2007;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cui-rmenu-bg {
|
||||||
|
position: absolute;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
max-width: 80%;
|
||||||
|
border: solid var(--bd-color) 1px;
|
||||||
|
background-color: var(--bg-color-solid);
|
||||||
|
border-radius: 8px;
|
||||||
|
animation: cui-rmenu-appear .25s cubic-bezier(0, 0, 0.36, 1.29);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cui-rmenu-content {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<template>
|
||||||
|
<div class="cui-rmenu-cell-wrapper">
|
||||||
|
<div class="cui-rmenu-cell-icon">
|
||||||
|
<slot name="icon"></slot>
|
||||||
|
</div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.cui-rmenu-cell-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
|
width: auto;
|
||||||
|
height: 30px;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
transition: .5s;
|
||||||
|
background-color: var(--bg-color-solid);
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 2px 7px 2px 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cui-rmenu-cell-wrapper:hover {
|
||||||
|
background-color: var(--bg-color-alter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cui-rmenu-cell-icon {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
<template>
|
||||||
|
<div class="item-edit-content">
|
||||||
|
<main class="item-edit-main">
|
||||||
|
<table class="item-edit-form">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="item-edit-form-title">标题</td>
|
||||||
|
<td><input type="text" v-model="data.name" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="item-edit-form-title">文件</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="image_src">
|
||||||
|
<img :src="image_src" class="item-edit-image" @click="selectPreview">
|
||||||
|
</template>
|
||||||
|
<template v-else-if="data.preview">
|
||||||
|
<img :src="data.preview" class="item-edit-image" @click="selectPreview">
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="item-edit-preview" @click="selectPreview">
|
||||||
|
<div class="item-edit-preview-text">
|
||||||
|
<SvgIcon name="add" size="20px"></SvgIcon>点击添加封面
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="item-edit-form-title">描述</td>
|
||||||
|
<td><textarea class="item-edit-description" v-model="data.description"></textarea>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="item-edit-form-title">静音</td>
|
||||||
|
<td>
|
||||||
|
<div><input type="checkbox" v-model="data.mute" /></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><button class="apply-button" @click="handleEdit" ref="applyButton">添加</button></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { open } from '@tauri-apps/plugin-dialog';
|
||||||
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
|
import { useStore } from 'vuex';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import type { EditInfo } from '@/ts/types';
|
||||||
|
|
||||||
|
const store = useStore();
|
||||||
|
const data = defineModel<EditInfo>("data", {
|
||||||
|
required: true
|
||||||
|
})
|
||||||
|
const emit = defineEmits(["submit"]);
|
||||||
|
const image_src = ref("");
|
||||||
|
const image_path = ref("");
|
||||||
|
const support_img_ext = ['.jpg', '.png', '.gif', '.webp'];
|
||||||
|
const support_img_ext_map: { [key in (typeof support_img_ext)[number]]: string } = {
|
||||||
|
'.jpg': 'image/jpeg',
|
||||||
|
'.png': 'image/png',
|
||||||
|
'.gif': 'image/gif',
|
||||||
|
'.webp': 'image/webp'
|
||||||
|
}
|
||||||
|
const applyButton = ref<HTMLButtonElement | null>(null);
|
||||||
|
|
||||||
|
async function handleFileOpen() {
|
||||||
|
const file = await open({
|
||||||
|
multiple: false,
|
||||||
|
directory: false,
|
||||||
|
});
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectPreview() {
|
||||||
|
handleFileOpen().then((file) => {
|
||||||
|
if (file) {
|
||||||
|
let ext = file.substring(file.lastIndexOf("."));
|
||||||
|
if (support_img_ext.includes(ext)) {
|
||||||
|
image_path.value = file;
|
||||||
|
invoke("get_file", {
|
||||||
|
path: file
|
||||||
|
}).then((res) => {
|
||||||
|
let binary_data_arr = new Uint8Array(res as number[]);
|
||||||
|
const blob = new Blob([binary_data_arr], { type: support_img_ext_map[ext] });
|
||||||
|
const imageUrl = URL.createObjectURL(blob);
|
||||||
|
image_src.value = imageUrl;
|
||||||
|
})
|
||||||
|
} else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "文件格式不受支持"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInfo(info: EditInfo) {
|
||||||
|
if (!info.name) return false
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEdit() {
|
||||||
|
if (checkInfo(data.value)) {
|
||||||
|
if (applyButton.value) {
|
||||||
|
ElMessage({
|
||||||
|
type: "info",
|
||||||
|
message: "正在修改项目, 请勿重新点击或关闭程序"
|
||||||
|
})
|
||||||
|
const info = Object.assign({}, data.value);
|
||||||
|
info.preview = image_path.value;
|
||||||
|
applyButton.value.disabled = true;
|
||||||
|
invoke("edit_wallpaper", {
|
||||||
|
info: info
|
||||||
|
}).then((res) => {
|
||||||
|
console.log(info);
|
||||||
|
if (applyButton.value) applyButton.value.disabled = false;
|
||||||
|
if (res as boolean) {
|
||||||
|
store.commit("getWpList");
|
||||||
|
emit("submit");
|
||||||
|
ElMessage({
|
||||||
|
type: "success",
|
||||||
|
message: "修改成功"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: `修改失败 ${res}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "请填写名称并选择媒体文件"
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.item-edit-show {
|
||||||
|
top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-content {
|
||||||
|
padding: 10px;
|
||||||
|
height: calc(100% - 20px);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-main {
|
||||||
|
margin: 10px;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-main::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-header-icon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #3b93ff;
|
||||||
|
transition: .3s;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-header-icon:hover {
|
||||||
|
background-color: #1e5daa;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-header-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-header-title {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-main {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-preview {
|
||||||
|
background: linear-gradient(135deg, #0000000A 0%, #FFFFFF0A 100%);
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 400px;
|
||||||
|
height: 200px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: var(--shadow-edge-glow);
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-preview:hover {
|
||||||
|
background: var(--bg-hover-fill);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-preview:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-image {
|
||||||
|
background: linear-gradient(135deg, #0000001A 0%, #FFFFFF1A 100%);
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 400px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: var(--shadow-edge-glow);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-image:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-form {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-form td {
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-description {
|
||||||
|
width: 300px;
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-form-title {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-edit-preview-text {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="item-card">
|
<div :style="{
|
||||||
<div class="item-card-main">
|
backgroundImage: cell.img ? `url(${cell.img})` : 'linear-gradient(135deg, #00000020 0%, #FFFFFF20 100%)'
|
||||||
|
}" class="item-card">
|
||||||
|
<!-- <div class="item-card-main">
|
||||||
<img :src="config.img" />
|
<img :src="config.img" />
|
||||||
</div>
|
</div> -->
|
||||||
<div class="item-card-title">
|
<div class="item-card-title">
|
||||||
{{ config.name }}
|
{{ cell.config.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -12,21 +14,21 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps } from 'vue'
|
import { defineProps } from 'vue'
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
|
import type { Cell } from '@/ts/types'
|
||||||
interface Config {
|
|
||||||
name: string,
|
|
||||||
img: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
config: {
|
cell: {
|
||||||
type: Object as PropType<Config>,
|
type: Object as PropType<Cell>,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@keyframes item-card-entry{
|
||||||
|
0%{opacity: 0;transform: translateY(10px);}
|
||||||
|
100%{opacity: 1;transform: translateY(0px);}
|
||||||
|
}
|
||||||
:root {
|
:root {
|
||||||
--item-card-size: 200px;
|
--item-card-size: 200px;
|
||||||
--item-card-margin: 20px;
|
--item-card-margin: 20px;
|
||||||
@@ -43,6 +45,9 @@ const props = defineProps({
|
|||||||
transition: .3s;
|
transition: .3s;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 0 1px 6px transparent;
|
box-shadow: 0 0 1px 6px transparent;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
animation: item-card-entry 0.3s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card-main {
|
.item-card-main {
|
||||||
@@ -52,7 +57,6 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item-card:hover {
|
.item-card:hover {
|
||||||
box-shadow: var(--shadow-edge-glow), var(--shadow);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transform: scale(1.03);
|
transform: scale(1.03);
|
||||||
box-shadow: 0 0 2px 5px rgba(177, 177, 177, 0.151);
|
box-shadow: 0 0 2px 5px rgba(177, 177, 177, 0.151);
|
||||||
@@ -67,7 +71,7 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item-card:hover .item-card-title {
|
.item-card:hover .item-card-title {
|
||||||
bottom: 0;
|
bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card-main img {
|
.item-card-main img {
|
||||||
@@ -78,10 +82,11 @@ const props = defineProps({
|
|||||||
.item-card-title {
|
.item-card-title {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: -40px;
|
bottom: -40px;
|
||||||
right: 5px;
|
right: 10px;
|
||||||
transition: .3s;
|
transition: .3s;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
|
text-shadow: 1px 1px 2px var(--bg-color);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<svg :style="{ width, height}">
|
<svg :style="{ width: size, height: size }">
|
||||||
<use :href="prefix + name" :fill="color"></use>
|
<use :href="prefix + name" :fill="color"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
@@ -11,20 +11,16 @@ defineProps({
|
|||||||
default: "#icon-"
|
default: "#icon-"
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type:String,
|
type: String,
|
||||||
required:true
|
required: true
|
||||||
},
|
},
|
||||||
color: {
|
color: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "#ffffff"
|
default: "#ffffff"
|
||||||
},
|
},
|
||||||
width: {
|
size: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "16px"
|
default: "16px"
|
||||||
},
|
},
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: "16px"
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -1,79 +1,84 @@
|
|||||||
<template>
|
<template>
|
||||||
<div data-tauri-drag-region class="titlebar colbox">
|
<div data-tauri-drag-region class="titlebar colbox">
|
||||||
<template v-if="mode == 'mac'">
|
|
||||||
<div class="titlebar-button-wrapper colbox">
|
|
||||||
<div class="titlebar-button" id="titlebar-minimize" @click="minimize">
|
|
||||||
<svg-icon name="window-minimize" color="red"></svg-icon>
|
|
||||||
</div>
|
|
||||||
<div class="titlebar-button" id="titlebar-maximize" @click="toggleMaximize">
|
|
||||||
<template v-if="maximized">
|
|
||||||
<svg-icon name="window-maximized"></svg-icon>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<svg-icon name="window-maximize" width="13px"></svg-icon>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<div class="titlebar-button" id="titlebar-close" @click="close">
|
|
||||||
<svg-icon name="window-close"></svg-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div class="titlebar-icon-wrapper colbox">
|
<div class="titlebar-icon-wrapper colbox">
|
||||||
|
<template v-if="mode == 'mac'">
|
||||||
|
<div class="titlebar-button titlebar-close button-style-mac" @click="close">
|
||||||
|
<svg-icon name="window-close" :size="button_size_mac"></svg-icon>
|
||||||
|
</div>
|
||||||
|
<div class="titlebar-button titlebar-minimize button-style-mac" @click="minimize">
|
||||||
|
<svg-icon name="window-minimize" :size="button_size_mac"></svg-icon>
|
||||||
|
</div>
|
||||||
|
<div class="titlebar-button titlebar-maximize button-style-mac" @click="toggleMaximize">
|
||||||
|
<svg-icon name="window-maximize" :size="button_size_mac"></svg-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<img src="@/assets/vw.png" class="titlebar-icon">
|
<img src="@/assets/vw.png" class="titlebar-icon">
|
||||||
<div class="titlebar-icon-title">
|
<div class="titlebar-icon-title">
|
||||||
Wallitor
|
Wallitor
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="mode == 'win'">
|
|
||||||
<div class="titlebar-button-wrapper colbox">
|
<div class="titlebar-button-wrapper colbox">
|
||||||
<div class="titlebar-button" id="titlebar-minimize" @click="minimize">
|
<div class="titlebar-button" id="titlebar-settings" :class="{
|
||||||
|
'button-style-win': mode == 'win'
|
||||||
|
}" @click="openSettings">
|
||||||
|
<div class="titlebar-button-rect">
|
||||||
|
<svg-icon name="setting" :size="button_size_default"></svg-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template v-if="mode == 'win'">
|
||||||
|
<div class="titlebar-button titlebar-minimize button-style-win" @click="minimize">
|
||||||
<div class="titlebar-button-rect">
|
<div class="titlebar-button-rect">
|
||||||
<svg-icon name="window-minimize" :width="button_size_default" :height="button_size_default"></svg-icon>
|
<svg-icon name="window-minimize" :size="button_size_default"></svg-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="titlebar-button" id="titlebar-maximize" @click="toggleMaximize">
|
<div class="titlebar-button titlebar-maximize button-style-win" @click="toggleMaximize">
|
||||||
<template v-if="maximized">
|
<template v-if="maximized">
|
||||||
<div class="titlebar-button-rect">
|
<div class="titlebar-button-rect">
|
||||||
<svg-icon name="window-maximized" :width="button_size_alter" :height="button_size_alter"></svg-icon>
|
<svg-icon name="window-maximized" :size="button_size_alter"></svg-icon>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="titlebar-button-rect">
|
<div class="titlebar-button-rect">
|
||||||
<svg-icon name="window-maximize" :width="button_size_alter" :height="button_size_alter"></svg-icon>
|
<svg-icon name="window-maximize" :size="button_size_alter"></svg-icon>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="titlebar-button" id="titlebar-close" @click="close">
|
<div class="titlebar-button titlebar-close button-style-win" @click="close">
|
||||||
<div class="titlebar-button-rect">
|
<div class="titlebar-button-rect">
|
||||||
<svg-icon name="window-close" :width="button_size_default" :height="button_size_default"></svg-icon>
|
<svg-icon name="window-close" :size="button_size_default"></svg-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import SvgIcon from '@/components/SvgIcon.vue';
|
import SvgIcon from '@/components/SvgIcon.vue';
|
||||||
import { ref, defineProps } from 'vue'
|
import { onMounted, ref, computed } from 'vue'
|
||||||
import type { PropType } from 'vue'
|
|
||||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useStore } from 'vuex';
|
||||||
|
import type { Settings } from '@/ts/types';
|
||||||
const appWindow = getCurrentWebviewWindow();
|
const appWindow = getCurrentWebviewWindow();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
type Mode = "win" | "mac";
|
type Mode = "win" | "mac";
|
||||||
|
|
||||||
const maximized = ref(false);
|
const maximized = ref(false);
|
||||||
const button_size_default = ref("18px");
|
const button_size_default = ref("18px");
|
||||||
const button_size_alter = ref("15px")
|
const button_size_alter = ref("15px")
|
||||||
const props = defineProps({
|
const button_size_mac = ref("11px")
|
||||||
mode: {
|
const store = useStore();
|
||||||
type: String as PropType<Mode>,
|
const settings = computed<Settings>(() => store.state.settings);
|
||||||
default: "win"
|
const mode = computed<Mode>(() => settings.value.title_bar);
|
||||||
}
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log(mode);
|
||||||
})
|
})
|
||||||
|
|
||||||
function minimize() {
|
function minimize() {
|
||||||
console.log(111)
|
|
||||||
appWindow.minimize()
|
appWindow.minimize()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +88,11 @@ function toggleMaximize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
appWindow.close()
|
appWindow.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function openSettings() {
|
||||||
|
router.push("settings");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -92,7 +101,7 @@ function close() {
|
|||||||
position: relative;
|
position: relative;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: var(--titlebar-height);
|
height: var(--titlebar-height);
|
||||||
padding: 5px;
|
padding: 4px;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,16 +115,18 @@ function close() {
|
|||||||
|
|
||||||
.titlebar-icon-title {
|
.titlebar-icon-title {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 20px;
|
font-size: 23px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titlebar-icon {
|
.titlebar-icon {
|
||||||
height: calc(var(--titlebar-height) - 10px);
|
height: var(--titlebar-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
.titlebar-button-wrapper {
|
.titlebar-button-wrapper {
|
||||||
height: var(--titlebar-height);
|
height: calc(var(--titlebar-height) - 4px);
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
place-self: center;
|
place-self: center;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
@@ -125,18 +136,19 @@ function close() {
|
|||||||
backdrop-filter: blur(10px) saturate(180%);
|
backdrop-filter: blur(10px) saturate(180%);
|
||||||
box-shadow: var(--shadow-edge-glow), var(--shadow);
|
box-shadow: var(--shadow-edge-glow), var(--shadow);
|
||||||
background-color: var(--bg-color-alpha);
|
background-color: var(--bg-color-alpha);
|
||||||
|
z-index: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titlebar-button {
|
.button-style-win.titlebar-button {
|
||||||
height: calc(var(--titlebar-height) - 6px);
|
height: 30px;
|
||||||
width: calc(var(--titlebar-height) - 6px);
|
width: 30px;
|
||||||
padding-top: 3px;
|
padding-top: 3px;
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titlebar-button-rect {
|
.titlebar-button-rect {
|
||||||
height: 34px;
|
height: 30px;
|
||||||
width: 34px;
|
width: 30px;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
transition: .3s;
|
transition: .3s;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -144,20 +156,67 @@ function close() {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#titlebar-minimize {
|
#titlebar-settings {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-style-win#titlebar-settings {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#titlebar-close {
|
.button-style-win.titlebar-close {
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#titlebar-minimize .titlebar-button-rect:hover,
|
#titlebar-settings .titlebar-button-rect:hover,
|
||||||
#titlebar-maximize .titlebar-button-rect:hover {
|
.button-style-win.titlebar-minimize .titlebar-button-rect:hover,
|
||||||
|
.button-style-win.titlebar-maximize .titlebar-button-rect:hover {
|
||||||
background-color: var(--bg-hover-fill);
|
background-color: var(--bg-hover-fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
#titlebar-close .titlebar-button-rect:hover {
|
.button-style-win.titlebar-close .titlebar-button-rect:hover {
|
||||||
background-color: var(--bg-hover-fill-close);
|
background-color: var(--bg-hover-fill-close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.button-style-mac.titlebar-button {
|
||||||
|
width: 13px;
|
||||||
|
height: 13px;
|
||||||
|
border-radius: 100%;
|
||||||
|
margin-left: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #000000b4
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-style-mac.titlebar-minimize {
|
||||||
|
background: #FFBB39;
|
||||||
|
border: 1px solid #CFA64E;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-style-mac.titlebar-maximize {
|
||||||
|
background: #606060;
|
||||||
|
border: 1px solid #656565;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-style-mac:hover.titlebar-maximize {
|
||||||
|
background: #00CD4E;
|
||||||
|
border: 1px solid #0EA642;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-style-mac.titlebar-close {
|
||||||
|
background: #FF5D5B;
|
||||||
|
border: 1px solid #CF544D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-style-mac svg {
|
||||||
|
opacity: 0;
|
||||||
|
transition: .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-style-mac:hover svg {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -4,10 +4,13 @@ import router from './router'
|
|||||||
import "virtual:svg-icons-register";
|
import "virtual:svg-icons-register";
|
||||||
import globalComponents from '@/components/install'
|
import globalComponents from '@/components/install'
|
||||||
import "@/style/global.css"
|
import "@/style/global.css"
|
||||||
|
import {store} from '@/store'
|
||||||
|
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(router);
|
app.use(router);
|
||||||
app.use(globalComponents);
|
app.use(globalComponents);
|
||||||
|
app.use(store)
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
@@ -10,12 +10,9 @@ const router = createRouter({
|
|||||||
component: HomeView
|
component: HomeView
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/about',
|
path: '/settings',
|
||||||
name: 'about',
|
name: 'settings',
|
||||||
// route level code-splitting
|
component: () => import('../views/SettingsView.vue')
|
||||||
// this generates a separate chunk (About.[hash].js) for this route
|
|
||||||
// which is lazy-loaded when the route is visited.
|
|
||||||
component: () => import('../views/AboutView.vue')
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,162 @@
|
|||||||
|
import { createStore } from 'vuex'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
import type { ResourceDir, wpConfig, Cell, Settings } from '@/ts/types'
|
||||||
|
import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||||
|
import { emit } from '@tauri-apps/api/event'
|
||||||
|
import { enable, isEnabled, disable } from '@tauri-apps/plugin-autostart'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
function arrayBufferToString(buffer: ArrayBuffer): string {
|
||||||
|
const decoder = new TextDecoder('utf-8')
|
||||||
|
return decoder.decode(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_auto_start(settings: Settings) {
|
||||||
|
const status = settings.auto_start
|
||||||
|
isEnabled().then((current) => {
|
||||||
|
if (current == true && status == false) {
|
||||||
|
disable().then(() =>
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: '已经禁用开机自启'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} else if (current == false && status == true) {
|
||||||
|
enable().then(() =>
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: '已经启用开机自启'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const support_ext = ['.jpg', '.png', '.gif', '.webp']
|
||||||
|
const support_ext_map: { [key in (typeof support_ext)[number]]: string } = {
|
||||||
|
'.jpg': 'image/jpeg',
|
||||||
|
'.png': 'image/png',
|
||||||
|
'.gif': 'image/gif',
|
||||||
|
'.webp': 'image/webp'
|
||||||
|
}
|
||||||
|
|
||||||
|
type VideoWindow = null | WebviewWindow
|
||||||
|
export const store = createStore({
|
||||||
|
state() {
|
||||||
|
return {
|
||||||
|
wpList: [] as Cell[],
|
||||||
|
videoWindow: null as VideoWindow,
|
||||||
|
settings: {
|
||||||
|
title_bar: 'win',
|
||||||
|
auto_pause: true,
|
||||||
|
auto_start: false,
|
||||||
|
version: '1.0.0'
|
||||||
|
} as Settings
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
getWpList(state) {
|
||||||
|
state.wpList = []
|
||||||
|
invoke('read_resource_dir', {}).then((res) => {
|
||||||
|
const resource = JSON.parse(res as string) as ResourceDir
|
||||||
|
for (const id of Object.keys(resource.files)) {
|
||||||
|
const dir = resource.files[id]
|
||||||
|
if ('config.json' in dir)
|
||||||
|
invoke('get_file', {
|
||||||
|
path: `${id}\\config.json`
|
||||||
|
}).then((cfg) => {
|
||||||
|
const config: wpConfig = JSON.parse(arrayBufferToString(cfg as ArrayBuffer))
|
||||||
|
let hasPreview = false
|
||||||
|
for (const ext of support_ext) {
|
||||||
|
const filename = 'preview' + ext
|
||||||
|
if (filename in dir) {
|
||||||
|
hasPreview = true
|
||||||
|
invoke('get_file', {
|
||||||
|
path: dir[filename]
|
||||||
|
}).then((res) => {
|
||||||
|
const binary_data_arr = new Uint8Array(res as number[])
|
||||||
|
const blob = new Blob([binary_data_arr], {
|
||||||
|
type: support_ext_map[ext]
|
||||||
|
})
|
||||||
|
const imageUrl = URL.createObjectURL(blob)
|
||||||
|
invoke('get_file', {
|
||||||
|
path: `${id}\\config.json`
|
||||||
|
}).then((cfg) => {
|
||||||
|
const config: wpConfig = JSON.parse(arrayBufferToString(cfg as ArrayBuffer))
|
||||||
|
state.wpList.push({
|
||||||
|
path: id,
|
||||||
|
img: imageUrl,
|
||||||
|
config: config
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasPreview) {
|
||||||
|
state.wpList.push({
|
||||||
|
path: id,
|
||||||
|
img: '',
|
||||||
|
config: config
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
new_wallpaper_window(
|
||||||
|
state,
|
||||||
|
payload: {
|
||||||
|
title: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const window_options = {
|
||||||
|
title: payload.title,
|
||||||
|
url: payload.url,
|
||||||
|
fullscreen: true,
|
||||||
|
shadow: false,
|
||||||
|
decorations: false,
|
||||||
|
transparent: true
|
||||||
|
}
|
||||||
|
state.videoWindow = new WebviewWindow(payload.title, window_options)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
async apply_wallpaper(
|
||||||
|
{ state, commit },
|
||||||
|
payload: {
|
||||||
|
title: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
return new Promise<boolean>((resolve) => {
|
||||||
|
if (state.videoWindow) {
|
||||||
|
state.videoWindow.destroy().then(() => {
|
||||||
|
commit('new_wallpaper_window', payload)
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
commit('new_wallpaper_window', payload)
|
||||||
|
resolve(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async get_settings({ state }) {
|
||||||
|
const settings = await invoke('get_settings')
|
||||||
|
state.settings = JSON.parse(settings as string) as Settings
|
||||||
|
check_auto_start(state.settings)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async set_settings({ state }, payload: Settings) {
|
||||||
|
state.settings = payload
|
||||||
|
const settings: boolean = await invoke('set_settings', {
|
||||||
|
settings: state.settings
|
||||||
|
})
|
||||||
|
if (state.settings.auto_pause) {
|
||||||
|
await emit('start_auto_pause')
|
||||||
|
} else await emit('stop_auto_pause')
|
||||||
|
check_auto_start(state.settings)
|
||||||
|
return settings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import type { Store } from 'vuex'
|
||||||
|
import type { Cell } from '@/ts/types'
|
||||||
|
|
||||||
|
declare module 'vuex' {
|
||||||
|
export * from 'vuex/types/index.d.ts'
|
||||||
|
export * from 'vuex/types/helpers.d.ts'
|
||||||
|
export * from 'vuex/types/logger.d.ts'
|
||||||
|
export * from 'vuex/types/vue.d.ts'
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'vue' {
|
||||||
|
// 声明自己的 store state
|
||||||
|
interface State {
|
||||||
|
wpList: Cell[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为 `this.$store` 提供类型声明
|
||||||
|
interface ComponentCustomProperties {
|
||||||
|
$store: Store<State>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
@keyframes cui-dialog-appear {
|
||||||
|
0% {
|
||||||
|
/* opacity: 0%; */
|
||||||
|
transform: translate(-50%, -50%) scale(0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
/* opacity: 100%; */
|
||||||
|
transform: translate(-50%, -50%) scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cui-dialog-disappear {
|
||||||
|
0% {
|
||||||
|
opacity: 100%;
|
||||||
|
transform: translate(-50%, -50%) scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0%;
|
||||||
|
transform: translate(-50%, -50%) scale(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cui-dialog-blur {
|
||||||
|
0% {
|
||||||
|
opacity: 0%;
|
||||||
|
/* backdrop-filter: blur(0px); */
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 100%;
|
||||||
|
/* backdrop-filter: blur(10px); */
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,67 +1,140 @@
|
|||||||
.colbox{
|
.colbox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rowbox{
|
.rowbox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
--text-shadow-color: #b3b3b3ae;
|
--text-shadow-color: #b3b3b3ae;
|
||||||
--bg-color-solid: #fcfcfc;
|
--bg-color-solid: #fcfcfc;
|
||||||
--bg-color-alter: #ffffff;
|
--bg-color-alter: #ffffff;
|
||||||
--bg-color: #ffffffae;
|
--bg-color: #ffffffae;
|
||||||
--text-color: #1c1c1c;
|
--text-color: #1c1c1c;
|
||||||
--bd-color: #bbbbbbce;
|
--bd-color: #b2b2b2da;
|
||||||
--login-button-bg: #9acdff;
|
--text-active: #7cbeff;
|
||||||
--login-button-bd: #c8c8c8;
|
--titlebar-height: 40px;
|
||||||
--login-button-hover: #7db7f0;
|
--shadow-edge-glow: inset 1px 1px 1px -.5px rgba(255, 255, 255, .2), inset -1px -1px 1px -.5px rgba(255, 255, 255, .12), inset 0 0 4px rgba(255, 255, 255, .4);
|
||||||
--branch-viewing-color: rgb(122, 212, 215);
|
--shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .06);
|
||||||
--branch-viewing-hover-color: rgb(102, 177, 180);
|
--bg-color-alpha: hsla(240, 17%, 91%, 0.68);
|
||||||
--delete-box-left-border: #f56c6c;
|
--bg-color-alpha-darker: hsla(0, 22%, 96%, 0.948);
|
||||||
--delete-box-bg: #f56c6c42;
|
--bg-hover-fill: rgba(172, 172, 193, 0.24);
|
||||||
--delete-box-title: #511f1f;
|
--bg-hover-fill-close: rgba(239, 90, 90, 0.579);
|
||||||
--delete-box-text: black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html.dark {
|
html.dark {
|
||||||
--text-shadow-color: #686868af;
|
--text-shadow-color: #686868af;
|
||||||
--bg-color-solid: #191919;
|
--bg-color-solid: #191919;
|
||||||
--bg-color-alter: #2d2d2d;
|
--bg-color-alter: #2d2d2d;
|
||||||
--bg-color: #2a2a2ace;
|
--bg-color: #2a2a2ace;
|
||||||
--text-color: #c0c0c0;
|
--text-color: #c0c0c0;
|
||||||
--bd-color: #7f7f7f7c;
|
--bd-color: #7f7f7f7c;
|
||||||
--titlebar-height: 40px;
|
--titlebar-height: 40px;
|
||||||
--shadow-edge-glow: inset 1px 1px 1px -.5px rgba(255, 255, 255, .12), inset -1px -1px 1px -.5px rgba(255, 255, 255, .04), inset 0 0 4px rgba(255, 255, 255, .06);
|
--shadow-edge-glow: inset 1px 1px 1px -0.5px rgba(255, 255, 255, 0.12),
|
||||||
--shadow: 0 10px 15px -3px rgb(0 0 0 / .2), 0 4px 6px -4px rgb(0 0 0 / .16);
|
inset -1px -1px 1px -0.5px rgba(255, 255, 255, 0.04), inset 0 0 4px rgba(255, 255, 255, 0.06);
|
||||||
--bg-color-alpha: hsl(230 12% 14% / .68);
|
--shadow: 0 10px 15px -3px rgb(0 0 0 / 0.2), 0 4px 6px -4px rgb(0 0 0 / 0.16);
|
||||||
--bg-color-alpha-darker: hsl(230 12% 14% / .93);
|
--bg-color-alpha: hsla(240, 1%, 14%, 0.68);
|
||||||
--bg-hover-fill: rgb(131 131 145 / 24%);
|
--bg-color-alpha-darker: hsla(0, 0%, 14%, 0.948);
|
||||||
--bg-hover-fill-close: rgba(211, 86, 86, 0.579);
|
--bg-hover-fill: rgb(131 131 145 / 24%);
|
||||||
|
--bg-hover-fill-close: rgba(211, 86, 86, 0.579);
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
font-family:
|
||||||
|
system-ui,
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
'Segoe UI',
|
||||||
|
Roboto,
|
||||||
|
'Helvetica Neue',
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type='text'] {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background-color: var(--bg-color-alter);
|
||||||
|
border-bottom: 2px solid var(--bd-color);
|
||||||
|
border-radius: 3px;
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 6px;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='text']:focus {
|
||||||
|
background-color: var(--bg-color-solid);
|
||||||
|
border-bottom: 2px solid var(--text-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
outline: none;
|
||||||
|
border: 1px solid var(--bd-color);
|
||||||
|
border-radius: 3px;
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 5px;
|
||||||
|
transition: 0.3s;
|
||||||
|
background-color: var(--bg-color-alter);
|
||||||
|
font-family:
|
||||||
|
system-ui,
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
'Segoe UI',
|
||||||
|
Roboto,
|
||||||
|
'Helvetica Neue',
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:focus {
|
||||||
|
background-color: var(--bg-color-solid);
|
||||||
|
border: 1px solid var(--text-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.apply-button {
|
||||||
|
align-self: flex-end;
|
||||||
|
outline: none;
|
||||||
|
border: solid 1px var(--bd-color);
|
||||||
|
border-radius: 2px;
|
||||||
|
width: 75px;
|
||||||
|
height: 30px;
|
||||||
|
background-color: var(--bg-color-alpha-darker);
|
||||||
|
color: var(--text-color);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apply-button:hover {
|
||||||
|
background-color: var(--bg-hover-fill);
|
||||||
|
}
|
||||||
|
|
||||||
|
.apply-button:active {
|
||||||
|
background-color: var(--bg-color-solid);
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
export interface wpConfig {
|
||||||
|
name: string
|
||||||
|
info: Info
|
||||||
|
option: Option
|
||||||
|
}
|
||||||
|
type WallpaperType = 'Video'
|
||||||
|
export interface Info {
|
||||||
|
media_type: WallpaperType
|
||||||
|
description: string
|
||||||
|
created: number
|
||||||
|
entry_point: string
|
||||||
|
}
|
||||||
|
export interface Option {
|
||||||
|
mute: boolean
|
||||||
|
}
|
||||||
|
export interface Cell {
|
||||||
|
img: string
|
||||||
|
path: string
|
||||||
|
config: wpConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Resource {
|
||||||
|
'config.json': string
|
||||||
|
[filename: string]: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ResourceDir {
|
||||||
|
files: {
|
||||||
|
[resId: string]: Resource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddInfo {
|
||||||
|
name: string
|
||||||
|
preview: string
|
||||||
|
media: string
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EditInfo {
|
||||||
|
path: string
|
||||||
|
name: string
|
||||||
|
preview: string
|
||||||
|
description: string
|
||||||
|
mute: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Settings {
|
||||||
|
title_bar: 'win' | 'mac'
|
||||||
|
auto_start: boolean
|
||||||
|
auto_pause: boolean
|
||||||
|
version: string
|
||||||
|
}
|
||||||
@@ -1,39 +1,131 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ItemCard from '@/components/ItemCard.vue';
|
import ItemCard from '@/components/ItemCard.vue';
|
||||||
import ApplyBar from '@/components/ApplyBar.vue';
|
import ApplyBar from '@/components/ApplyBar.vue';
|
||||||
import { ref, onMounted } from 'vue';
|
import AddItem from '@/components/AddItem.vue';
|
||||||
import { entry } from '@/ts/entry';
|
import { ref, onMounted, computed, nextTick } from 'vue';
|
||||||
interface Config {
|
import CRMenu from '@/components/CRMenu.vue';
|
||||||
name: string,
|
import CRMenuCell from '@/components/CRMenuCell.vue';
|
||||||
img: string
|
import SvgIcon from '@/components/SvgIcon.vue';
|
||||||
}
|
import type { Cell, EditInfo } from '@/ts/types'
|
||||||
const items = ref<Config[]>([{
|
import { useStore } from 'vuex';
|
||||||
name: "test1",
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
img: "https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
|
import { ElMessage } from 'element-plus';
|
||||||
}, {
|
import CDialog from '@/components/CDialog.vue';
|
||||||
name: "test2",
|
import EditItem from '@/components/EditItem.vue';
|
||||||
img: "https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
|
|
||||||
}])
|
const store = useStore();
|
||||||
|
const items = computed<Cell[]>(() => store.state.wpList);
|
||||||
const apply_bar_visible = ref(false);
|
const apply_bar_visible = ref(false);
|
||||||
const applyBar = ref<InstanceType<typeof ApplyBar> | null>(null);
|
const applyBar = ref<InstanceType<typeof ApplyBar> | null>(null);
|
||||||
|
const item_add_visible = ref(false);
|
||||||
|
const r_display = ref(false);
|
||||||
|
const r_data = ref<Cell>({
|
||||||
|
img: "",
|
||||||
|
path: "",
|
||||||
|
config: {
|
||||||
|
name: "",
|
||||||
|
info: {
|
||||||
|
description: "",
|
||||||
|
created: 0,
|
||||||
|
media_type: "Video",
|
||||||
|
entry_point: ""
|
||||||
|
},
|
||||||
|
option: {
|
||||||
|
mute: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const menu = ref<InstanceType<typeof CRMenu> | null>(null);
|
||||||
|
const options = ref<{ name: string, icon: string, handler: (data: Cell) => void }[]>([{
|
||||||
|
name: "删除",
|
||||||
|
icon: "delete",
|
||||||
|
handler: del_wallpaper
|
||||||
|
}, {
|
||||||
|
name: "修改",
|
||||||
|
icon: "edit",
|
||||||
|
handler: edit_wallpaper
|
||||||
|
}])
|
||||||
|
const edit_visible = ref(false);
|
||||||
|
const edit_data = ref<EditInfo>({
|
||||||
|
path: "",
|
||||||
|
name: "",
|
||||||
|
preview: "",
|
||||||
|
description: "",
|
||||||
|
mute: true
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const main = document.querySelector(".home-main") as HTMLElement;
|
store.commit("getWpList");
|
||||||
setTimeout(() => {
|
|
||||||
entry("up", main, 20);
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function openCard(config: Config) {
|
function openCard(config: Cell) {
|
||||||
if (applyBar.value) applyBar.value.open(config);
|
if (applyBar.value) applyBar.value.open(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleRightClick(event: MouseEvent, data: Cell) {
|
||||||
|
r_data.value = data;
|
||||||
|
r_display.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
if (menu.value) menu.value.handleOpen(event.x, event.y);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function del_wallpaper(data: Cell) {
|
||||||
|
invoke("del_folder", {
|
||||||
|
path: data.path
|
||||||
|
}).then((res) => {
|
||||||
|
if (res) {
|
||||||
|
store.commit("getWpList");
|
||||||
|
ElMessage({
|
||||||
|
type: "success",
|
||||||
|
message: `已删除 ${data.path}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: `删除失败`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function edit_wallpaper(data: Cell) {
|
||||||
|
edit_visible.value = true;
|
||||||
|
edit_data.value = {
|
||||||
|
path: data.path,
|
||||||
|
name: data.config.name,
|
||||||
|
preview: data.img,
|
||||||
|
description: data.config.info.description,
|
||||||
|
mute: data.config.option.mute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_edit_close() {
|
||||||
|
edit_visible.value = false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<main class="colbox home-main">
|
<main class="colbox home-main">
|
||||||
<ItemCard v-for="(item, index) in items" :key="index" :config="item" @click="openCard(item)"></ItemCard>
|
<ItemCard v-for="(item, index) in items" :key="index" :cell="item" @click="openCard(item)"
|
||||||
|
@contextmenu.prevent="(e) => handleRightClick(e, item)"></ItemCard>
|
||||||
</main>
|
</main>
|
||||||
<ApplyBar v-model="apply_bar_visible" ref="applyBar"></ApplyBar>
|
<ApplyBar v-model="apply_bar_visible" ref="applyBar"></ApplyBar>
|
||||||
|
<AddItem v-model="item_add_visible"></AddItem>
|
||||||
|
<CRMenu ref="menu" v-model:visible="r_display">
|
||||||
|
<template #content>
|
||||||
|
<CRMenuCell v-for="option in options" :key="option.name" @click="option.handler(r_data); r_display = false;">
|
||||||
|
<template #icon>
|
||||||
|
<SvgIcon size="20px" :name="option.icon" style="color: var(--text-color);"></SvgIcon>
|
||||||
|
</template>
|
||||||
|
{{ option.name }}
|
||||||
|
</CRMenuCell>
|
||||||
|
</template>
|
||||||
|
</CRMenu>
|
||||||
|
<CDialog v-model:visible="edit_visible" height="80%" width="80%">
|
||||||
|
<template #content>
|
||||||
|
<EditItem v-model:data="edit_data" @submit="handle_edit_close"></EditItem>
|
||||||
|
</template>
|
||||||
|
</CDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
<template>
|
||||||
|
<div class="settings-wrapper">
|
||||||
|
<div class="settings-back colbox" @click="back_home">
|
||||||
|
<SvgIcon name="direction-left"></SvgIcon>
|
||||||
|
<div class="settings-back-text">返回</div>
|
||||||
|
</div>
|
||||||
|
<table class="settings-table">
|
||||||
|
<tbody class="setting-table-body">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="settings-label">
|
||||||
|
<div class="settings-label-title">标题栏样式</div>
|
||||||
|
<div class="settings-label-subtitle">选择选题栏关闭按钮样式</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<el-select @change="save" v-model="settings.title_bar">
|
||||||
|
<el-option label="Windows" value="win"></el-option>
|
||||||
|
<el-option label="OSX" value="mac"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="settings-label">
|
||||||
|
<div class="settings-label-title">开机自启</div>
|
||||||
|
<div class="settings-label-subtitle">开机自启</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td><el-switch @change="save" v-model="settings.auto_start"></el-switch></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="settings-label">
|
||||||
|
<div class="settings-label-title">最大化自动暂停</div>
|
||||||
|
<div class="settings-label-subtitle">最大化自动暂停</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td><el-switch @change="save" v-model="settings.auto_pause"></el-switch></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ElSelect, ElSwitch, ElOption, ElMessage } from 'element-plus';
|
||||||
|
import { entry } from '@/ts/entry';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useStore } from 'vuex';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import SvgIcon from '@/components/SvgIcon.vue';
|
||||||
|
import type { Settings } from '@/ts/types';
|
||||||
|
const router = useRouter();
|
||||||
|
const store = useStore();
|
||||||
|
const settings = ref<Settings>(store.state.settings);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const table_body = document.querySelector(".setting-table-body") as HTMLElement;
|
||||||
|
entry("left", table_body, 50);
|
||||||
|
})
|
||||||
|
|
||||||
|
function back_home() {
|
||||||
|
router.push("/")
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
store.dispatch("set_settings", settings.value).then((status) => {
|
||||||
|
if (status as boolean) {
|
||||||
|
ElMessage({
|
||||||
|
type: "success",
|
||||||
|
message: "设置已更改"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "设置更改失败"
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.settings-wrapper {
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
width: calc(100% - 60px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-back {
|
||||||
|
color: var(--text-color);
|
||||||
|
padding: 8px;
|
||||||
|
margin: 5px;
|
||||||
|
width: fit-content;
|
||||||
|
border-radius: 10px;
|
||||||
|
transition: .3s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-back:hover {
|
||||||
|
background-color: var(--bg-color-alter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-back:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-table {
|
||||||
|
width: calc(100% - 80px);
|
||||||
|
margin-left: 40px;
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-table td,
|
||||||
|
th {
|
||||||
|
padding: 5px;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-label-title {
|
||||||
|
margin-bottom: 3px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-label-subtitle {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 300;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-back-text {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
margin-left: 4px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,5 +7,10 @@
|
|||||||
{
|
{
|
||||||
"path": "./tsconfig.app.json"
|
"path": "./tsconfig.app.json"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"vuex": ["./node_modules/vuex/types"]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite App</title>
|
||||||
|
<style>
|
||||||
|
html,body{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
#player{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transition: .5s ease-in-out;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<video id="player"></video>
|
||||||
|
<script type="module" src="./playback.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
import { listen } from '@tauri-apps/api/event'
|
||||||
|
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||||
|
interface Params {
|
||||||
|
url?: string
|
||||||
|
mute?: string
|
||||||
|
auto_pause?: string
|
||||||
|
}
|
||||||
|
function getSearchParamsAsObject() {
|
||||||
|
const params = new URLSearchParams(window.location.search)
|
||||||
|
const paramsObject = {}
|
||||||
|
params.forEach((value, key) => {
|
||||||
|
paramsObject[key] = value
|
||||||
|
})
|
||||||
|
return paramsObject
|
||||||
|
}
|
||||||
|
|
||||||
|
listen('video_pause', () => {
|
||||||
|
const player = document.getElementById('player') as HTMLVideoElement
|
||||||
|
if (player) player.pause()
|
||||||
|
})
|
||||||
|
|
||||||
|
class player {
|
||||||
|
playing: boolean
|
||||||
|
params: Params
|
||||||
|
interval: number
|
||||||
|
constructor(params: Params) {
|
||||||
|
this.params = params
|
||||||
|
this.playing = false
|
||||||
|
this.interval = 0
|
||||||
|
}
|
||||||
|
init_player(videoUrl: string) {
|
||||||
|
const player = document.getElementById('player') as HTMLVideoElement
|
||||||
|
if (player) {
|
||||||
|
player.src = videoUrl
|
||||||
|
player.play()
|
||||||
|
this.playing = true
|
||||||
|
if (this.params.mute) {
|
||||||
|
player.muted = JSON.parse(this.params.mute)
|
||||||
|
}
|
||||||
|
player.loop = true
|
||||||
|
setTimeout(() => {
|
||||||
|
player.style.opacity = '1'
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
if (this.params.auto_pause && this.params.auto_pause === 'true') {
|
||||||
|
this.detect_zoom()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detect_zoom() {
|
||||||
|
this.clear_detection()
|
||||||
|
this.interval = window.setInterval(() => {
|
||||||
|
invoke('any_zoomed').then((res) => {
|
||||||
|
if (res as boolean) {
|
||||||
|
if (this.playing) {
|
||||||
|
const player = document.getElementById('player') as HTMLVideoElement
|
||||||
|
if (player) {
|
||||||
|
player.pause()
|
||||||
|
this.playing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!this.playing) {
|
||||||
|
const player = document.getElementById('player') as HTMLVideoElement
|
||||||
|
if (player) {
|
||||||
|
player.play()
|
||||||
|
this.playing = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
clear_detection() {
|
||||||
|
if (this.interval) {
|
||||||
|
clearInterval(this.interval)
|
||||||
|
this.interval = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let player_instance: player | null = null
|
||||||
|
|
||||||
|
window.onload = () => {
|
||||||
|
invoke('set_wallpaper', {
|
||||||
|
title: 'wallitor_video_playback'
|
||||||
|
}).then((res) => {
|
||||||
|
if (!res) {
|
||||||
|
console.error('Unable to set wallpaper.')
|
||||||
|
const win = getCurrentWindow()
|
||||||
|
win.destroy()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const params: Params = getSearchParamsAsObject()
|
||||||
|
if (params.url) {
|
||||||
|
invoke('get_file', {
|
||||||
|
path: params.url
|
||||||
|
}).then((res) => {
|
||||||
|
const binary_data_arr = new Uint8Array(res as number[])
|
||||||
|
const blob = new Blob([binary_data_arr], { type: 'video/mp4' })
|
||||||
|
const videoUrl = URL.createObjectURL(blob)
|
||||||
|
player_instance = new player(params)
|
||||||
|
player_instance.init_player(videoUrl)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
listen('stop_auto_pause', () => {
|
||||||
|
if (player_instance) player_instance.clear_detection()
|
||||||
|
})
|
||||||
|
|
||||||
|
listen('start_auto_pause', () => {
|
||||||
|
if (player_instance) player_instance.detect_zoom()
|
||||||
|
})
|
||||||
@@ -3,6 +3,7 @@ import { fileURLToPath, URL } from 'node:url'
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||||
|
import ElementPlus from 'unplugin-element-plus/vite'
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
|
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
|
||||||
|
|
||||||
@@ -22,7 +23,10 @@ export default defineConfig({
|
|||||||
path.resolve(__dirname, "src/assets/svgs"),
|
path.resolve(__dirname, "src/assets/svgs"),
|
||||||
],
|
],
|
||||||
symbolId: "icon-[name]"
|
symbolId: "icon-[name]"
|
||||||
})
|
}),
|
||||||
|
ElementPlus({
|
||||||
|
// options
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
@@ -36,5 +40,11 @@ export default defineConfig({
|
|||||||
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
|
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
|
||||||
// 为调试构建生成源代码映射 (sourcemap)
|
// 为调试构建生成源代码映射 (sourcemap)
|
||||||
sourcemap: !!process.env.TAURI_DEBUG,
|
sourcemap: !!process.env.TAURI_DEBUG,
|
||||||
|
rollupOptions: {
|
||||||
|
input: {
|
||||||
|
main: path.resolve(__dirname, 'index.html'),
|
||||||
|
video: path.resolve(__dirname, 'video/index.html'),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||