mirror of
https://github.com/AkiChase/scrcpy-mask
synced 2025-04-21 04:25:13 +08:00
feat(sidebar): add tooltip for sidebar button
This commit is contained in:
parent
6eac5c8875
commit
3bb71df47e
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import Sidebar from "./components/Sidebar.vue";
|
||||
import Sidebar from "./components/sidebar/Sidebar.vue";
|
||||
import Header from "./components/Header.vue";
|
||||
import {
|
||||
darkTheme,
|
||||
|
@ -1,209 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import {
|
||||
GameControllerOutline,
|
||||
LogoAndroid,
|
||||
SettingsOutline,
|
||||
ReturnDownBackOutline,
|
||||
VolumeHighOutline,
|
||||
VolumeLowOutline,
|
||||
StopOutline,
|
||||
ListOutline,
|
||||
BulbOutline,
|
||||
Bulb,
|
||||
} from "@vicons/ionicons5";
|
||||
import { Keyboard24Regular } from "@vicons/fluent";
|
||||
import { NIcon, useMessage } from "naive-ui";
|
||||
import { useGlobalStore } from "../store/global";
|
||||
import { sendSetScreenPowerMode } from "../frontcommand/controlMsg";
|
||||
import { AndroidKeycode } from "../frontcommand/android";
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { SendKeyAction, sendKey } from "../frontcommand/scrcpyMaskCmd";
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const store = useGlobalStore();
|
||||
const message = useMessage();
|
||||
|
||||
const nextScreenPowerMode = ref(0);
|
||||
|
||||
function nav(name: string) {
|
||||
router.replace({ name });
|
||||
}
|
||||
|
||||
async function sendKeyCodeToDevice(code: AndroidKeycode) {
|
||||
if (store.controledDevice) {
|
||||
await sendKey({
|
||||
action: SendKeyAction.Default,
|
||||
keycode: code,
|
||||
});
|
||||
} else {
|
||||
message.error(t("sidebar.noControledDevice"));
|
||||
}
|
||||
}
|
||||
|
||||
async function changeScreenPowerMode() {
|
||||
if (store.controledDevice) {
|
||||
sendSetScreenPowerMode({ mode: nextScreenPowerMode.value });
|
||||
nextScreenPowerMode.value = nextScreenPowerMode.value ? 0 : 2;
|
||||
} else {
|
||||
message.error(t("sidebar.noControledDevice"));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="sidebar">
|
||||
<div data-tauri-drag-region class="logo">S M</div>
|
||||
<div class="module">
|
||||
<div :class="{ active: route.name == 'mask' }" @click="nav('mask')">
|
||||
<NIcon>
|
||||
<GameControllerOutline />
|
||||
</NIcon>
|
||||
</div>
|
||||
<div :class="{ active: route.name == 'device' }" @click="nav('device')">
|
||||
<NIcon>
|
||||
<LogoAndroid />
|
||||
</NIcon>
|
||||
</div>
|
||||
<div
|
||||
:class="{ active: route.name == 'keyboard' }"
|
||||
@click="nav('keyboard')"
|
||||
>
|
||||
<NIcon>
|
||||
<Keyboard24Regular />
|
||||
</NIcon>
|
||||
</div>
|
||||
<div :class="{ active: route.name == 'setting' }" @click="nav('setting')">
|
||||
<NIcon>
|
||||
<SettingsOutline />
|
||||
</NIcon>
|
||||
</div>
|
||||
</div>
|
||||
<div data-tauri-drag-region class="drag"></div>
|
||||
<div class="nav">
|
||||
<div @click="changeScreenPowerMode">
|
||||
<NIcon>
|
||||
<Bulb v-if="nextScreenPowerMode" />
|
||||
<BulbOutline v-else />
|
||||
</NIcon>
|
||||
</div>
|
||||
<div @click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_VOLUME_UP)">
|
||||
<NIcon>
|
||||
<VolumeHighOutline />
|
||||
</NIcon>
|
||||
</div>
|
||||
<div @click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_VOLUME_DOWN)">
|
||||
<NIcon>
|
||||
<VolumeLowOutline />
|
||||
</NIcon>
|
||||
</div>
|
||||
<div @click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_BACK)">
|
||||
<NIcon>
|
||||
<ReturnDownBackOutline />
|
||||
</NIcon>
|
||||
</div>
|
||||
<div @click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_HOME)">
|
||||
<NIcon>
|
||||
<StopOutline />
|
||||
</NIcon>
|
||||
</div>
|
||||
<div @click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_APP_SWITCH)">
|
||||
<NIcon>
|
||||
<ListOutline />
|
||||
</NIcon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.sidebar {
|
||||
background-color: var(--bg-color);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 10px 0 0 10px;
|
||||
grid-area: sidebar;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
.logo {
|
||||
height: 30px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--light-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.drag{
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.module {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
& > div {
|
||||
flex-shrink: 0;
|
||||
height: 50px;
|
||||
color: var(--gray-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: transform 0.3s ease;
|
||||
box-sizing: border-box;
|
||||
font-size: 28px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-hover-color);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
&:active {
|
||||
color: var(--primary-pressed-color);
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
& > div.active {
|
||||
color: var(--primary-color);
|
||||
border-left: 3px solid var(--primary-color);
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav {
|
||||
color: var(--light-color);
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
& > div {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-hover-color);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
&:active {
|
||||
color: var(--primary-pressed-color);
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
40
src/components/sidebar/FuncButton.vue
Normal file
40
src/components/sidebar/FuncButton.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
import { NIcon, NTooltip } from "naive-ui";
|
||||
|
||||
const props = defineProps<{
|
||||
icon: Object;
|
||||
tip: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="btn-content">
|
||||
<NTooltip trigger="hover">
|
||||
<template #trigger>
|
||||
<NIcon><component :is="props.icon" /></NIcon>
|
||||
</template>
|
||||
{{ props.tip }}
|
||||
</NTooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.btn-content {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-hover-color);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
&:active {
|
||||
color: var(--primary-pressed-color);
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
</style>
|
63
src/components/sidebar/ModuleNav.vue
Normal file
63
src/components/sidebar/ModuleNav.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<script setup lang="ts">
|
||||
import { NIcon, NTooltip } from "naive-ui";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
const props = defineProps<{
|
||||
name: string;
|
||||
icon: Object;
|
||||
tip: string;
|
||||
}>();
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
function nav(name: string) {
|
||||
router.replace({ name });
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="{
|
||||
'nav-active': route.name === props.name,
|
||||
'nav-content': true,
|
||||
}"
|
||||
@click="nav(props.name)"
|
||||
>
|
||||
<NTooltip trigger="hover">
|
||||
<template #trigger>
|
||||
<NIcon><component :is="props.icon" /></NIcon>
|
||||
</template>
|
||||
{{ props.tip }}
|
||||
</NTooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nav-content {
|
||||
flex-shrink: 0;
|
||||
height: 50px;
|
||||
color: var(--gray-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: transform 0.3s ease;
|
||||
box-sizing: border-box;
|
||||
font-size: 28px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-hover-color);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
&:active {
|
||||
color: var(--primary-pressed-color);
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-active {
|
||||
color: var(--primary-color);
|
||||
border-left: 3px solid var(--primary-color);
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
154
src/components/sidebar/Sidebar.vue
Normal file
154
src/components/sidebar/Sidebar.vue
Normal file
@ -0,0 +1,154 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
GameControllerOutline,
|
||||
LogoAndroid,
|
||||
SettingsOutline,
|
||||
ReturnDownBackOutline,
|
||||
VolumeHighOutline,
|
||||
VolumeLowOutline,
|
||||
StopOutline,
|
||||
ListOutline,
|
||||
BulbOutline,
|
||||
Bulb,
|
||||
} from "@vicons/ionicons5";
|
||||
import { Keyboard24Regular } from "@vicons/fluent";
|
||||
import { useMessage } from "naive-ui";
|
||||
import { useGlobalStore } from "../../store/global";
|
||||
import { sendSetScreenPowerMode } from "../../frontcommand/controlMsg";
|
||||
import { AndroidKeycode } from "../../frontcommand/android";
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { SendKeyAction, sendKey } from "../../frontcommand/scrcpyMaskCmd";
|
||||
import ModuleNav from "./ModuleNav.vue";
|
||||
import FuncButton from "./FuncButton.vue";
|
||||
|
||||
const { t } = useI18n();
|
||||
const store = useGlobalStore();
|
||||
const message = useMessage();
|
||||
|
||||
const nextScreenPowerMode = ref(0);
|
||||
|
||||
async function sendKeyCodeToDevice(code: AndroidKeycode) {
|
||||
if (store.controledDevice) {
|
||||
await sendKey({
|
||||
action: SendKeyAction.Default,
|
||||
keycode: code,
|
||||
});
|
||||
} else {
|
||||
message.error(t("sidebar.noControledDevice"));
|
||||
}
|
||||
}
|
||||
|
||||
async function changeScreenPowerMode() {
|
||||
if (store.controledDevice) {
|
||||
sendSetScreenPowerMode({ mode: nextScreenPowerMode.value });
|
||||
nextScreenPowerMode.value = nextScreenPowerMode.value ? 0 : 2;
|
||||
} else {
|
||||
message.error(t("sidebar.noControledDevice"));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="sidebar">
|
||||
<div data-tauri-drag-region class="logo">S M</div>
|
||||
<div class="module-nav">
|
||||
<ModuleNav
|
||||
name="mask"
|
||||
:icon="GameControllerOutline"
|
||||
:tip="t('sidebar.tip.mask')"
|
||||
/>
|
||||
<ModuleNav
|
||||
name="device"
|
||||
:icon="LogoAndroid"
|
||||
:tip="t('sidebar.tip.device')"
|
||||
/>
|
||||
<ModuleNav
|
||||
name="keyboard"
|
||||
:icon="Keyboard24Regular"
|
||||
:tip="t('sidebar.tip.keyboard')"
|
||||
/>
|
||||
<ModuleNav
|
||||
name="setting"
|
||||
:icon="SettingsOutline"
|
||||
:tip="t('sidebar.tip.setting')"
|
||||
/>
|
||||
</div>
|
||||
<div data-tauri-drag-region class="drag" />
|
||||
<div class="func-btn">
|
||||
<FuncButton
|
||||
@click="changeScreenPowerMode"
|
||||
:tip="nextScreenPowerMode? t('sidebar.tip.screenPowerModeOff'): t('sidebar.tip.screenPowerModeOn')"
|
||||
:icon="nextScreenPowerMode ? Bulb : BulbOutline"
|
||||
/>
|
||||
<FuncButton
|
||||
@click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_VOLUME_UP)"
|
||||
:tip="t('sidebar.tip.volumeUp')"
|
||||
:icon="VolumeHighOutline"
|
||||
/>
|
||||
<FuncButton
|
||||
@click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_VOLUME_DOWN)"
|
||||
:tip="t('sidebar.tip.volumeDown')"
|
||||
:icon="VolumeLowOutline"
|
||||
/>
|
||||
<FuncButton
|
||||
@click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_BACK)"
|
||||
:tip="t('sidebar.tip.back')"
|
||||
:icon="ReturnDownBackOutline"
|
||||
/>
|
||||
<FuncButton
|
||||
@click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_HOME)"
|
||||
:tip="t('sidebar.tip.home')"
|
||||
:icon="StopOutline"
|
||||
/>
|
||||
<FuncButton
|
||||
@click="sendKeyCodeToDevice(AndroidKeycode.AKEYCODE_APP_SWITCH)"
|
||||
:tip="t('sidebar.tip.appSwitch')"
|
||||
:icon="ListOutline"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.sidebar {
|
||||
background-color: var(--bg-color);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 10px 0 0 10px;
|
||||
grid-area: sidebar;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
.logo {
|
||||
height: 30px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--light-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.drag {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.module-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.func-btn {
|
||||
color: var(--light-color);
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -282,7 +282,20 @@
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"noControledDevice": "No devices are controlled"
|
||||
"noControledDevice": "No devices are controlled",
|
||||
"tip": {
|
||||
"mask": "Mask",
|
||||
"device": "Device",
|
||||
"keyboard": "Key mapping",
|
||||
"setting": "Setting",
|
||||
"screenPowerModeOff": "Screen off",
|
||||
"screenPowerModeOn": "Screen on",
|
||||
"volumeUp": "Volume up",
|
||||
"volumeDown": "Volume down",
|
||||
"back": "Back",
|
||||
"home": "Home",
|
||||
"appSwitch": "App switch"
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"open": "Connected to external control server",
|
||||
|
@ -282,7 +282,20 @@
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"noControledDevice": "未控制任何设备"
|
||||
"noControledDevice": "未控制任何设备",
|
||||
"tip": {
|
||||
"mask": "蒙版",
|
||||
"device": "设备",
|
||||
"keyboard": "按键映射",
|
||||
"setting": "设置",
|
||||
"screenPowerModeOff": "息屏",
|
||||
"screenPowerModeOn": "亮屏",
|
||||
"volumeUp": "增加音量",
|
||||
"volumeDown": "减少音量",
|
||||
"back": "返回",
|
||||
"home": "主页",
|
||||
"appSwitch": "最近任务"
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"open": "已连接到外部控制服务端",
|
||||
|
Loading…
Reference in New Issue
Block a user