Changeset 35525


Ignore:
Timestamp:
2021-09-29T15:28:53+13:00 (3 years ago)
Author:
cstephen
Message:

Add hold-to-scrub for audio steppers. Split word when pressing space in the middle.

Location:
main/trunk/model-interfaces-dev/atea/korero-maori-asr/src/components
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/model-interfaces-dev/atea/korero-maori-asr/src/components/AudioTimeBar.vue

    r35454 r35525  
    33    <input type="range" class="slider-continuous" v-model.number="sliderValue" min="0" :max="audioLength" step="0.01" :disabled="isDisabled" />
    44
    5     <button type="button" class="btn-fab theme-flat" @click="stepBack" :disabled="isDisabled">
     5    <button type="button" class="btn-fab theme-flat" :disabled="isDisabled"
     6            @click="stepBack" @mousedown="onStepBackMouseDown" @mouseup="onStepperMouseUp">
    67        <span class="material-icons mdi-s">arrow_back_ios_new</span>
    78    </button>
     
    910    <span>{{ stringSliderValue }}</span>
    1011
    11     <button type="button" class="btn-fab theme-flat" @click="stepForward" :disabled="isDisabled">
     12    <button type="button" class="btn-fab theme-flat" :disabled="isDisabled"
     13            @click="stepForward" @mousedown="onStepForwardMouseDown" @mouseup="onStepperMouseUp">
    1214        <span class="material-icons mdi-s">arrow_forward_ios</span>
    1315    </button>
     
    3537    },
    3638    emits: [ "update:modelValue" ],
     39    data() {
     40        return {
     41            stepperHeld: false,
     42            stepperHeldTimeout: null
     43        }
     44    },
    3745    computed: {
    3846        sliderValue: {
     
    6270        stepForward() {
    6371            AudioPlayback.scrub(this.modelValue + 0.1);
     72        },
     73        onStepBackMouseDown() {
     74            this.stepperHeldTimeout = setTimeout(() => this.continuousStep(true, this), 500);
     75            this.stepperHeld = true;
     76        },
     77        onStepForwardMouseDown() {
     78            this.stepperHeldTimeout = setTimeout(() => this.continuousStep(false, this), 500);
     79            this.stepperHeld = true;
     80        },
     81        onStepperMouseUp() {
     82            this.stepperHeld = false;
     83            clearTimeout(this.stepperHeldTimeout);
     84        },
     85        continuousStep(back, vm) {
     86            (function run() {
     87                if (!vm.stepperHeld) {
     88                    return;
     89                }
     90
     91                if (back) {
     92                    vm.stepBack();
     93                }
     94                else {
     95                    vm.stepForward();
     96                }
     97
     98                setTimeout(run, 25); // 40hz
     99            })();
    64100        }
    65101    }
  • main/trunk/model-interfaces-dev/atea/korero-maori-asr/src/components/TranscriptionItemEditor.vue

    r35521 r35525  
    208208            /** @type {Word} */
    209209            const word = this.words[index];
    210 
    211             if (deletionEvents.includes(event.inputType) && word.word.length === 0) {
    212                 event.preventDefault(); // Prevents the event from being propagated to the newly focused input
    213                 this.setFocus(index, event.inputType === "deleteContentBackward"); // Shifting focus off an empty input, hence the word will be removed
     210            const inputIndex = this.$refs[word.id].selectionStart;
     211
     212            if (deletionEvents.includes(event.inputType)) {
     213                if (word.word.length === 0) { // Remove the word
     214                    this.setFocus(index, event.inputType === "deleteContentBackward"); // Shifting focus off an empty input, hence the word will be removed
     215                    event.preventDefault(); // Prevents the event from being propagated to the newly focused input
     216                    // TODO: Shuffle timestamps
     217                }
     218                else if (inputIndex === 0 && event.inputType === "deleteContentBackward") {
     219                    // TODO: Join with previous
     220                }
     221                else if (inputIndex === word.word.length && event.inputType === "deleteContentForward") {
     222                    // TODO: Join with next
     223                }
    214224            }
    215225
    216226            if (insertionEvents.includes(event.inputType)) {
    217                 const inputIndex = this.$refs[word.id].selectionStart;
    218 
    219227                if (event.data === " ") { // ONLY whitespace entered. Split or add new word
    220228                    let newWord;
    221229
    222                     if (inputIndex === 0) {
     230                    if (inputIndex === 0) { // Insert on left side
    223231                        const newEndTime = word.startTime + (word.endTime - word.startTime) / 2;
    224232                        newWord = new Word("", word.startTime, newEndTime);
     
    227235                        word.startTime = newEndTime;
    228236                    }
    229                     else if (inputIndex === word.word.length) {
     237                    else if (inputIndex === word.word.length) { // Insert on right side
    230238                        const newStartTime = word.startTime + ((word.endTime - word.startTime) / 2);
    231239                        newWord = new Word("", newStartTime, word.endTime);
     
    234242                        word.endTime = newStartTime;
    235243                    }
    236                     else {
    237                         // Split down middle
     244                    else { // Split down the middle
     245                        const metadataIndex = this.transcription.metadata.findIndex(m => m.start_time === word.startTime) + inputIndex;
     246                        const newStartTime = this.transcription.metadata[metadataIndex].start_time;
     247                        newWord = new Word(word.word.slice(inputIndex), newStartTime, word.endTime);
     248
     249                        this.words.splice(index + 1, 0, newWord);
     250                        word.endTime = newStartTime;
     251                        word.word = word.word.slice(0, inputIndex);
    238252                    }
    239253
    240254                    event.preventDefault();
    241                     setTimeout(() => this.$refs[newWord.id].focus(), 50); // Give the element time to be mounted before focusing
     255                    // Give the element time to be mounted before focusing
     256                    setTimeout(
     257                        () => {
     258                            this.$refs[newWord.id].focus();
     259                            this.$refs[newWord.id].selectionStart = 0;
     260                            this.$refs[newWord.id].selectionEnd = null;
     261                        },
     262                        50
     263                    );
    242264                }
    243265                else if (event.data.includes(" ")) {
    244                     // Split input
     266                    // TODO: Split input
    245267                }
    246268            }
  • main/trunk/model-interfaces-dev/atea/korero-maori-asr/src/components/WordTimingSelector.vue

    r35508 r35525  
    191191        },
    192192        shouldHoist(word) {
    193             return word.startTime === this.word.startTime && word.word === this.word.word;
     193            return word && this.word && word.startTime === this.word.startTime && word.word === this.word.word;
    194194        },
    195195        /**
Note: See TracChangeset for help on using the changeset viewer.