mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-10-14 06:51:58 +00:00
4.20.60
* Added: Backup and Restore now supports backing up any binary data stored in FFZ settings, creating a `zip` file rather than a `json` file. * Fixed: Remove dead code from the `clear-settings` menu component. * Changed: Update the theme mapping to include missing elements. * Changed: Data Management > Storage >> Provider now indicates if a provider supports storing binary data. * Changed: Update the link-parsing regex to match Twitch. Currently under limited roll-out while ensuring the implementation is bug-free. * API Added: `setting-hotkey` now functions as would be expected and can be used. * API Changed: A setting's `onUIChange` method now has the Vue component as its second argument, for getting any necessary state from the settings UI. * API Changed: Providers now sanity check the format of Blobs before storing them.
This commit is contained in:
parent
5412a928a1
commit
2c5937c8af
20 changed files with 574 additions and 138 deletions
171
src/std-components/key-picker.vue
Normal file
171
src/std-components/key-picker.vue
Normal file
|
@ -0,0 +1,171 @@
|
|||
<template lang="html">
|
||||
<div class="ffz--key-widget">
|
||||
<div class="tw-relative tw-full-width tw-mg-05">
|
||||
<div
|
||||
ref="input"
|
||||
v-bind="$attrs"
|
||||
class="default-dimmable tw-block tw-border-radius-medium tw-font-size-6 tw-full-width tw-input tw-pd-l-1 tw-pd-r-3 tw-pd-y-05 tw-mg-y-05"
|
||||
tabindex="0"
|
||||
@click="startRecording"
|
||||
@keydown="onKey"
|
||||
@keyup="onKeyUp"
|
||||
@blur="cancelRecording"
|
||||
>
|
||||
<template v-if="active">
|
||||
{{ t('setting.record-key', 'Press a Key') }}
|
||||
</template>
|
||||
<template v-else-if="value == null">
|
||||
{{ t('setting.unset', 'Unset') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ value }}
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="ffz-button--hollow ffz-clear-key tw-absolute tw-top-0 tw-bottom-0 tw-right-0 tw-border-l tw-z-default tw-pd-x-1 tw-tooltip__container"
|
||||
@click="clear"
|
||||
>
|
||||
<figure class="ffz-i-trash" />
|
||||
<div class="tw-tooltip tw-tooltip--down tw-tooltip--align-right">
|
||||
{{ t('setting.clear', 'Clear') }}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {KEYS} from 'utilities/constants';
|
||||
|
||||
const IGNORE_KEYS = [
|
||||
KEYS.Shift,
|
||||
KEYS.Control,
|
||||
KEYS.Alt,
|
||||
KEYS.Meta
|
||||
];
|
||||
|
||||
const BAD_KEYS = [
|
||||
KEYS.Escape,
|
||||
KEYS.Tab
|
||||
];
|
||||
|
||||
const KEYS_MAP = {
|
||||
Backquote: '`',
|
||||
Comma: ',',
|
||||
Period: '.',
|
||||
Slash: '/',
|
||||
Semicolon: ';',
|
||||
Quote: "'",
|
||||
BracketLeft: '[',
|
||||
BracketRight: ']',
|
||||
Backslash: '\\',
|
||||
Minus: '-',
|
||||
Equal: '=',
|
||||
ArrowLeft: 'left',
|
||||
ArrowRight: 'right',
|
||||
ArrowUp: 'up',
|
||||
ArrowDown: 'down'
|
||||
};
|
||||
|
||||
for(const num of [1,2,3,4,5,6,7,8,9,0])
|
||||
KEYS_MAP[`Digit${num}`] = `${num}`;
|
||||
|
||||
for(const letter of 'abcdefghijklmnopqrstuvwxyz')
|
||||
KEYS_MAP[`Key${letter.toUpperCase()}`] = letter;
|
||||
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: String
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
active: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onKey(e) {
|
||||
if ( this.active )
|
||||
this.record(e);
|
||||
},
|
||||
|
||||
onKeyUp(e) {
|
||||
if ( this.active )
|
||||
this.finishRecording(e);
|
||||
else {
|
||||
const key = e.keyCode || e.which;
|
||||
if ( key === KEYS.Enter || key === KEYS.Space )
|
||||
this.startRecording(e);
|
||||
}
|
||||
},
|
||||
|
||||
stop(e) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
},
|
||||
|
||||
startRecording(e) {
|
||||
if ( e )
|
||||
this.stop(e);
|
||||
|
||||
if ( this.active )
|
||||
return;
|
||||
|
||||
this.active = true;
|
||||
this.key = null;
|
||||
},
|
||||
|
||||
record(e) {
|
||||
const key = e.keyCode || e.which;
|
||||
if ( BAD_KEYS.includes(key) )
|
||||
return;
|
||||
|
||||
this.stop(e);
|
||||
|
||||
if ( IGNORE_KEYS.includes(key) )
|
||||
return;
|
||||
|
||||
this.key = e;
|
||||
},
|
||||
|
||||
cancelRecording() {
|
||||
this.active = false;
|
||||
},
|
||||
|
||||
finishRecording(e) {
|
||||
const k = e.keyCode || e.which;
|
||||
if ( BAD_KEYS.includes(k) )
|
||||
return;
|
||||
|
||||
this.stop(e);
|
||||
|
||||
if ( IGNORE_KEYS.includes(k) )
|
||||
return;
|
||||
|
||||
this.active = false;
|
||||
const key = this.key;
|
||||
this.key = null;
|
||||
if ( ! key )
|
||||
return;
|
||||
|
||||
let code = KEYS_MAP[key.code];
|
||||
if ( ! code )
|
||||
code = key.key;
|
||||
|
||||
const val = `${key.ctrlKey ? 'ctrl+' : ''}${key.altKey ? 'alt+' : ''}${key.shiftKey ? 'shift+' : ''}${code}`;
|
||||
this.$emit('input', val);
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.$emit('input', null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue