feat: add button tooltip

This commit is contained in:
AkiChase 2025-03-12 14:39:03 +08:00
parent e99475ba4b
commit 4cb9897f11
11 changed files with 132 additions and 66 deletions

View File

@ -43,12 +43,6 @@ onMounted(() => {
"sidebar content"; "sidebar content";
} }
.n-spin-content,
.n-spin-container {
width: 100%;
height: 100%;
}
.n-message { .n-message {
user-select: none; user-select: none;
-webkit-user-select: none; -webkit-user-select: none;

View File

@ -27,9 +27,7 @@ import {
NDataTable, NDataTable,
NDropdown, NDropdown,
NEmpty, NEmpty,
NTooltip,
NFlex, NFlex,
NIcon,
NSpin, NSpin,
DataTableColumns, DataTableColumns,
DropdownOption, DropdownOption,
@ -45,6 +43,7 @@ import { useI18n } from "vue-i18n";
import { closeExternalControl, connectExternalControl } from "../websocket"; import { closeExternalControl, connectExternalControl } from "../websocket";
import { LogicalSize, getCurrentWindow } from "@tauri-apps/api/window"; import { LogicalSize, getCurrentWindow } from "@tauri-apps/api/window";
import { writeText } from "@tauri-apps/plugin-clipboard-manager"; import { writeText } from "@tauri-apps/plugin-clipboard-manager";
import ButtonWithTip from "./common/ButtonWithTip.vue";
const { t } = useI18n(); const { t } = useI18n();
const dialog = useDialog(); const dialog = useDialog();
@ -359,8 +358,8 @@ function closeWS() {
<template> <template>
<div class="container"> <div class="container">
<div class="device"> <NSpin :show="store.showLoadingFlag">
<NSpin :show="store.showLoadingFlag"> <div class="device">
<NH4 prefix="bar">{{ $t("pages.Device.localPort") }}</NH4> <NH4 prefix="bar">{{ $t("pages.Device.localPort") }}</NH4>
<NInputNumber <NInputNumber
v-model:value="port" v-model:value="port"
@ -413,21 +412,21 @@ function closeWS() {
}}) }})
</div> </div>
<div class="device-op"> <div class="device-op">
<NTooltip trigger="hover"> <ButtonWithTip
<template #trigger> quaternary
<NButton quaternary circle type="info"> circle
<template #icon> type="info"
<NIcon><InformationCircle /></NIcon> :tip="`scid: ${store.controledDevice.scid}`"
</template> :icon="InformationCircle"
</NButton> />
</template> <ButtonWithTip
scid: {{ store.controledDevice.scid }} quaternary
</NTooltip> circle
<NButton quaternary circle type="error" @click="shutdownSC()"> type="error"
<template #icon> @click="shutdownSC()"
<NIcon><CloseCircle /></NIcon> :tip="$t('pages.Device.btnShutdown')"
</template> :icon="CloseCircle"
</NButton> />
</div> </div>
</div> </div>
</div> </div>
@ -435,17 +434,15 @@ function closeWS() {
<NH4 style="margin: 20px 0" prefix="bar">{{ <NH4 style="margin: 20px 0" prefix="bar">{{
$t("pages.Device.availableDevice") $t("pages.Device.availableDevice")
}}</NH4> }}</NH4>
<NButton <ButtonWithTip
tertiary tertiary
circle circle
type="primary" type="primary"
@click="refreshDevices" @click="refreshDevices"
style="margin-right: 20px" style="margin-right: 20px"
> :tip="$t('pages.Device.btnRefresh')"
<template #icon> :icon="Refresh"
<NIcon><Refresh /></NIcon> />
</template>
</NButton>
</NFlex> </NFlex>
<NDataTable <NDataTable
max-height="120" max-height="120"
@ -465,8 +462,8 @@ function closeWS() {
:on-clickoutside="onMenuClickoutside" :on-clickoutside="onMenuClickoutside"
@select="onMenuSelect" @select="onMenuSelect"
/> />
</NSpin> </div>
</div> </NSpin>
</div> </div>
</template> </template>
@ -480,13 +477,12 @@ function closeWS() {
} }
.device { .device {
flex-grow: 1; @include common.scrollbar;
@include common.flexFullHeight;
color: var(--light-color); color: var(--light-color);
background-color: var(--bg-color); background-color: var(--bg-color);
padding: 0 20px; padding: 0 20px;
height: 0;
overflow-y: auto; overflow-y: auto;
@include common.scrollbar;
} }
.controled-device-list { .controled-device-list {

View File

@ -0,0 +1,40 @@
<script setup lang="ts">
import { NTooltip, NIcon, NButton } from "naive-ui";
const props = defineProps<{
tip: string;
icon?: Object;
circle?: boolean;
disabled?: boolean;
round?: boolean;
size?: "tiny" | "small" | "medium" | "large";
secondary?: boolean;
tertiary?: boolean;
text?: boolean;
}>();
defineOptions({ inheritAttrs: false });
</script>
<template>
<NTooltip trigger="hover">
<template #trigger>
<NButton
v-bind="$attrs"
:circle="props.circle"
:disabled="props.disabled"
:round="props.round"
:size="props.size"
:secondary="props.secondary"
:tertiary="props.tertiary"
:text="props.text"
>
<template v-if="props.icon" #icon>
<NIcon><component :is="props.icon" /></NIcon>
</template>
<slot></slot>
</NButton>
</template>
{{ props.tip }}
</NTooltip>
</template>

View File

@ -68,15 +68,17 @@ function changeClipboardSync() {
$t("pages.Setting.Basic.adbPath.set") $t("pages.Setting.Basic.adbPath.set")
}}</NButton> }}</NButton>
</NInputGroup> </NInputGroup>
<NH4 prefix="bar">剪切板同步</NH4> <NH4 prefix="bar">{{ $t("pages.Setting.Basic.clipboardSync.title") }}</NH4>
<NFlex vertical> <NFlex vertical>
<NCheckbox <NCheckbox
v-model:checked="store.clipboardSync.syncFromDevice" v-model:checked="store.clipboardSync.syncFromDevice"
@update:checked="changeClipboardSync" @update:checked="changeClipboardSync"
> >
<NTooltip trigger="hover"> <NTooltip trigger="hover">
<template #trigger>从设备同步</template> <template #trigger>{{
设备剪切板发生变化时自动同步更新电脑剪切板 $t("pages.Setting.Basic.clipboardSync.syncFromDevice")
}}</template>
{{ $t("pages.Setting.Basic.clipboardSync.syncFromDeviceTip") }}
</NTooltip> </NTooltip>
</NCheckbox> </NCheckbox>
<NCheckbox <NCheckbox
@ -84,8 +86,10 @@ function changeClipboardSync() {
@update:checked="changeClipboardSync" @update:checked="changeClipboardSync"
> >
<NTooltip trigger="hover"> <NTooltip trigger="hover">
<template #trigger>粘贴时同步</template> <template #trigger>{{
在按键输入模式下按下 Ctrl + V 可将电脑剪切板内容同步粘贴到设备 $t("pages.Setting.Basic.clipboardSync.pasteFromPC")
}}</template>
{{ $t("pages.Setting.Basic.clipboardSync.pasteFromPCTip") }}
</NTooltip> </NTooltip>
</NCheckbox> </NCheckbox>
</NFlex> </NFlex>

View File

@ -11,19 +11,17 @@ import {
NInput, NInput,
useDialog, useDialog,
NCard, NCard,
NIcon,
} from "naive-ui"; } from "naive-ui";
import { relaunch } from "@tauri-apps/plugin-process"; import { relaunch } from "@tauri-apps/plugin-process";
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { LocalStore } from "../../store/localStore"; import { LocalStore } from "../../store/localStore";
import ButtonWithTip from "../common/ButtonWithTip.vue";
const { t } = useI18n(); const { t } = useI18n();
const dialog = useDialog(); const dialog = useDialog();
// TODO add tooltip for btn
const localStoreEntries = ref<[string, unknown][]>([]); const localStoreEntries = ref<[string, unknown][]>([]);
const showDataModal = ref(false); const showDataModal = ref(false);
const dataModalInputVal = ref(""); const dataModalInputVal = ref("");
@ -80,28 +78,22 @@ function delLocalStore(key?: string) {
<NFlex justify="space-between"> <NFlex justify="space-between">
<NH4 prefix="bar">{{ $t("pages.Setting.Data.localStore") }}</NH4> <NH4 prefix="bar">{{ $t("pages.Setting.Data.localStore") }}</NH4>
<NFlex> <NFlex>
<NButton <ButtonWithTip
tertiary tertiary
circle circle
type="primary" type="primary"
@click="delLocalStore()" @click="delLocalStore()"
style="margin-right: 20px" :tip="$t('pages.Setting.Data.btnDelAll')"
> :icon="TrashBinOutline"
<template #icon> />
<NIcon><TrashBinOutline /></NIcon> <ButtonWithTip
</template>
</NButton>
<NButton
tertiary tertiary
circle circle
type="primary" type="primary"
@click="refreshLocalData()" @click="refreshLocalData()"
style="margin-right: 20px" :tip="$t('pages.Setting.Data.btnRefresh')"
> :icon="Refresh"
<template #icon> />
<NIcon><Refresh /></NIcon>
</template>
</NButton>
</NFlex> </NFlex>
</NFlex> </NFlex>
<NP>{{ $t("pages.Setting.Data.delLocalStore.warning") }}</NP> <NP>{{ $t("pages.Setting.Data.delLocalStore.warning") }}</NP>

View File

@ -48,12 +48,13 @@ const store = useGlobalStore();
color: var(--light-color); color: var(--light-color);
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
// for spin div
display: flex; display: flex;
flex-direction: column;
.n-tabs { .n-tabs {
height: 100%; height: 100%;
} }
.n-tab-pane { .n-tab-pane {
padding: 0; padding: 0;
} }

View File

@ -4,6 +4,14 @@
height: 100%; height: 100%;
} }
@mixin flexFullHeight {
flex-grow: 1;
height: 0;
// for child
display: flex;
flex-direction: column;
}
@mixin scrollbar { @mixin scrollbar {
&::-webkit-scrollbar { &::-webkit-scrollbar {
height: 6px; height: 6px;

View File

@ -1,3 +1,5 @@
@use "./common.scss";
:root { :root {
--primary-color: #63e2b7; --primary-color: #63e2b7;
--primary-hover-color: #7fe7c4; --primary-hover-color: #7fe7c4;
@ -10,8 +12,8 @@
--gray-color: #6b6e76; --gray-color: #6b6e76;
--red-color: #fc5185; --red-color: #fc5185;
--red-pressed-color: #f4336d; --red-pressed-color: #f4336d;
--blue-color: #70C0E8; --blue-color: #70c0e8;
--blue-pressed-color: #66AFD3; --blue-pressed-color: #66afd3;
} }
html, html,
@ -26,3 +28,10 @@ div#app {
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
} }
.n-spin-container {
@include common.flexFullHeight;
.n-spin-content {
@include common.flexFullHeight;
}
}

View File

@ -36,7 +36,9 @@
"wsConnect": "Control", "wsConnect": "Control",
"adbDeviceError": "Unable to get available devices", "adbDeviceError": "Unable to get available devices",
"adbConnectError": "Wireless connection failed", "adbConnectError": "Wireless connection failed",
"rotation": "Device rotation {0}°" "rotation": "Device rotation {0}°",
"btnShutdown": "Shutdown control",
"btnRefresh": "Refresh"
}, },
"Mask": { "Mask": {
"keyconfigException": "The key mapping config is abnormal, please delete this config", "keyconfigException": "The key mapping config is abnormal, please delete this config",
@ -105,6 +107,13 @@
"set": "Save", "set": "Save",
"setSuccess": "adb path set successfully", "setSuccess": "adb path set successfully",
"title": "adb path" "title": "adb path"
},
"clipboardSync": {
"title": "Clipboard Sync",
"syncFromDevice": "Sync from device",
"syncFromDeviceTip": "Automatically synchronize and update your computer's clipboard when the device clipboard changes.",
"pasteFromPC": "Paste from PC",
"pasteFromPCTip": "In KeyInpu mode, press Ctrl + V to paste the contents of your computer's clipboard to your device."
} }
}, },
"Data": { "Data": {
@ -119,7 +128,9 @@
"warning": "Deleting data may lead to unpredictable consequences, so please operate with caution. \nIf an exception occurs, please try clearing the data and restarting the software." "warning": "Deleting data may lead to unpredictable consequences, so please operate with caution. \nIf an exception occurs, please try clearing the data and restarting the software."
}, },
"localStore": "Local data", "localStore": "Local data",
"delCurData": "Delete current data" "delCurData": "Delete current data",
"btnRefresh": "Refresh",
"btnDelAll": "Clear local data"
}, },
"About": { "About": {
"introduction": "A Scrcpy client in Rust & Tarui aimed at providing mouse and key mapping to control Android device.", "introduction": "A Scrcpy client in Rust & Tarui aimed at providing mouse and key mapping to control Android device.",

View File

@ -36,7 +36,9 @@
"wsConnect": "控制", "wsConnect": "控制",
"adbDeviceError": "无法获取可用设备", "adbDeviceError": "无法获取可用设备",
"adbConnectError": "无线连接失败", "adbConnectError": "无线连接失败",
"rotation": "设备旋转 {0}°" "rotation": "设备旋转 {0}°",
"btnShutdown": "关闭控制",
"btnRefresh": "刷新"
}, },
"Mask": { "Mask": {
"keyconfigException": "按键方案异常,请删除此方案", "keyconfigException": "按键方案异常,请删除此方案",
@ -105,6 +107,13 @@
"title": "adb 路径", "title": "adb 路径",
"placeholder": "adb 路径", "placeholder": "adb 路径",
"set": "设置" "set": "设置"
},
"clipboardSync": {
"title": "剪切板同步",
"syncFromDevice": "从设备同步",
"syncFromDeviceTip": "设备剪切板发生变化时自动同步更新电脑剪切板",
"pasteFromPC": "从电脑粘贴",
"pasteFromPCTip": "在按键输入模式下,按下 Ctrl + V 可将电脑剪切板内容同步粘贴到设备"
} }
}, },
"Data": { "Data": {
@ -119,7 +128,9 @@
"warning": "删除数据可能导致无法预料的后果,请慎重操作。若出现异常请尝试清空数据并重启软件。" "warning": "删除数据可能导致无法预料的后果,请慎重操作。若出现异常请尝试清空数据并重启软件。"
}, },
"localStore": "本地数据", "localStore": "本地数据",
"delCurData": "删除当前数据" "delCurData": "删除当前数据",
"btnDelAll": "清空本地数据",
"btnRefresh": "刷新"
}, },
"About": { "About": {
"about": "关于", "about": "关于",

View File

@ -1,6 +1,6 @@
import { createApp } from "vue"; import { createApp } from "vue";
import { createPinia } from "pinia"; import { createPinia } from "pinia";
import "./styles.css"; import "./css/global.scss";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
import i18n from "./i18n"; import i18n from "./i18n";