Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Commit

Permalink
Use localstorage to save settings. Add keyboard shortcuts.
Browse files Browse the repository at this point in the history
  • Loading branch information
curtgrimes committed Apr 9, 2018
1 parent c543a72 commit 4e0ca50
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 13 deletions.
5 changes: 5 additions & 0 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/package.json
Expand Up @@ -14,6 +14,7 @@
"audio-stream-meter": "^1.0.4",
"body-parser": "^1.17.2",
"bootstrap": "^4.0.0",
"combokeys": "^3.0.0",
"compression": "^1.7.2",
"cookie-parser": "~1.4.3",
"cross-env": "^5.1.4",
Expand Down
31 changes: 30 additions & 1 deletion app/src/App.vue
Expand Up @@ -58,9 +58,38 @@

<script>
import VolumeMeter from './components/VolumeMeter.vue'
import Combokeys from 'combokeys'
export default {
name: 'settings-view',
name: 'app-view',
data: function() {
return {
combokeysDocument: null,
};
},
mounted: function() {
let self = this;
this.combokeysDocument = new Combokeys(document.documentElement);
this.combokeysDocument
.bind('w s', function() {
self.$router.push('/captioner/settings');
})
.bind('?', function() {
self.$router.push('/captioner/settings/keyboard-shortcuts');
})
.bind('w c', function() {
self.$router.push('/captioner');
if (!self.captioningOn) {
self.startCaptioning();
}
else {
self.stopCaptioning();
}
});
},
beforeDestroy: function() {
this.combokeysDocument.detach();
},
components: {
VolumeMeter,
},
Expand Down
41 changes: 36 additions & 5 deletions app/src/components/Transcript.vue
@@ -1,10 +1,15 @@
<template>
<div
ref="transcript"
class="transcript d-flex align-items-end"
class="transcript d-flex align-items-end" v-bind:class="wrapTextPositionClass"
v-bind:style="{color, backgroundColor}"
>
{{finalTranscript}} <span>{{interimTranscript}}</span>
<span class="" v-bind:class="textPositionClass">
<span class="transcript-child d-flex align-items-end" ref="transcriptScroller">
<span>
{{finalTranscript}} <span v-bind:style="{color: interimColor}">{{interimTranscript}}</span>
</span>
</span>
</span>
</div>
</template>

Expand All @@ -16,8 +21,8 @@ export default {
methods: {
scrollToBottom: function () {
this.$nextTick(function () {
if (this.$refs.transcript) {
this.$refs.transcript.scrollTop = this.$refs.transcript.scrollHeight;
if (this.$refs.transcriptScroller) {
this.$refs.transcriptScroller.scrollTop = this.$refs.transcriptScroller.scrollHeight;
}
});
},
Expand All @@ -26,6 +31,9 @@ export default {
color () {
return this.$store.state.settings.appearance.text.textColor;
},
interimColor () {
return this.$store.state.settings.appearance.text.textColorInterim;
},
backgroundColor () {
return this.$store.state.settings.appearance.background.color;
},
Expand All @@ -37,6 +45,29 @@ export default {
this.scrollToBottom();
return ' ' + this.$store.state.captioner.transcript.interim;
},
textPositionClass: function () {
return {
/* Horizontal alignments */
'w-100 mx-0': this.$store.state.settings.appearance.text.alignment.horizontal == 'full',
'w-50 mr-auto': this.$store.state.settings.appearance.text.alignment.horizontal == 'left',
'w-50 mx-auto': this.$store.state.settings.appearance.text.alignment.horizontal == 'middle',
'w-50 ml-auto': this.$store.state.settings.appearance.text.alignment.horizontal == 'right',
/* Vertical alignments */
// 'h-100': this.$store.state.settings.appearance.text.alignment.vertical == 'full',
'h-50': ['top','middle','bottom'].includes(this.$store.state.settings.appearance.text.alignment.vertical),
'h-25': this.$store.state.settings.appearance.text.alignment.vertical == 'lowerThird',
}
},
wrapTextPositionClass: function () {
return {
/* Vertical alignments */
'align-items-start': ['full','top'].includes(this.$store.state.settings.appearance.text.alignment.vertical),
'align-items-center': this.$store.state.settings.appearance.text.alignment.vertical == 'middle',
'align-items-end': ['bottom','lowerThird'].includes(this.$store.state.settings.appearance.text.alignment.vertical),
}
},
},
}
</script>
Expand Down
3 changes: 2 additions & 1 deletion app/src/data/changelog.js
Expand Up @@ -4,8 +4,9 @@ export default [
date: "2018-04-01",
notes: [
'A rewrite of Web Captioner to make fixes and future development much easier. Please leave me <a href="/feedback">lots of feedback</a>.',
'Added search box in <a href="/captioner/settings/language">language settings</a>.',
'Added <a href="/captioner/settings/keyboard-shortcuts">keyboard shortcuts</a> because keyboard shortcuts are cool.',
'Added an option to show asterisks for <a href="/captioner/settings/censor">censored words</a>.',
'Added search box in <a href="/captioner/settings/language">language settings</a>.',
'Removed the chroma key background color setting for simplicity. You can still change the background color on the <a href="/captioner/settings/appearance">appearance tab</a>.'
],
},
Expand Down
9 changes: 9 additions & 0 deletions app/src/entry-client.js
Expand Up @@ -40,6 +40,15 @@ if (window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__)
}

// Restore locally saved settings
const localSettings = JSON.parse(localStorage.getItem('webcaptioner:settings'));
if (localSettings) {
store.commit('RESTORE_SETTINGS', {
settings: localSettings.settings,
version: localSettings.version,
});
}

store.dispatch('SET_LOCALE_FROM_USER_DEFAULT');


Expand Down
5 changes: 5 additions & 0 deletions app/src/router/index.js
Expand Up @@ -16,6 +16,7 @@ const SettingsLanguageView = () => import('../views/settings/SettingsLanguageVie
const SettingsWordReplacementsView = () => import('../views/settings/SettingsWordReplacementsView.vue')
const SettingsCensorView = () => import('../views/settings/SettingsCensorView.vue')
const SettingsVmixView = () => import('../views/settings/SettingsVmixView.vue')
const SettingsKeyboardShortcutsView = () => import('../views/settings/SettingsKeyboardShortcutsView.vue')
const CaptionerView = () => import('../views/CaptionerView.vue')
const CaptionerCaptionView = () => import('../views/CaptionerCaptionView.vue')

Expand Down Expand Up @@ -54,6 +55,10 @@ export function createRouter () {
path: 'vmix',
component: SettingsVmixView
},
{
path: 'keyboard-shortcuts',
component: SettingsKeyboardShortcutsView
},
]
},
]
Expand Down
7 changes: 6 additions & 1 deletion app/src/scss/app.scss
Expand Up @@ -299,7 +299,7 @@ a.nav-link.active {
}

.transcript {
overflow: hidden;
overflow-y:scroll;
height: 100vh;
width:100%;
line-height: 5rem;
Expand All @@ -311,6 +311,11 @@ a.nav-link.active {
padding-bottom:4rem;
}

.transcript-child {
overflow-y:scroll;
max-height:100%;
}

.final:focus {
outline:0;
}
Expand Down
1 change: 1 addition & 0 deletions app/src/store/actions.js
Expand Up @@ -24,6 +24,7 @@ export default {
},



// ensure data for rendering given list type
FETCH_LIST_DATA: ({ commit, dispatch, state }, { type }) => {
commit('SET_ACTIVE_TYPE', { type })
Expand Down
13 changes: 11 additions & 2 deletions app/src/store/index.js
Expand Up @@ -5,7 +5,7 @@ import mutations from './mutations'
import getters from './getters'
import captioner from './modules/captioner'
import fontChocies from '../util/fontChoices'
import VuexPersistence from 'vuex-persist'
import vuexPersist from 'vuex-persist'

Vue.use(Vuex)

Expand All @@ -15,6 +15,7 @@ export function createStore () {
captioner,
},
state: {
version: '2.0.0',
settings: {
appearance: {
text: {
Expand Down Expand Up @@ -55,6 +56,14 @@ export function createStore () {
actions,
mutations,
getters,
plugins: [(new VuexPersistence({})).plugin],
plugins: [new vuexPersist({
key: 'webcaptioner:settings',
reducer: (state) => {
return {
settings: state.settings,
version: state.version,
};
},
}).plugin],
})
}
4 changes: 2 additions & 2 deletions app/src/store/modules/captioner/index.js
Expand Up @@ -6,8 +6,8 @@ let speechRecognizer;
const state = {
on: false,
transcript: {
interim: '',
final: '',
interim: 'hello',
final: 'hello2',
},
volume: {
tooLow: false,
Expand Down
3 changes: 3 additions & 0 deletions app/src/store/mutations.js
@@ -1,6 +1,9 @@
import Vue from 'vue'

export default {
RESTORE_SETTINGS: (state, { settings, version }) => {
state.settings = settings;
},
SET_TEXT_COLOR: (state, { textColor }) => {
state.settings.appearance.text.textColor = textColor
},
Expand Down
26 changes: 25 additions & 1 deletion app/src/views/SettingsView.vue
@@ -1,5 +1,5 @@
<template>
<div class="settings-view h-100 bg-primary">
<div class="settings-view h-100 bg-primary" v-on:keyup.enter="alert('hi')">
<router-link to="/captioner" class="btn btn-primary position-fixed py-md-3 px-3 px-md-4" style="z-index:2;right:0;top:0" role="tab" active-class=""><i class="fa fa-times fa-2x" aria-label="Close"></i></router-link>
<div class="container pb-5 h-100">
<div class="row h-100">
Expand All @@ -17,6 +17,10 @@
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<router-link to="vmix" class="nav-link" role="tab" active-class="active">vMix</router-link>
</div>
<hr/>
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<router-link to="keyboard-shortcuts" class="nav-link" role="tab" active-class="active">Keyboard Shortcuts</router-link>
</div>
</div>
</div>
<div class="col-md-9 mb-2 py-5">
Expand All @@ -30,9 +34,25 @@
</template>

<script>
import Combokeys from 'combokeys'
export default {
name: 'settings-view',
data: function() {
return {
escShortcut: null,
};
},
mounted: function() {
let self = this;
this.escShortcut = new Combokeys(document.documentElement);
this.escShortcut.bind('esc', function() {
self.$router.push('/captioner');
});
},
beforeDestroy: function() {
this.escShortcut.detach();
},
}
</script>

Expand All @@ -42,4 +62,8 @@ export default {
font-size:1.3rem;
margin:1rem 0;
}
.settings-view .nav-pills {
font-size:0.92rem;
}
</style>
33 changes: 33 additions & 0 deletions app/src/views/settings/SettingsKeyboardShortcutsView.vue
@@ -0,0 +1,33 @@
<template>
<div class="settings-word-replacements-view">
<h2>Keyboard Shortcuts</h2>

<div class="list-group">
<div class="list-group-item">
<div class="row">
<div class="col-6">Toggle Captioning On/Off</div>
<div class="col-6 text-right"><kbd>w</kbd> then <kbd>c</kbd></div>
</div>
</div>
<div class="list-group-item">
<div class="row">
<div class="col-6">Settings</div>
<div class="col-6 text-right"><kbd>w</kbd> then <kbd>s</kbd></div>
</div>
</div>
<div class="list-group-item">
<div class="row">
<div class="col-6">List Keyboard Shortcuts</div>
<div class="col-6 text-right"><kbd>?</kbd></div>
</div>
</div>
</div>
</div>
</template>

<script>
export default {
name: 'settings-keyboard-shortcuts-view',
}
</script>

0 comments on commit 4e0ca50

Please sign in to comment.