Sort out inputs, shortcut button
This commit is contained in:
parent
6ce8bba6b7
commit
0daef615c1
189
src/common/components/EditShortcutButton.vue
Normal file
189
src/common/components/EditShortcutButton.vue
Normal file
@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<div class="flex flex-row">
|
||||
<div
|
||||
class="flex-grow button"
|
||||
@click="editShortcut()"
|
||||
|
||||
>
|
||||
<template v-if="!editing">
|
||||
{{shortcutDisplay}}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{currentKeypress ?? 'Press a key'}}
|
||||
<input ref="input"
|
||||
class="hidden-input"
|
||||
@keyup.capture="keyup($event)"
|
||||
@keydown.capture="keydown($event)"
|
||||
@input.prevent=""
|
||||
@blur="editing = false;"
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import KeyboardShortcutParser from '../js/KeyboardShortcutParser';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
shortcut: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentKeypress: undefined,
|
||||
currentKey: undefined,
|
||||
editing: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
shortcutDisplay() {
|
||||
if (!this.shortcut) {
|
||||
return '(no shortcut)'
|
||||
}
|
||||
return KeyboardShortcutParser.parseShortcut(this.shortcut);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
editShortcut() {
|
||||
this.editing = true;
|
||||
this.currentKeypress = undefined;
|
||||
this.currentKey = undefined;
|
||||
|
||||
// input doesn't exist now, but will exist on the next tick
|
||||
this.$nextTick(()=> this.$refs.input.focus());
|
||||
},
|
||||
/**
|
||||
* Updates currently pressed keypress for display
|
||||
*/
|
||||
keydown(event) {
|
||||
// event.repeat is set to 'true' when key is being held down, but not on
|
||||
// first keydown. We don't need to process subsequent repeats of a keypress
|
||||
// we already processed.
|
||||
if (event.repeat) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shortcut = KeyboardShortcutParser.generateShortcutFromKeypress(event);
|
||||
const fixedShortcut = this.handleModifierKeypress(shortcut);
|
||||
|
||||
if (this.currentKey === undefined) {
|
||||
this.currentKey = fixedShortcut;
|
||||
} else {
|
||||
// here's a fun fact. Keydown doesn't do modifier keys the way we want —
|
||||
// notably, A-Z0-9 keys are returned without modifier state (all modifiers)
|
||||
// are set to false in keydown events. That means we need to keep track of
|
||||
// modifiers ourselves.
|
||||
if (fixedShortcut.notModifier) {
|
||||
this.currentKey.key = fixedShortcut.key;
|
||||
this.currentKey.code = fixedShortcut.code;
|
||||
} else {
|
||||
this.currentKey = {
|
||||
...fixedShortcut,
|
||||
key: this.currentKey.key,
|
||||
code: this.currentKey.code
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update display
|
||||
this.currentKeypress = KeyboardShortcutParser.parseShortcut(this.currentKey);
|
||||
},
|
||||
/**
|
||||
* Emits shortcutChanged when shortcut is considered changed
|
||||
*/
|
||||
keyup(event) {
|
||||
const shortcut = KeyboardShortcutParser.generateShortcutFromKeypress(event);
|
||||
const fixedShortcut = this.handleModifierKeypress(shortcut);
|
||||
|
||||
if (fixedShortcut.notModifier) {
|
||||
this.editing = false;
|
||||
this.$emit('shortcutChanged', this.currentKey);
|
||||
console.log('emitted shortcut:', shortcut, 'raw event:', event);
|
||||
} else {
|
||||
// if none of the modifiers are pressed and if no other key is being held down,
|
||||
// we need to reset label back to 'pls press key'
|
||||
if (!fixedShortcut.altKey && !fixedShortcut.ctrlKey && !fixedShortcut.metaKey && !fixedShortcut.shiftKey && !fixedShortcut.code) {
|
||||
this.currentKeypress = undefined;
|
||||
this.currentKey = undefined;
|
||||
} else {
|
||||
this.currentKey = shortcut;
|
||||
this.currentKeypress = KeyboardShortcutParser.parseShortcut(this.currentKey);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles current keypress if event.keyCode is a modifier key.
|
||||
* Returns true if current event was a modifier key, false if
|
||||
* if was a regular A-Z 0-9 key.
|
||||
*/
|
||||
handleModifierKeypress(event) {
|
||||
const modifierPressed = event.type === 'keydown';
|
||||
|
||||
switch (event.code) {
|
||||
case 'ShiftLeft':
|
||||
case 'ShiftRight':
|
||||
return {
|
||||
...event,
|
||||
key: '…',
|
||||
code: null,
|
||||
shiftKey: modifierPressed
|
||||
}
|
||||
case 'ControlLeft':
|
||||
case 'ControlRight':
|
||||
return {
|
||||
...event,
|
||||
key: '…',
|
||||
code: null,
|
||||
controlKey: modifierPressed
|
||||
};
|
||||
case 'MetaLeft':
|
||||
case 'MetaRight':
|
||||
return {
|
||||
...event,
|
||||
key: '…',
|
||||
code: null,
|
||||
metaKey: modifierPressed
|
||||
};
|
||||
case 'AltLeft':
|
||||
case 'AltRight':
|
||||
return {
|
||||
...event,
|
||||
key: '…',
|
||||
code: null,
|
||||
altKey: modifierPressed
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...event,
|
||||
notModifier: true,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" src="../../csui/src/res-common/common.scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
@import "../../csui/src/res-common/variables";
|
||||
|
||||
.center-text {
|
||||
text-align: center;
|
||||
}
|
||||
.dark {
|
||||
opacity: 50%;
|
||||
}
|
||||
|
||||
.hidden-input {
|
||||
position: absolute;
|
||||
z-index: -9999;
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
@ -1,38 +0,0 @@
|
||||
<template>
|
||||
<div class="flex flex-column flex-center">
|
||||
<template v-if="!editing">
|
||||
<div class="flex flex-self-center">
|
||||
{{label}}
|
||||
</div>
|
||||
<div class="flex dark flex-self-center">
|
||||
<small>
|
||||
{{shortcut ? `(${shortcut})` : ''}}
|
||||
</small>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="flex flex-row flex-center">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
label: String,
|
||||
shortcut: String,
|
||||
editing: Boolean,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.center-text {
|
||||
text-align: center;
|
||||
}
|
||||
.dark {
|
||||
opacity: 50%;
|
||||
}
|
||||
</style>
|
@ -21,6 +21,19 @@ class KeyboardShortcutParser {
|
||||
}
|
||||
return shortcutCombo;
|
||||
}
|
||||
|
||||
static generateShortcutFromKeypress(event) {
|
||||
return {
|
||||
ctrlKey: event.ctrlKey,
|
||||
shiftKey: event.altKey,
|
||||
altKey: event.altKey,
|
||||
code: event.code,
|
||||
key: event.key,
|
||||
keyup: true,
|
||||
keydown: false,
|
||||
type: event.type, // only needed for purposes of EditShortcutButton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default KeyboardShortcutParser;
|
@ -50,48 +50,58 @@
|
||||
</div>
|
||||
|
||||
<!-- EDIT MODE PANEL -->
|
||||
<div class="edit-action-area">
|
||||
<div>
|
||||
Editing options for <b>{{editModeOptions?.crop?.selected?.label}}</b>
|
||||
</div>
|
||||
|
||||
<!-- Some options are only shown for type 4 (fixed) crops -->
|
||||
<template v-if="editModeOptions?.crop?.selected.arguments.type === AspectRatioType.Fixed">
|
||||
<div>
|
||||
Label: -- todo --
|
||||
<div class="sub-panel-content">
|
||||
<div class="edit-action-area">
|
||||
<div class="edit-action-area-header">
|
||||
Editing options for: <b>{{editModeOptions?.crop?.selected?.label}}</b>
|
||||
</div>
|
||||
<div>
|
||||
Ratio: -- todo --
|
||||
|
||||
<!-- Some options are only shown for type 4 (fixed) crops -->
|
||||
<template v-if="editModeOptions?.crop?.selected?.arguments?.type === AspectRatioType.Fixed">
|
||||
<div class="field">
|
||||
<div class="label">
|
||||
Ratio:
|
||||
</div>
|
||||
<div class="input">
|
||||
<input v-model="editModeOptions.crop.selected.arguments.ratio">
|
||||
</div>
|
||||
<div class="hint">
|
||||
You can enter a ratio in width:height format (e.g. "21:9" or "1:2.39"), or just the factor
|
||||
(in this case, "1:2.39" would become "2.39" and "21:9" would become "2.33"). You should enter
|
||||
your numbers without quote marks. Number will be converted to factor form on save.
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">
|
||||
Label:
|
||||
</div>
|
||||
<div class="input">
|
||||
<input v-model="editModeOptions.crop.selected.label">
|
||||
</div>
|
||||
<div class="hint">
|
||||
Label for the button. You can make it say something other than ratio.
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- editing keyboard shortcuts is always allowed -->
|
||||
<div class="field">
|
||||
<div class="label">Shortcut:</div>
|
||||
<div class="">
|
||||
<EditShortcutButton
|
||||
:shortcut="editModeOptions?.crop?.selected?.shortcut"
|
||||
@shortcutChanged="updateSelectedShortcut($event, 'crop')"
|
||||
>
|
||||
</EditShortcutButton>
|
||||
</div>
|
||||
<div class="hint">
|
||||
<b>Note:</b> Your browser and OS already use certain key combinations that involve Ctrl and Meta (Windows) keys — and, to a lesser extent, Alt.
|
||||
The extension doesn't (and cannot) check whether the keyboard shortcut you enter is actually free for you to use. The extension also won't override
|
||||
any keyboard shortcuts defined by the site itself.
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- editing keyboard shortcuts is always allowed -->
|
||||
<div>
|
||||
-- todo: edit keyboard shortcut --
|
||||
</div>
|
||||
|
||||
<div>
|
||||
------------ <br/>>
|
||||
present items:<br/>>
|
||||
editModeOptions? {{!!editModeOptions}}<br/>
|
||||
.crop? {{!!editModeOptions?.crop}}<br/>
|
||||
.selected? {{!!editModeOptions?.crop?.selected}}<br/>
|
||||
<br/>
|
||||
selected action:<br/>{{editModeOptions?.crop?.selected}}
|
||||
</div>
|
||||
|
||||
<!-- <select class=""
|
||||
:value="selectedAction"
|
||||
@change="setAction($event.target.value)"
|
||||
>
|
||||
<option :value="undefined" selected disabled>Select ...</option>
|
||||
<option v-for="(action, key) in ActionList"
|
||||
:value="key"
|
||||
:key="key"
|
||||
>
|
||||
{{action.name}}
|
||||
</option>
|
||||
</select> -->
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row">
|
||||
@ -297,6 +307,7 @@
|
||||
import Button from '../../../common/components/Button.vue'
|
||||
import KeyboardShortcutParser from '../../../common/js/KeyboardShortcutParser';
|
||||
import ShortcutButton from '../../../common/components/ShortcutButton';
|
||||
import EditShortcutButton from '../../../common/components/EditShortcutButton';
|
||||
import ComputeActionsMixin from '../../../common/mixins/ComputeActionsMixin';
|
||||
import ExecAction from '../ui-libs/ExecAction';
|
||||
import BrowserDetect from '../../../ext/conf/BrowserDetect';
|
||||
@ -319,7 +330,8 @@ export default {
|
||||
y: 0
|
||||
},
|
||||
editMode: true,
|
||||
editModeOptions: {},
|
||||
editModeOptions: {
|
||||
},
|
||||
resizerConfig: {
|
||||
crop: null,
|
||||
stretch: null,
|
||||
@ -357,6 +369,7 @@ export default {
|
||||
},
|
||||
components: {
|
||||
ShortcutButton,
|
||||
EditShortcutButton,
|
||||
Button,
|
||||
AlignmentOptionsControlComponent
|
||||
},
|
||||
@ -521,6 +534,18 @@ export default {
|
||||
console.error(`[Ultrawidify] there's a problem with VideoSettings.vue::editAction():`, e);
|
||||
}
|
||||
},
|
||||
|
||||
updateSelectedShortcut(shortcut, actionType) {
|
||||
try {
|
||||
if (!this.editModeOptions[actionType]?.selected) {
|
||||
return;
|
||||
} else {
|
||||
this.editModeOptions[actionType].selected.shortcut = shortcut
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`[Ultrawidify] there's a problem with VideoSettings.vue::updateShortcut():`, e);
|
||||
}
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//#region comms and bus
|
||||
@ -588,4 +613,13 @@ export default {
|
||||
padding-bottom: 16px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.edit-action-area {
|
||||
background-color: rgba($blackBg,0.5);
|
||||
padding: 0.5rem;
|
||||
|
||||
.edit-action-area-header {
|
||||
border-bottom: 1px solid rgba(255,255,255,0.5);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -3,3 +3,7 @@ $warning-color: #d6ba4a;
|
||||
$primary: rgb(255, 147, 85);
|
||||
$primaryBrighter: rgb(255, 174, 127);
|
||||
$primaryBg: rgba(54, 31, 21, 0.5);
|
||||
|
||||
$blackBg: rgb(11,11,11);
|
||||
$normalTransparentOpacity: 0.5;
|
||||
$hoverTransparentOpacity: 0.9;
|
||||
|
@ -31,13 +31,18 @@ h1, h2, h3 {
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: rgba(11,11,11,0.5);
|
||||
background-color: rgba($blackBg, $normalTransparentOpacity);
|
||||
|
||||
padding: 0.5rem 2rem;
|
||||
margin: 3px;
|
||||
|
||||
color: #aaa;
|
||||
border: 1px solid transparent;
|
||||
user-select: none !important;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background-color: rgba(11,11,11,0.9);
|
||||
background-color: rgba($blackBg, $hoverTransparentOpacity);
|
||||
border-bottom: 1px solid rgba($primary, 0.5);
|
||||
}
|
||||
|
||||
@ -51,3 +56,47 @@ h1, h2, h3 {
|
||||
margin: 0.25rem;
|
||||
padding: 0.5rem 2rem;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
padding-top: 0.5rem;
|
||||
|
||||
align-items: center;
|
||||
|
||||
.label {
|
||||
flex: 0 0 25%;
|
||||
text-align: right;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.input {
|
||||
flex: 0 0 70%;
|
||||
background-color: rgba($blackBg, $normalTransparentOpacity);
|
||||
border: 1px solid transparent;
|
||||
border-bottom: 1px solid rgba(255,255,255,0.5);
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
|
||||
&:active, &:focus, &:focus-within {
|
||||
border-bottom: 1px solid rgba($primary, 0.5);
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
outline: none;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.hint {
|
||||
padding-left: calc(25% + 1rem);
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
@ -226,18 +226,16 @@ small {
|
||||
}
|
||||
|
||||
.button {
|
||||
/*display: inline-block;*/
|
||||
// padding-top: 8px;
|
||||
// padding-bottom: 3px;
|
||||
//padding-left: 5px;
|
||||
//padding-right: 5px;
|
||||
border: 1px solid rgb(39, 39, 39);
|
||||
border: 1px solid transparent;
|
||||
padding: 0.5rem 2rem;
|
||||
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
|
||||
color: $text-dim;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
user-select: none;;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user