mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
feat: ability to add new shortcuts
This commit is contained in:
@ -3,13 +3,18 @@ export const shortcutEvents: { [key: string]: { l18n: string; l18nParam?: string
|
|||||||
'close-tab': { l18n: 'message.closeTab', context: 'tab' },
|
'close-tab': { l18n: 'message.closeTab', context: 'tab' },
|
||||||
'next-tab': { l18n: 'message.nextTab', context: 'tab' },
|
'next-tab': { l18n: 'message.nextTab', context: 'tab' },
|
||||||
'prev-tab': { l18n: 'message.previousTab', context: 'tab' },
|
'prev-tab': { l18n: 'message.previousTab', context: 'tab' },
|
||||||
'open-connections-modal': { l18n: 'message.allConnections' },
|
'open-all-connections': { l18n: 'message.openAllConnections' },
|
||||||
'toggle-console': { l18n: 'message.toggleConsole' }
|
'toggle-console': { l18n: 'message.toggleConsole' },
|
||||||
|
'save-content': { l18n: 'message.saveContent' },
|
||||||
|
'run-or-reload': { l18n: 'message.runOrReload' },
|
||||||
|
'create-connection': { l18n: 'message.createNewConnection' },
|
||||||
|
'open-settings': { l18n: 'message.openSettings' },
|
||||||
|
'open-scratchpad': { l18n: 'message.openScratchpad' }
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ShortcutRecord {
|
interface ShortcutRecord {
|
||||||
event: string;
|
event: string;
|
||||||
keys: Electron.Accelerator[];
|
keys: Electron.Accelerator[] | string[];
|
||||||
/** Needed for default shortcuts */
|
/** Needed for default shortcuts */
|
||||||
os: NodeJS.Platform[];
|
os: NodeJS.Platform[];
|
||||||
}
|
}
|
||||||
@ -18,6 +23,16 @@ interface ShortcutRecord {
|
|||||||
* Default shortcuts
|
* Default shortcuts
|
||||||
*/
|
*/
|
||||||
const shortcuts: ShortcutRecord[] = [
|
const shortcuts: ShortcutRecord[] = [
|
||||||
|
{
|
||||||
|
event: 'run-or-reload',
|
||||||
|
keys: ['F5'],
|
||||||
|
os: ['darwin', 'linux', 'win32']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: 'save-content',
|
||||||
|
keys: ['CommandOrControl+S'],
|
||||||
|
os: ['darwin', 'linux', 'win32']
|
||||||
|
},
|
||||||
{
|
{
|
||||||
event: 'open-new-tab',
|
event: 'open-new-tab',
|
||||||
keys: ['CommandOrControl+T'],
|
keys: ['CommandOrControl+T'],
|
||||||
@ -49,7 +64,7 @@ const shortcuts: ShortcutRecord[] = [
|
|||||||
os: ['linux', 'win32']
|
os: ['linux', 'win32']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
event: 'open-connections-modal',
|
event: 'open-all-connections',
|
||||||
keys: ['Shift+CommandOrControl+Space'],
|
keys: ['Shift+CommandOrControl+Space'],
|
||||||
os: ['darwin', 'linux', 'win32']
|
os: ['darwin', 'linux', 'win32']
|
||||||
},
|
},
|
||||||
|
@ -67,7 +67,7 @@ const { changeApplicationTheme } = settingsStore;
|
|||||||
|
|
||||||
const isAllConnectionsModal: Ref<boolean> = ref(false);
|
const isAllConnectionsModal: Ref<boolean> = ref(false);
|
||||||
|
|
||||||
ipcRenderer.on('open-connections-modal', () => {
|
ipcRenderer.on('open-all-connections', () => {
|
||||||
isAllConnectionsModal.value = true;
|
isAllConnectionsModal.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -68,6 +68,10 @@ const props = defineProps({
|
|||||||
disableAutofocus: {
|
disableAutofocus: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
closeOnConfirm: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['confirm', 'hide']);
|
const emit = defineEmits(['confirm', 'hide']);
|
||||||
@ -90,7 +94,7 @@ const modalSizeClass = computed(() => {
|
|||||||
|
|
||||||
const confirmModal = () => {
|
const confirmModal = () => {
|
||||||
emit('confirm');
|
emit('confirm');
|
||||||
hideModal();
|
if (props.closeOnConfirm) hideModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
const hideModal = () => {
|
const hideModal = () => {
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="form-group has-icon-right p-2 m-0">
|
<div class="form-group has-icon-right m-0">
|
||||||
<input
|
<input
|
||||||
class="form-input"
|
class="form-input"
|
||||||
type="text"
|
type="text"
|
||||||
:value="pressedKeys"
|
:value="pressedKeys"
|
||||||
readonly
|
|
||||||
:placeholder="t('message.registerAShortcut')"
|
:placeholder="t('message.registerAShortcut')"
|
||||||
@focus="isFocus = true"
|
@focus="isFocus = true"
|
||||||
@blur="isFocus = false"
|
@blur="isFocus = false"
|
||||||
@ -94,7 +93,8 @@ const onKey = (e: KeyboardEvent) => {
|
|||||||
keyboardEvent.value = e;
|
keyboardEvent.value = e;
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(pressedKeys, () => {
|
watch(pressedKeys, (value) => {
|
||||||
|
if (value !== t('message.invalidShortcutMessage'))
|
||||||
emit('update:modelValue', pressedKeys.value);
|
emit('update:modelValue', pressedKeys.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -108,10 +108,13 @@ watch(isFocus, (val) => {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.has-icon-right {
|
.has-icon-right {
|
||||||
.form-input {
|
.form-input {
|
||||||
padding-right: 1.4rem;
|
padding-right: 1.8rem;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
caret-color: transparent;
|
||||||
}
|
}
|
||||||
.form-icon {
|
.form-icon {
|
||||||
right: 0.8rem;
|
right: 0.4rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-relative">
|
<div class="p-relative">
|
||||||
<KeyPressDetector />
|
|
||||||
<div class="shortcuts-tools pb-2 px-2">
|
<div class="shortcuts-tools pb-2 px-2">
|
||||||
<button class="btn btn-dark btn-sm d-flex ml-2">
|
<button class="btn btn-dark btn-sm d-flex ml-2" @click="showAddModal">
|
||||||
<i class="mdi mdi-24px mdi-plus mr-1" /><span>{{ t('message.addShortcut') }}</span>
|
<i class="mdi mdi-24px mdi-plus mr-1" /><span>{{ t('message.addShortcut') }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-dark btn-sm d-flex ml-2" @click="isConfirmRestoreModal = true">
|
<button class="btn btn-dark btn-sm d-flex ml-2" @click="isConfirmRestoreModal = true">
|
||||||
@ -56,8 +55,43 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Teleport to="#window-content">
|
<Teleport to="#window-content">
|
||||||
|
<ConfirmModal
|
||||||
|
v-if="isConfirmAddModal"
|
||||||
|
:disable-autofocus="true"
|
||||||
|
:confirm-text="t('word.save')"
|
||||||
|
:close-on-confirm="false"
|
||||||
|
@confirm="addShortcut"
|
||||||
|
@hide="closeAddModal"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="d-flex">
|
||||||
|
<i class="mdi mdi-24px mdi-plus mr-1" /> {{ t('message.addShortcut') }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body>
|
||||||
|
<div class="mb-2">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">{{ t('word.event') }}</label>
|
||||||
|
<BaseSelect
|
||||||
|
v-model="shortcutToAdd.event"
|
||||||
|
class="form-select"
|
||||||
|
:options="eventOptions"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">{{ t('word.key', 2) }}</label>
|
||||||
|
<KeyPressDetector v-model="typedShortcut" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small v-if="doesShortcutExists" class="text-warning">{{ t('message.shortcutAlreadyExists') }}</small>
|
||||||
|
</template>
|
||||||
|
</ConfirmModal>
|
||||||
|
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
v-if="isConfirmDeleteModal"
|
v-if="isConfirmDeleteModal"
|
||||||
|
:disable-autofocus="true"
|
||||||
@confirm="deleteShortcut"
|
@confirm="deleteShortcut"
|
||||||
@hide="isConfirmDeleteModal = false"
|
@hide="isConfirmDeleteModal = false"
|
||||||
>
|
>
|
||||||
@ -74,6 +108,7 @@
|
|||||||
</ConfirmModal>
|
</ConfirmModal>
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
v-if="isConfirmRestoreModal"
|
v-if="isConfirmRestoreModal"
|
||||||
|
:disable-autofocus="true"
|
||||||
@confirm="restoreDefaults"
|
@confirm="restoreDefaults"
|
||||||
@hide="isConfirmRestoreModal = false"
|
@hide="isConfirmRestoreModal = false"
|
||||||
>
|
>
|
||||||
@ -91,7 +126,7 @@
|
|||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Ref, ref } from 'vue';
|
import { Ref, ref, watch } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useSettingsStore } from '@/stores/settings';
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
@ -99,18 +134,36 @@ import KeyPressDetector from './KeyPressDetector.vue';
|
|||||||
import Application from '@/ipc-api/Application';
|
import Application from '@/ipc-api/Application';
|
||||||
import { shortcutEvents, ShortcutRecord } from 'common/shortcuts';
|
import { shortcutEvents, ShortcutRecord } from 'common/shortcuts';
|
||||||
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||||
|
import BaseSelect from '@/components/BaseSelect.vue';
|
||||||
|
import { computed } from '@vue/reactivity';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const isMacOS = process.platform === 'darwin';
|
const isMacOS = process.platform === 'darwin';
|
||||||
|
|
||||||
const isConfirmRestoreModal = ref(false);
|
const isConfirmRestoreModal = ref(false);
|
||||||
|
const isConfirmAddModal = ref(false);
|
||||||
const isConfirmDeleteModal = ref(false);
|
const isConfirmDeleteModal = ref(false);
|
||||||
|
const doesShortcutExists = ref(false);
|
||||||
|
const shortcutToAdd: Ref<ShortcutRecord> = ref({ event: undefined, keys: [], os: [process.platform] });
|
||||||
|
const typedShortcut = ref('');
|
||||||
const shortcutToDelete: Ref<ShortcutRecord> = ref(null);
|
const shortcutToDelete: Ref<ShortcutRecord> = ref(null);
|
||||||
|
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
const { shortcuts } = storeToRefs(settingsStore);
|
const { shortcuts } = storeToRefs(settingsStore);
|
||||||
|
|
||||||
|
const eventOptions = computed(() => {
|
||||||
|
return Object.keys(shortcutEvents)
|
||||||
|
.map(key => {
|
||||||
|
return { value: key, label: t(shortcutEvents[key].l18n, { param: shortcutEvents[key].l18nParam }) };
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (a.label < b.label) return -1;
|
||||||
|
if (a.label > b.label) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const parseKeys = (keys: {[key: number]: string}[]) => {
|
const parseKeys = (keys: {[key: number]: string}[]) => {
|
||||||
return (keys as string[]).map(k => (
|
return (keys as string[]).map(k => (
|
||||||
k.split('+')
|
k.split('+')
|
||||||
@ -127,6 +180,27 @@ const restoreDefaults = () => {
|
|||||||
return Application.restoreDefaultShortcuts();
|
return Application.restoreDefaultShortcuts();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showAddModal = () => {
|
||||||
|
shortcutToAdd.value.event = eventOptions.value[0].value;
|
||||||
|
isConfirmAddModal.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeAddModal = () => {
|
||||||
|
typedShortcut.value = '';
|
||||||
|
doesShortcutExists.value = false;
|
||||||
|
shortcutToAdd.value = { event: undefined, keys: [], os: [process.platform] };
|
||||||
|
isConfirmAddModal.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addShortcut = () => {
|
||||||
|
if (!typedShortcut.value.length || doesShortcutExists.value) return;
|
||||||
|
shortcutToAdd.value.keys = [typedShortcut.value.replaceAll(isMacOS ? '`Command' : 'Control', 'CommandOrControl')];
|
||||||
|
const filteredShortcuts = [shortcutToAdd.value, ...shortcuts.value];
|
||||||
|
|
||||||
|
isConfirmAddModal.value = false;
|
||||||
|
return Application.updateShortcuts(filteredShortcuts);
|
||||||
|
};
|
||||||
|
|
||||||
const showDeleteModal = (shortcut: ShortcutRecord) => {
|
const showDeleteModal = (shortcut: ShortcutRecord) => {
|
||||||
isConfirmDeleteModal.value = true;
|
isConfirmDeleteModal.value = true;
|
||||||
shortcutToDelete.value = shortcut;
|
shortcutToDelete.value = shortcut;
|
||||||
@ -134,11 +208,20 @@ const showDeleteModal = (shortcut: ShortcutRecord) => {
|
|||||||
|
|
||||||
const deleteShortcut = () => {
|
const deleteShortcut = () => {
|
||||||
const filteredShortcuts = shortcuts.value.filter(s => (
|
const filteredShortcuts = shortcuts.value.filter(s => (
|
||||||
shortcutToDelete.value.event !== s.event && shortcutToDelete.value.keys !== s.keys
|
shortcutToDelete.value.keys.toString() !== s.keys.toString()
|
||||||
));
|
));
|
||||||
|
|
||||||
Application.updateShortcuts(filteredShortcuts);
|
isConfirmDeleteModal.value = false;
|
||||||
|
return Application.updateShortcuts(filteredShortcuts);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watch(typedShortcut, () => {
|
||||||
|
doesShortcutExists.value = shortcuts.value.some(s => (
|
||||||
|
s.keys.some(k => (
|
||||||
|
k.replaceAll('CommandOrControl', isMacOS ? '`Command' : 'Control') === typedShortcut.value
|
||||||
|
))
|
||||||
|
));
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.table {
|
.table {
|
||||||
|
@ -343,6 +343,7 @@ watch(selectedWorkspace, (newVal, oldVal) => {
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
color: rgba($body-font-color-dark, 0.8);
|
color: rgba($body-font-color-dark, 0.8);
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settingbar-element-pin {
|
.settingbar-element-pin {
|
||||||
|
@ -309,7 +309,13 @@ export const enUS = {
|
|||||||
restoreDefaultsQuestion: 'Do you confirm to restore default values?',
|
restoreDefaultsQuestion: 'Do you confirm to restore default values?',
|
||||||
registerAShortcut: 'Register a shortcut',
|
registerAShortcut: 'Register a shortcut',
|
||||||
deleteShortcut: 'Delete shortcut',
|
deleteShortcut: 'Delete shortcut',
|
||||||
invalidShortcutMessage: 'Invalid combination, continue to type'
|
invalidShortcutMessage: 'Invalid combination, continue to type',
|
||||||
|
shortcutAlreadyExists: 'Shortcut already exists',
|
||||||
|
saveContent: 'Save content',
|
||||||
|
openAllConnections: 'Open all connections',
|
||||||
|
openSettings: 'Open settings',
|
||||||
|
openScratchpad: 'Open scratchpad',
|
||||||
|
runOrReload: 'Run or reload'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
|
@ -163,7 +163,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
background-color: #000;
|
background-color: #111;
|
||||||
|
border: 1px solid #444;
|
||||||
color: rgba($body-font-color-dark, 0.7);
|
color: rgba($body-font-color-dark, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,6 +209,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background-color: #eee;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
.workspace {
|
.workspace {
|
||||||
.workspace-explorebar {
|
.workspace-explorebar {
|
||||||
background: $bg-color-light-gray;
|
background: $bg-color-light-gray;
|
||||||
|
Reference in New Issue
Block a user