setting ui

master
cast1e 2024-10-16 20:50:22 +08:00
parent 31fcf4ea83
commit b8f1b81c0f
11 changed files with 225 additions and 75 deletions

View File

@ -34,6 +34,6 @@ playerInstance* player_instance = NULL;
return set_as_wallpaper(window_title); return set_as_wallpaper(window_title);
} }
extern "C" __declspec(dllexport) BOOL anyMaximized() { extern "C" __declspec(dllexport) BOOL any_maximized() {
return !detectWindowMaximized(); return !detectWindowMaximized();
} }

View File

@ -4048,6 +4048,7 @@ name = "wallitor-gui"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"lazy_static",
"libloading 0.8.5", "libloading 0.8.5",
"serde", "serde",
"serde_json", "serde_json",

View File

@ -25,4 +25,5 @@ tauri-plugin-fs = "2.0.0-rc"
tauri-plugin-dialog = "2.0.0-rc" tauri-plugin-dialog = "2.0.0-rc"
chrono = "0.4.38" chrono = "0.4.38"
libloading = "0.8.5" libloading = "0.8.5"
lazy_static = "1.5.0"

View File

@ -1,49 +1,52 @@
use libloading::{Library, Symbol}; use libloading::{self,Library};
use std::{ffi::CString, rc::Rc, sync::Arc}; use std::{ffi::CString, ops::Deref, sync::Arc};
use lazy_static::lazy_static;
struct CoreModule<'a>{ struct CoreModule{
module:Arc<Library>, _module:Arc<Library>,
set_wallpaper:Arc<Symbol<'a,unsafe extern "C" fn(*const i8) -> i8>>, pub set_wallpaper:libloading::os::windows::Symbol<unsafe extern "C" fn(*const i8) -> i8>,
any_maximized:Arc<Symbol<'a,unsafe extern "C" fn() -> i8>> pub any_maximized:libloading::os::windows::Symbol<unsafe extern "C" fn() -> i8>
} }
impl<'a> CoreModule<'a> { impl CoreModule {
fn new(library_path: &str) -> Result<Self, libloading::Error> { fn new(library_path: &str) -> CoreModule {
let lib = Arc::new(unsafe { Library::new(library_path).unwrap() }); // 首先加载动态库
let _module = Arc::new(unsafe { Library::new(library_path).unwrap()});
let set_fn:&Symbol<'a,unsafe extern "C" fn(*const i8) -> i8> = unsafe { // 然后获取符号
&lib.get::<unsafe extern "C" fn(*const i8) -> i8>(b"set_wallpaper\0")? 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() };
let any_fn:&Symbol<'a,unsafe extern "C" fn() -> i8> = unsafe { // 返回初始化的结构体
&lib.get::<unsafe extern "C" fn() -> i8>(b"any_maximized\0")? CoreModule {
}; _module,
set_wallpaper,
Ok(CoreModule { any_maximized,
module: Arc::clone(&lib),
set_wallpaper:Arc::new(set_fn),
any_maximized:Arc::new(any_fn),
})
} }
} }
}
lazy_static!{
static ref core_module:CoreModule = CoreModule::new("wallitor-core.dll");
}
#[tauri::command] #[tauri::command]
pub async fn set_wallpaper(title: String) -> bool { pub async fn set_wallpaper(title: String) -> bool {
let lib = unsafe { Library::new("wallitor-core.dll").unwrap() };
type SetFn = unsafe extern "C" fn(*const i8) -> i8;
let set: Symbol<SetFn> = unsafe { lib.get(b"set_wallpaper\0").unwrap() };
let title = CString::new(title.to_string()).unwrap(); let title = CString::new(title.to_string()).unwrap();
unsafe { unsafe {
let res = set(title.as_ptr()); let res = core_module.set_wallpaper.deref()(title.as_ptr());
if res == 0 { if res == 0 {
drop(lib);
return false; return false;
}; };
} }
drop(lib); true
return true;
} }
#[tauri::command] #[tauri::command]
pub async fn anyZoomed()->bool{ pub async fn any_zoomed()->bool{
let Library unsafe {
let res = core_module.any_maximized.deref()();
if res == 0{
return false;
}
}
true
} }

View File

@ -1,6 +1,7 @@
mod setup; mod setup;
mod handler; mod handler;
mod reader; mod reader;
extern crate lazy_static;
#[cfg_attr(mobile, tauri::mobile_entry_point)] #[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() { pub fn run() {
@ -15,6 +16,7 @@ pub fn run() {
handler::wallpaper::new_wallpaper, handler::wallpaper::new_wallpaper,
handler::apply::set_wallpaper, handler::apply::set_wallpaper,
handler::wallpaper::edit_wallpaper, handler::wallpaper::edit_wallpaper,
handler::apply::any_zoomed
]) ])
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");

View File

@ -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="1729046702329" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3377" data-darkreader-inline-fill="" 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="#666666" p-id="3378" data-darkreader-inline-fill="" style="--darkreader-inline-fill: #4d5356;"></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="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>

Before

Width:  |  Height:  |  Size: 1007 B

After

Width:  |  Height:  |  Size: 907 B

View File

@ -107,11 +107,10 @@ function open(conFig: Cell) {
} }
function apply() { function apply() {
store.commit("apply_wallpaper", { store.dispatch("apply_wallpaper", {
url: `/video/?url=${cell.value.path}\\res\\${cell.value.config.info.entry_point}&mute=${cell.value.config.option.mute}`, url: `/video/?url=${cell.value.path}\\res\\${cell.value.config.info.entry_point}&mute=${cell.value.config.option.mute}`,
title: "wallitor_video_playback" title: "wallitor_video_playback"
}) }).then(()=>appWindow.minimize())
appWindow.minimize();
} }
</script> </script>

View File

@ -25,6 +25,10 @@ const props = defineProps({
</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 +47,7 @@ const props = defineProps({
box-shadow: 0 0 1px 6px transparent; box-shadow: 0 0 1px 6px transparent;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
animation: item-card-entry 0.3s ease-out;
} }
.item-card-main { .item-card-main {

View File

@ -2,6 +2,7 @@ import { createStore } from 'vuex'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import type { ResourceDir, wpConfig, Cell } from '@/ts/types' import type { ResourceDir, wpConfig, Cell } from '@/ts/types'
import { WebviewWindow } from '@tauri-apps/api/webviewWindow' import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
import { emit } from '@tauri-apps/api/event'
function arrayBufferToString(buffer: ArrayBuffer): string { function arrayBufferToString(buffer: ArrayBuffer): string {
const decoder = new TextDecoder('utf-8') const decoder = new TextDecoder('utf-8')
@ -21,7 +22,7 @@ export const store = createStore({
state() { state() {
return { return {
wpList: [] as Cell[], wpList: [] as Cell[],
videoWindow: null as VideoWindow videoWindow: null as VideoWindow,
} }
}, },
mutations: { mutations: {
@ -73,7 +74,7 @@ export const store = createStore({
} }
}) })
}, },
apply_wallpaper( new_wallpaper_window(
state, state,
payload: { payload: {
title: string title: string
@ -88,12 +89,29 @@ export const store = createStore({
decorations: false, decorations: false,
transparent: true transparent: true
} }
if (state.videoWindow) state.videoWindow = new WebviewWindow(payload.title, window_options);
state.videoWindow.destroy().then((_) => {
state.videoWindow = new WebviewWindow(payload.title, window_options)
})
else state.videoWindow = new WebviewWindow(payload.title, window_options)
} }
}, },
actions: {} 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);
}
})
}
}
}) })

View File

@ -1,28 +1,98 @@
<template> <template>
<div @click="back_home"> <div class="settings-wrapper">
<div class="settings-back" @click="back_home">
<SvgIcon name="direction-left"></SvgIcon> <SvgIcon name="direction-left"></SvgIcon>
返回 返回
</div> </div>
<el-form label-position="right"> <table class="settings-table">
<el-form-item label="标题栏样式"> <tbody class="setting-table-body">
<el-switch></el-switch> <tr>
</el-form-item> <td><div class="settings-label">
<el-form-item label="开机自启"> <div class="settings-label-title">标题栏样式</div>
<el-switch></el-switch> <div class="settings-label-subtitle">选择选题栏关闭按钮样式</div>
</el-form-item> </div></td>
<el-form-item label="最大化自动暂停"> <td><el-switch></el-switch></td>
<el-switch></el-switch> </tr>
</el-form-item> <tr>
</el-form> <td><div class="settings-label">
<div class="settings-label-title">开机自启</div>
<div class="settings-label-subtitle">开机自启</div>
</div></td>
<td><el-switch></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></el-switch></td>
</tr>
</tbody>
</table>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ElForm, ElFormItem, ElSwitch, ElOption } from 'element-plus'; import { ElForm, ElFormItem, ElSwitch, ElOption } from 'element-plus';
import { entry } from '@/ts/entry';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { onMounted } from 'vue';
import SvgIcon from '@/components/SvgIcon.vue'; import SvgIcon from '@/components/SvgIcon.vue';
const router = useRouter(); const router = useRouter();
onMounted(()=>{
const table_body = document.querySelector(".setting-table-body") as HTMLElement;
entry("left",table_body,50);
})
function back_home() { function back_home() {
router.push("/") router.push("/")
} }
</script> </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;
}
</style>

View File

@ -1,7 +1,8 @@
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { listen } from '@tauri-apps/api/event'
import { getCurrentWindow } from '@tauri-apps/api/window' import { getCurrentWindow } from '@tauri-apps/api/window'
interface Params { interface Params {
url?: string, url?: string
mute?: string mute?: string
} }
function getSearchParamsAsObject() { function getSearchParamsAsObject() {
@ -13,15 +14,73 @@ function getSearchParamsAsObject() {
return paramsObject 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)
}
this.detect_zoom();
}
detect_zoom(){
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)
}
}
let player_instance:player | null = null;
window.onload = () => { window.onload = () => {
invoke('set_wallpaper', { invoke('set_wallpaper', {
title: 'wallitor_video_playback' title: 'wallitor_video_playback'
}).then((res) => { }).then((res) => {
if (!res) { if (!res) {
console.error("Unable to set wallpaper."); console.error('Unable to set wallpaper.')
const win = getCurrentWindow(); const win = getCurrentWindow()
win.destroy(); win.destroy()
return; return
} }
const params: Params = getSearchParamsAsObject() const params: Params = getSearchParamsAsObject()
if (params.url) { if (params.url) {
@ -31,16 +90,8 @@ window.onload = () => {
const binary_data_arr = new Uint8Array(res as number[]) const binary_data_arr = new Uint8Array(res as number[])
const blob = new Blob([binary_data_arr], { type: 'video/mp4' }) const blob = new Blob([binary_data_arr], { type: 'video/mp4' })
const videoUrl = URL.createObjectURL(blob) const videoUrl = URL.createObjectURL(blob)
const player = document.getElementById('player') as HTMLVideoElement player_instance = new player(params);
if (player) { player_instance.init_player(videoUrl);
player.src = videoUrl
player.play()
if(params.mute) {
player.muted = JSON.parse(params.mute);
}
player.loop = true
setTimeout(()=>{player.style.opacity = '1'},0);
}
}) })
} }
}) })