add: settings page
This commit is contained in:
@@ -8,9 +8,4 @@ import MainLayout from "./components/MainLayout.vue";
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
body,
|
||||
#app {
|
||||
font-family: "Noto Sans", "Roboto", "Segoe UI", sans-serif !important;
|
||||
}
|
||||
</style>
|
||||
<style></style>
|
||||
|
||||
@@ -7,11 +7,22 @@ import { Transfer } from "../../bindings/mesh-drop/internal/transfer";
|
||||
import { GetPeers } from "../../bindings/mesh-drop/internal/discovery/service";
|
||||
import { Events } from "@wailsio/runtime";
|
||||
import { GetTransferList } from "../../bindings/mesh-drop/internal/transfer/service";
|
||||
import {
|
||||
GetSavePath,
|
||||
SetSavePath,
|
||||
GetHostName,
|
||||
SetHostName,
|
||||
GetAutoAccept,
|
||||
SetAutoAccept,
|
||||
GetSaveHistory,
|
||||
SetSaveHistory,
|
||||
} from "../../bindings/mesh-drop/internal/config/config";
|
||||
import { Dialogs } from "@wailsio/runtime";
|
||||
|
||||
const peers = ref<Peer[]>([]);
|
||||
const transferList = ref<Transfer[]>([]);
|
||||
const activeKey = ref("discover");
|
||||
const drawer = ref(true); // Control drawer visibility
|
||||
const drawer = ref(true);
|
||||
const isMobile = ref(false);
|
||||
|
||||
// 监听窗口大小变化更新 isMobile
|
||||
@@ -26,6 +37,12 @@ onMounted(async () => {
|
||||
if (isMobile.value) {
|
||||
drawer.value = false;
|
||||
}
|
||||
|
||||
// 加载配置
|
||||
savePath.value = await GetSavePath();
|
||||
hostName.value = await GetHostName();
|
||||
autoAccept.value = await GetAutoAccept();
|
||||
saveHistory.value = await GetSaveHistory();
|
||||
});
|
||||
|
||||
const checkMobile = () => {
|
||||
@@ -73,8 +90,34 @@ const menuItems = computed(() => [
|
||||
icon: "mdi-inbox",
|
||||
badge: pendingCount.value > 0 ? pendingCount.value : null,
|
||||
},
|
||||
{
|
||||
title: "Settings",
|
||||
value: "settings",
|
||||
icon: "mdi-cog",
|
||||
},
|
||||
]);
|
||||
|
||||
// --- 设置 ---
|
||||
const savePath = ref("");
|
||||
|
||||
const changeSavePath = async () => {
|
||||
const opts: Dialogs.OpenFileDialogOptions = {
|
||||
Title: "Select Save Path",
|
||||
CanChooseDirectories: true,
|
||||
CanChooseFiles: false,
|
||||
AllowsMultipleSelection: false,
|
||||
};
|
||||
const path = await Dialogs.OpenFile(opts);
|
||||
if (path && typeof path === "string") {
|
||||
await SetSavePath(path);
|
||||
savePath.value = path;
|
||||
}
|
||||
};
|
||||
|
||||
const hostName = ref("");
|
||||
const autoAccept = ref(false);
|
||||
const saveHistory = ref(false);
|
||||
|
||||
// --- 操作 ---
|
||||
|
||||
const handleMenuClick = (key: string) => {
|
||||
@@ -87,17 +130,17 @@ const handleMenuClick = (key: string) => {
|
||||
|
||||
<template>
|
||||
<v-layout>
|
||||
<!-- App Bar for Mobile -->
|
||||
<!-- 小屏幕抽屉 -->
|
||||
<v-app-bar v-if="isMobile" border flat>
|
||||
<v-toolbar-title class="text-primary font-weight-bold"
|
||||
>Mesh Drop</v-toolbar-title
|
||||
>
|
||||
<template v-slot:append>
|
||||
<template #append>
|
||||
<v-btn icon="mdi-menu" @click="drawer = !drawer"></v-btn>
|
||||
</template>
|
||||
</v-app-bar>
|
||||
|
||||
<!-- Navigation Drawer -->
|
||||
<!-- 导航抽屉 -->
|
||||
<v-navigation-drawer v-model="drawer" :permanent="!isMobile">
|
||||
<div class="pa-4" v-if="!isMobile">
|
||||
<div class="text-h6 text-primary font-weight-bold">Mesh Drop</div>
|
||||
@@ -113,7 +156,7 @@ const handleMenuClick = (key: string) => {
|
||||
rounded="xl"
|
||||
color="primary"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<template #prepend>
|
||||
<v-icon :icon="item.icon"></v-icon>
|
||||
</template>
|
||||
|
||||
@@ -131,10 +174,10 @@ const handleMenuClick = (key: string) => {
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
|
||||
<!-- Main Content -->
|
||||
<!-- 主内容 -->
|
||||
<v-main>
|
||||
<v-container fluid class="pa-4">
|
||||
<!-- Discover View -->
|
||||
<!-- 发现视图 -->
|
||||
<div v-show="activeKey === 'discover'">
|
||||
<div v-if="peers.length > 0" class="peer-grid">
|
||||
<div v-for="peer in peers" :key="peer.id">
|
||||
@@ -160,7 +203,7 @@ const handleMenuClick = (key: string) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transfers View -->
|
||||
<!-- 传输视图 -->
|
||||
<div v-show="activeKey === 'transfers'">
|
||||
<div v-if="transferList.length > 0">
|
||||
<TransferItem
|
||||
@@ -177,6 +220,69 @@ const handleMenuClick = (key: string) => {
|
||||
<div class="text-grey">No transfers yet</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 设置视图 -->
|
||||
<div v-show="activeKey === 'settings'">
|
||||
<v-list lines="one" bg-color="transparent">
|
||||
<v-list-item title="Save Path" :subtitle="savePath">
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-folder-download"></v-icon>
|
||||
</template>
|
||||
<template #append>
|
||||
<v-btn
|
||||
variant="text"
|
||||
color="primary"
|
||||
@click="changeSavePath"
|
||||
prepend-icon="mdi-pencil"
|
||||
>
|
||||
Change
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item title="HostName">
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-laptop"></v-icon>
|
||||
</template>
|
||||
<template #append
|
||||
><v-text-field
|
||||
clearable
|
||||
variant="underlined"
|
||||
v-model="hostName"
|
||||
width="200"
|
||||
@update:modelValue="SetHostName"
|
||||
></v-text-field
|
||||
></template>
|
||||
</v-list-item>
|
||||
<v-list-item title="Save History">
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-history"></v-icon>
|
||||
</template>
|
||||
<template #append
|
||||
><v-switch
|
||||
v-model="saveHistory"
|
||||
color="primary"
|
||||
inset
|
||||
hide-details
|
||||
@update:modelValue="SetSaveHistory(saveHistory)"
|
||||
></v-switch
|
||||
></template>
|
||||
</v-list-item>
|
||||
<v-list-item title="Auto Accept">
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-content-save"></v-icon>
|
||||
</template>
|
||||
<template #append
|
||||
><v-switch
|
||||
v-model="autoAccept"
|
||||
color="primary"
|
||||
inset
|
||||
hide-details
|
||||
@update:modelValue="SetAutoAccept(autoAccept)"
|
||||
></v-switch
|
||||
></template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
</v-container>
|
||||
</v-main>
|
||||
</v-layout>
|
||||
|
||||
@@ -208,14 +208,14 @@ const handleSendFiles = () => {
|
||||
|
||||
<template>
|
||||
<v-card hover link class="peer-card pa-2">
|
||||
<template v-slot:title>
|
||||
<template #title>
|
||||
<div class="d-flex align-center">
|
||||
<v-icon :icon="osIcon" size="24" class="mr-2"></v-icon>
|
||||
<span class="text-subtitle-1 font-weight-bold">{{ peer.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:text>
|
||||
<template #text>
|
||||
<div class="d-flex align-center flex-wrap ga-2 mt-2">
|
||||
<v-icon icon="mdi-web" size="20" class="text-medium-emphasis"></v-icon>
|
||||
|
||||
@@ -241,9 +241,9 @@ const handleSendFiles = () => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:actions>
|
||||
<template #actions>
|
||||
<v-menu>
|
||||
<template v-slot:activator="{ props }">
|
||||
<template #activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
block
|
||||
@@ -252,10 +252,10 @@ const handleSendFiles = () => {
|
||||
:disabled="ips.length === 0"
|
||||
append-icon="mdi-chevron-down"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-send"></v-icon>
|
||||
</template>
|
||||
Send...
|
||||
Send
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
@@ -265,7 +265,7 @@ const handleSendFiles = () => {
|
||||
:value="item.value"
|
||||
@click="handleAction(item.value)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<template #prepend>
|
||||
<v-icon :icon="item.icon"></v-icon>
|
||||
</template>
|
||||
<v-list-item-title>{{ item.title }}</v-list-item-title>
|
||||
@@ -312,7 +312,7 @@ const handleSendFiles = () => {
|
||||
:subtitle="file.path"
|
||||
lines="two"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<template #append>
|
||||
<v-btn
|
||||
icon="mdi-delete"
|
||||
size="small"
|
||||
|
||||
@@ -261,29 +261,16 @@ const canAccept = computed(() => {
|
||||
<v-btn
|
||||
v-if="canAccept"
|
||||
color="success"
|
||||
icon="mdi-check"
|
||||
icon="mdi-content-save"
|
||||
@click="acceptTransfer"
|
||||
></v-btn>
|
||||
|
||||
<v-menu v-if="canAccept && props.transfer.content_type !== 'text'">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn
|
||||
color="success"
|
||||
icon="mdi-chevron-down"
|
||||
v-bind="props"
|
||||
></v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item
|
||||
v-for="(item, index) in dropdownItems"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
@click="handleSelect(item.value)"
|
||||
>
|
||||
<v-list-item-title>{{ item.title }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-btn
|
||||
v-if="canAccept"
|
||||
color="success"
|
||||
icon="mdi-folder-arrow-right"
|
||||
@click="acceptToFolder"
|
||||
></v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="canAccept"
|
||||
|
||||
Reference in New Issue
Block a user