Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an in-app guided tour #586

Merged
merged 1 commit into from
Feb 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@types/chai": "^4.3.0",
"@types/crypto-js": "^4.1.1",
"@types/electron-devtools-installer": "^2.2.1",
"@types/ffi-napi": "^4.0.7",
"@types/lodash": "^4.14.181",
"@types/mocha": "^9.1.0",
"@types/node-abi": "^3.0.0",
Expand Down Expand Up @@ -97,6 +98,7 @@
"postcss-import": "^14.0.2",
"prettier": "2.6.2",
"replace": "^1.2.1",
"sam-js": "Imrane03/better-sam",
"sass": "^1.49.11",
"sass-loader": "^12.0.0",
"socket.io-client": "^4.5.4",
Expand All @@ -110,13 +112,12 @@
"vue-query": "^1.22.3",
"vue-router": "^4.0.14",
"vue-tippy": "^6.0.0-alpha.54",
"vue-tour": "^2.0.0",
"vue3-moveable": "^0.11.2",
"vue3-styled-components": "^1.2.1",
"vuex": "^4.0.0",
"webpack-bundle-analyzer": "^4.7.0",
"webpack-notifier": "^1.15.0",
"sam-js": "Imrane03/better-sam",
"@types/ffi-napi": "^4.0.7"
"webpack-notifier": "^1.15.0"
},
"iohook": {
"targets": [
Expand Down
1 change: 1 addition & 0 deletions apps/app/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ declare module 'electron-postman'
declare module '@ryanmorr/ready'
declare module 'sam-js'
declare module 'node-record-lpcm16'
declare module '@globalhive/vuejs-tour'

declare module 'socket.io/*'
declare module '@packages/electron-pinia/*'
Expand Down
1 change: 1 addition & 0 deletions apps/app/src/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { watchHitbox } from '@/modules/vue-hitboxes'
watchHitbox('.el-select-dropdown')
watchHitbox('.tippy-box')
watchHitbox('.autocomplete')
watchHitbox('#vjt-tooltip')

function requireAll(r: __WebpackModuleApi.RequireContext) {
r.keys().forEach(r)
Expand Down
4 changes: 2 additions & 2 deletions apps/app/src/teams/messenger/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<ThemeProvider :theme="tokens">
<NvBackground />
<NvBackground/>
<div class="h-0">
<div id="router-overlay"></div>
<NvMessenger
Expand All @@ -10,7 +10,7 @@
class="w-full h-full"
/>
</div>
<NvDebug v-if="settingsStore.debugMode" />
<NvDebug v-if="settingsStore.debugMode"/>
</ThemeProvider>
</template>
<style lang="scss">
Expand Down
4 changes: 4 additions & 0 deletions apps/app/src/teams/messenger/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import App from '@/teams/messenger/App.vue'
import router from '@/teams/messenger/router'
import { pinia } from '@/store'
import { NvLoading } from '@packages/ui'
import VueJsTour from '@globalhive/vuejs-tour'
import '@globalhive/vuejs-tour/dist/style.css'
import './styles'

const vueQueryPluginOptions: VueQueryPluginOptions = {
queryClientConfig: {
Expand All @@ -21,5 +24,6 @@ const app = createApp(App)
.use(pinia)
.use(VueQueryPlugin, vueQueryPluginOptions)
.use(NvLoading)
.use(VueJsTour)

app.mount('#app')
1 change: 1 addition & 0 deletions apps/app/src/teams/messenger/components/NvMessenger.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<div
ref="messenger"
class="messenger bg-gray-10/95 rounded grid p-4 gap-4 grid-rows-3 grid-rows-none min-w-[768px]"
data-v-step="14"
>
<!-- Top -->
<NvGroup :spacing="4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
? 'plain'
: 'default'
"
data-v-step="7"
icon-name="users-alt"
size="sm"
@click="messengerContext.navigateTo({ name: 'settings-engine' })"
Expand All @@ -23,6 +24,7 @@
<SpeechEngineSelect
:modelValue="speechStore.selectedSpeechEngine"
class="w-13"
data-v-step="3"
icon-name="direction"
placeholder="Speech Engine"
size="sm"
Expand All @@ -38,6 +40,7 @@
:is="speechStore.currentSpeechEngine.voiceSelectComponent"
v-if="speechStore.currentSpeechEngine.voiceSelectComponent"
class="w-13"
data-v-step="4"
placeholder="Speech Voice"
size="sm"
/>
Expand Down Expand Up @@ -70,7 +73,7 @@
<NvTooltip>
<NvText>Audio outputs</NvText>
<template #reference>
<NvButton icon-name="direction" size="sm"
<NvButton data-v-step="5" icon-name="direction" size="sm"
>Outputs ({{
settingsStore.audioOutputs.length +
(settingsStore.playSpeechOnDefaultPlaybackDevice ? 1 : 0)
Expand Down Expand Up @@ -115,7 +118,7 @@
<NvTooltip>
<NvText>Audio input</NvText>
<template #reference>
<NvButton icon-name="direction" size="sm">Input</NvButton>
<NvButton data-v-step="6" icon-name="direction" size="sm">Input</NvButton>
</template>
</NvTooltip>
</template>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<NvCard class="h-7" size="xs">
<NvCard class="h-7" data-v-step="13" size="xs">
<NvGroup :spacing="2" noWrap>
<template v-if="settingsStore.debugMode">
<NvTooltip>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
:placeholder="placeholder"
:voice="speechStore.currentSpeechEngine?.getSelectedVoice()"
class="w-full"
data-v-step="1"
size="lg"
@blur="onInputBlur"
@enter="onInputEnter"
@esc="onInputEsc"
@focus="onInputFocus"
@space="(e) => settingsStore.messageMode === 'word' && [playMessage(), e.preventDefault()]"
/>
<NvButton icon-name="message" size="lg" @click="playMessage()" />
<NvButton data-v-step="2" icon-name="message" size="lg" @click="playMessage()"/>
</NvGroup>
</NvCard>
</template>
Expand Down Expand Up @@ -43,7 +44,7 @@ const onInputEsc = () => {

const placeholder = computed(() => {
if (speechStore.commands.length > 0) {
return `Type / to see available commands (${speechStore.commands.length})`
return `Type / to see available commands (${ speechStore.commands.length })`
}
return 'So, said the angel to the child who, divided, broke the knife..'
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<NvTooltip>
<NvText>Message mode</NvText>
<template #reference>
<NvGroup noWrap>
<NvGroup data-v-step="8" noWrap>
<NvButton
:type="settingsStore.messageMode === 'sentence' && 'plain'"
size="sm"
Expand All @@ -26,6 +26,7 @@
<template #reference>
<NvButton
:type="route.name === 'messages-shortcuts' && messengerContext.isViewShown.value ? 'plain' : 'default'"
data-v-step="9"
icon-name="keyboard-alt"
size="sm"
@click="messengerContext.navigateTo({ name: 'messages-shortcuts' })"
Expand All @@ -37,6 +38,7 @@
<template #reference>
<NvButton
:type="route.name === 'messages-history' && messengerContext.isViewShown.value ? 'plain' : 'default'"
data-v-step="10"
icon-name="history"
size="sm"
@click="messengerContext.navigateTo({ name: 'messages-history' })"
Expand Down
118 changes: 116 additions & 2 deletions apps/app/src/teams/messenger/components/NvMessengerNavigationBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<NvTooltip>
<NvText>Guided tour</NvText>
<template #reference>
<NvButton icon-name="question-circle" size="sm"/>
<NvButton icon-name="question-circle" size="sm" @click="startTour"/>
</template>
</NvTooltip>
<NvTooltip>
Expand All @@ -16,6 +16,7 @@
? 'plain'
: 'default'
"
data-v-step="11"
icon-name="comment-alt-lines"
size="sm"
@click="messengerContext.navigateTo({ name: 'messages-history' })"
Expand All @@ -31,6 +32,7 @@
? 'plain'
: 'default'
"
data-v-step="12"
icon-name="setting"
size="sm"
@click="messengerContext.navigateTo({ name: 'settings-general' })"
Expand All @@ -49,17 +51,129 @@
</NvTooltip>
</NvGroup>
</NvCard>
<VTour ref="tour" :steps="steps">
<template #content="{step}">
<NvText :style="{
color: 'white'
}">{{ steps[step.currentStep].content }}
</NvText>
</template>
<template #actions="scope">
<NvGroup :key="step" justify="apart">
<span></span>
<NvGroup>
<NvButton :type="step !== steps.length - 1 ? 'plain' : 'default'" size="sm"
@click.prevent="() => {
step = 0
scope.endTour()
}">Close
</NvButton>
<NvButton v-if="step > 0 && step !== steps.length - 1" size="sm" @click.prevent="() => {
step -= 1
scope.prevStep()
}">Previous
</NvButton>
<NvButton v-if="step !== steps.length - 1" size="sm" @click.prevent="() => {
step += 1
scope.nextStep()
}">Next
</NvButton>
</NvGroup>
</NvGroup>
</template>
</VTour>
</template>
<script lang="ts" setup>
import { NvButton, NvCard, NvGroup, NvText, NvTooltip } from '@packages/ui'
import { inject } from 'vue'
import { inject, ref } from 'vue'
import { useRoute } from 'vue-router'
import { useSettingsStore } from '@/features/settings/store'

const settingsStore = useSettingsStore()
const messengerContext = inject('messenger')
const { ElectronMessengerWindow } = window
const route = useRoute()

const hide = () => {
ElectronMessengerWindow.hide()
}
const tour = ref(null)
const step = ref(0)
const startTour = () => {
step.value = 0
tour.value.resetTour()
tour.value.startTour()
}
const steps = [
{
target: '[data-v-step="1"]',
content: 'You can input any message you want Izabela to speak here.',
placement: 'top',
},
{
target: '[data-v-step="2"]',
content: 'You can send the message by pressing [Enter] inside the text input or by clicking on the [Send] button here.',
placement: 'top',
},
{
target: '[data-v-step="3"]',
content: 'You can select a different speech engine here. Each speech engines come with a unique set of voices so it is recommended to explore them based on your preferences!',
placement: 'top',
},
{
target: '[data-v-step="4"]',
content: 'You can select a different voice supported by the selected speech engine here.',
placement: 'top',
},
{
target: '[data-v-step="5"]',
content: 'You can select different audio outputs here. By default, Izabela will always speak on your default playback device. If you want to use Izabela as an audio input, select your preferred virtual audio cable here.',
placement: 'top',
},
{
target: '[data-v-step="6"]',
content: 'If you want to use Speech Recognition (speech-to-text-to-speech), you can select an audio input here.',
placement: 'top',
},
{
target: '[data-v-step="7"]',
content: 'You can access more advanced parameters for each speech engines in the speech settings here.',
placement: 'top',
},
{
target: '[data-v-step="8"]',
content: 'You can select a different speaking strategy here. Sentence mode will send a message after every [Enter] key press. Word mode will send a message after every [Enter] or [Space] key press.',
placement: 'top',
},
{
target: '[data-v-step="9"]',
content: 'You can bind messages to keyboard shortcuts here.',
placement: 'top',
},
{
target: '[data-v-step="10"]',
content: 'You can see a list of your latest messages here. You can replay them or download them locally.',
placement: 'top',
},
{
target: '[data-v-step="11"]',
content: 'You can access all message related pages here.',
placement: 'top',
},
{
target: '[data-v-step="12"]',
content: 'You can access the settings here.',
placement: 'top',
},
{
target: '[data-v-step="13"]',
content: `You can move the window by dragging the bar here.`,
placement: 'top',
},
{
target: '[data-v-step="14"]',
content: `Finally, you can toggle the window by pressing ${ settingsStore.keybindings.toggleMessengerWindow.map((k) => `[${ k.key }]`).join(' + ') }. If the text input is focused, you can also press [Esc] to close the window.`,
placement: 'top',
},
]
</script>
35 changes: 35 additions & 0 deletions apps/app/src/teams/messenger/styles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { injectGlobal } from 'vue3-styled-components'

import { tokens } from '@packages/ui'
import { rem } from 'polished'

const { colors, borderRadius, spacing } = tokens

// eslint-disable-next-line no-unused-expressions
injectGlobal`
#vjt-tooltip {
background-color: ${colors.black} !important;
color: inherit !important;
border-radius: ${rem(borderRadius.md)} !important;
font-size: inherit !important;
padding: ${rem(spacing['5'])} !important;
display: flex;
flex-direction: column;
gap: ${rem(spacing['5'])};

&[data-hidden] {
display: none !important;
}
}

#vjt-arrow {
&::before {
background-color: ${colors.black} !important;
}
}

.vjt-highlight {
outline: ${rem(2)} solid ${colors.black} !important;
border-radius: inherit !important;
}
`
Loading