Adding keyboard shortcut for direct access + Fixes for Linux clipboard reading (#1479)

* feat: add ctrl+d keyboard shortcut to open direct access

* fix: make sure direct access promt only get shown once

* fix: linux clipboard acess on non x11 systems

xclip not present on all linux machines: using the electron mechanism instead
This commit is contained in:
kubectl
2025-11-11 05:16:23 +01:00
committed by GitHub
parent dda3d2dda9
commit 56b13ae4cb
5 changed files with 57 additions and 23 deletions

View File

@@ -11,6 +11,7 @@ const {
nativeImage
} = require('electron');
const { spawn, spawnSync } = require('child_process');
const { clipboard } = require('electron');
const fs = require('fs');
const https = require('https');
@@ -262,6 +263,9 @@ ipcMain.handle(
ipcMain.handle('app:getArch', () => {
return process.arch.toString();
});
ipcMain.handle('app:getClipboardText', () => {
return clipboard.readText();
});
ipcMain.handle('app:getNoUpdater', () => {
return noUpdater;

View File

@@ -23,6 +23,7 @@ const validChannels = ['launch-command'];
contextBridge.exposeInMainWorld('electron', {
getArch: () => ipcRenderer.invoke('app:getArch'),
getClipboardText: () => ipcRenderer.invoke('app:getClipboardText'),
getNoUpdater: () => ipcRenderer.invoke('app:getNoUpdater'),
setTrayIconNotification: (notify) =>
ipcRenderer.invoke('app:setTrayIconNotification', notify),

View File

@@ -198,7 +198,7 @@
</template>
<script setup>
import { computed, onMounted, ref, watch } from 'vue';
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
@@ -374,6 +374,13 @@
openExternalLink('https://github.com/vrcx-team/VRCX');
};
function handleKeydown(e) {
if (e.ctrlKey && e.key === 'd') {
e.preventDefault();
directAccessPaste();
}
}
const supportLinks = {
wiki: 'https://github.com/vrcx-team/VRCX/wiki',
github: 'https://github.com/vrcx-team/VRCX',
@@ -451,6 +458,11 @@
if (!sentryErrorReporting.value) return;
const feedback = Sentry.getFeedback();
feedback?.attachTo(document.getElementById('feedback'));
window.addEventListener('keydown', handleKeydown);
});
onUnmounted(() => {
window.removeEventListener('keydown', handleKeydown);
});
</script>

View File

@@ -31,6 +31,8 @@ export const useSearchStore = defineStore('Search', () => {
const quickSearchItems = ref([]);
const friendsListSearch = ref('');
const directAccessPrompt = ref(null);
const stringComparer = computed(() =>
Intl.Collator(appearanceSettingsStore.appLanguage.replace('_', '-'), {
usage: 'search',
@@ -217,12 +219,21 @@ export const useSearchStore = defineStore('Search', () => {
return results;
}
function directAccessPaste() {
AppApi.GetClipboard().then((clipboard) => {
if (!directAccessParse(clipboard.trim())) {
promptOmniDirectDialog();
}
});
async function directAccessPaste() {
let cbText = '';
if (LINUX) {
cbText = await window.electron.getClipboardText();
} else {
cbText = await AppApi.GetClipboard().catch((e) => {
console.log(e);
return '';
});
}
let trimemd = cbText.trim();
if (!directAccessParse(trimemd)) {
promptOmniDirectDialog();
}
}
function directAccessParse(input) {
@@ -335,8 +346,10 @@ export const useSearchStore = defineStore('Search', () => {
return false;
}
function promptOmniDirectDialog() {
ElMessageBox.prompt(
async function promptOmniDirectDialog() {
if (directAccessPrompt.value) return;
directAccessPrompt.value = ElMessageBox.prompt(
t('prompt.direct_access_omni.description'),
t('prompt.direct_access_omni.header'),
{
@@ -346,21 +359,24 @@ export const useSearchStore = defineStore('Search', () => {
inputPattern: /\S+/,
inputErrorMessage: t('prompt.direct_access_omni.input_error')
}
)
.then(({ value, action }) => {
if (action === 'confirm' && value) {
const input = value.trim();
if (!directAccessParse(input)) {
ElMessage({
message: t(
'prompt.direct_access_omni.message.error'
),
type: 'error'
});
}
);
try {
const { value, action } = await directAccessPrompt.value;
if (action === 'confirm' && value) {
const input = value.trim();
if (!directAccessParse(input)) {
ElMessage({
message: t('prompt.direct_access_omni.message.error'),
type: 'error'
});
}
})
.catch(() => {});
}
} catch {
} finally {
directAccessPrompt.value = null;
}
}
function showGroupDialogShortCode(shortCode) {

View File

@@ -36,6 +36,7 @@ declare global {
};
electron: {
getArch: () => Promise<string>;
getClipboardText: () => Promise<string>;
getNoUpdater: () => Promise<boolean>;
setTrayIconNotification: (notify: boolean) => Promise<void>;
openFileDialog: () => Promise<string>;