merging
This commit is contained in:
commit
81662942a2
24 changed files with 506 additions and 402 deletions
|
|
@ -49,11 +49,11 @@ export default function useAudioInputController (typing: Ref) {
|
|||
// Start recording on space bar.
|
||||
if (cmd == "SPACE" && !recording.value && !typing.value) {
|
||||
|
||||
post('start-recording', "");
|
||||
console.log("INPT:Starting record.")
|
||||
post("start-recording", "");
|
||||
|
||||
showRecIcon()
|
||||
recording.value = true;
|
||||
console.log("Recording...")
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +70,8 @@ export default function useAudioInputController (typing: Ref) {
|
|||
emitter.emit("self-message", message);
|
||||
|
||||
// Stop recording and get audio from recorder.
|
||||
const audio = await invoke('stop-recording', "");
|
||||
console.log("INPT:Stopping record.")
|
||||
const audio = await invoke("stop-recording", "");
|
||||
|
||||
// Send message to the backend for processing.
|
||||
const clientM = clientMessage("", audio, message.uid);
|
||||
|
|
@ -78,7 +79,6 @@ export default function useAudioInputController (typing: Ref) {
|
|||
|
||||
hideRecIcon()
|
||||
recording.value = false;
|
||||
console.log("Stopping record...")
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,29 +23,27 @@
|
|||
|
||||
<script lang="ts">
|
||||
|
||||
import { defineComponent, ref, onMounted, onUnmounted } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import draggify from "@/modules/draggify";
|
||||
|
||||
import TextInput from "@/components/inputItem/textInput.vue";
|
||||
import TextInput from "@/components/textInput.vue";
|
||||
|
||||
import useTextInputController from
|
||||
"@/components/inputItem/controllers/textCtrl";
|
||||
"@/components/controllers/textCtrl";
|
||||
import useAudioInputController from
|
||||
"@/components/inputItem/controllers/audioCtrl";
|
||||
"@/components/controllers/audioCtrl";
|
||||
|
||||
export default defineComponent({
|
||||
name: "InputItem",
|
||||
|
||||
props: ["initials"],
|
||||
|
||||
components: {
|
||||
TextInput
|
||||
},
|
||||
|
||||
setup() {
|
||||
|
||||
// Mark input item with user's initials.
|
||||
const initials = ref("")
|
||||
|
||||
// Set initials.
|
||||
const initialData = window.localStorage.getItem("initials")
|
||||
if (initialData) initials.value = initialData
|
||||
|
||||
// Default values for position.
|
||||
const xStart = 15;
|
||||
const yStart = window.innerHeight - 200;
|
||||
|
|
@ -57,25 +55,10 @@ export default defineComponent({
|
|||
const { typing } = useTextInputController(elementX)
|
||||
const { recording } = useAudioInputController(typing)
|
||||
|
||||
// Update profile functionality.
|
||||
const onUpdateProfile = (_event: any, payload: any) => {
|
||||
initials.value = payload.message.first[0] + payload.message.last[0]
|
||||
window.localStorage.setItem("initials", initials.value)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.ipcRenderer.on("update-profile", onUpdateProfile);
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.ipcRenderer.removeAllListeners("update-profile");
|
||||
})
|
||||
|
||||
return {
|
||||
elementX,
|
||||
elementY,
|
||||
recording,
|
||||
initials
|
||||
recording
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
@ -29,16 +29,14 @@
|
|||
</form>
|
||||
|
||||
<!-- back to login button: position: fixed -->
|
||||
<button class="createAccountButton button" @click.prevent="switchView">Create account</button>
|
||||
<!-- <button class="createAccountButton button" @click.prevent="switchView">Create account</button> -->
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { useAuth } from "@/modules/auth";
|
||||
import { useIpc } from "@/modules/ipc";
|
||||
import useMessages from "@/modules/messages";
|
||||
import { authRequest } from '@/modules/message';
|
||||
import { authRequest } from '@/modules/message';
|
||||
|
||||
export default defineComponent({
|
||||
name: "Login",
|
||||
|
|
@ -46,11 +44,9 @@ export default defineComponent({
|
|||
setup() {
|
||||
|
||||
const { post } = useIpc();
|
||||
const { setToken } = useAuth();
|
||||
const { resetMessages } = useMessages();
|
||||
|
||||
let usr = ref("");
|
||||
let pwd = ref("");
|
||||
const usr = ref("");
|
||||
const pwd = ref("");
|
||||
|
||||
// Submit login credentials to the backend.
|
||||
const submitForm = () => {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,14 @@
|
|||
<!-- Three types of messages: self (sf), friend (fr), and crimata (ai) -->
|
||||
<!-- !denoted by the modifier attribute -->
|
||||
|
||||
<!-- Shows when a new session is created with Crimata. -->
|
||||
<div
|
||||
v-if="message.context === 'launch'"
|
||||
class="divider"
|
||||
>
|
||||
<div>new session</div>
|
||||
</div>
|
||||
|
||||
<!-- Includes bubble and context. -->
|
||||
<div
|
||||
:id="`${message.modifier}MessageBox`"
|
||||
|
|
@ -21,6 +29,12 @@
|
|||
:class="`${message.modifier}-${message.isChild}ChildBubble`"
|
||||
:id="`${message.modifier}Bubble`"
|
||||
>
|
||||
|
||||
<!-- Notification dot for new messages. -->
|
||||
<div v-if="notify === true"
|
||||
class="notify"
|
||||
/>
|
||||
|
||||
<!-- Show loader when audio is being transcribed. -->
|
||||
<div
|
||||
v-if="message.content.text === ''"
|
||||
|
|
@ -73,21 +87,60 @@
|
|||
<script lang='ts'>
|
||||
|
||||
import {defineComponent, ref, onMounted} from 'vue';
|
||||
import { RenderMessage } from "@/types/message/index";
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: "MessageItem",
|
||||
|
||||
props: {
|
||||
message: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
props: ["message"],
|
||||
|
||||
setup(props) {
|
||||
|
||||
let addListener = false;
|
||||
|
||||
const notify = ref(false)
|
||||
const isPlaying = ref(false);
|
||||
|
||||
if (!props.message.seen) {
|
||||
|
||||
// newMessages always render with blue dot.
|
||||
if (props.message.newMessage) {
|
||||
console.log("MSG:New message, notifying.")
|
||||
props.message.seen = true;
|
||||
notify.value = true;
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
// Do nothing if window is visible on setup.
|
||||
if (document.visibilityState === "visible") {
|
||||
props.message.seen = true;
|
||||
}
|
||||
|
||||
// We must listen for window visible event.
|
||||
else {
|
||||
console.log("MSG:Unseen, adding listener.")
|
||||
addListener = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Callback for window visibilityState.
|
||||
const onVisibilityChange = (event: any) => {
|
||||
if (document.visibilityState === "visible") {
|
||||
console.log("MSG:Window visible, notifying.")
|
||||
|
||||
props.message.seen = true;
|
||||
notify.value = true; // triggers blue dot anim.
|
||||
|
||||
// Once complete we can remove.
|
||||
document.removeEventListener("visibilitychange", onVisibilityChange)
|
||||
}
|
||||
}
|
||||
|
||||
const onStopPlayback = (e: any) => {
|
||||
window.ipcRenderer.removeAllListeners("stop-playback-anim");
|
||||
isPlaying.value = false
|
||||
|
|
@ -95,6 +148,11 @@
|
|||
|
||||
onMounted(() => {
|
||||
|
||||
// Listen for window focus event.
|
||||
if (addListener) {
|
||||
document.addEventListener("visibilitychange", onVisibilityChange)
|
||||
}
|
||||
|
||||
// Turn on audio playback animation if audio.
|
||||
if (props.message.content.audio === true) {
|
||||
window.ipcRenderer.on("stop-playback-anim", onStopPlayback);
|
||||
|
|
@ -104,6 +162,7 @@
|
|||
})
|
||||
|
||||
return {
|
||||
notify,
|
||||
isPlaying
|
||||
}
|
||||
}
|
||||
|
|
@ -133,6 +192,20 @@
|
|||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
font-family: "SF Compact Display";
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #9B9B9B;
|
||||
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.firstChildMessage {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
|
@ -183,6 +256,8 @@
|
|||
}
|
||||
|
||||
.bubble {
|
||||
position: relative;
|
||||
|
||||
max-width: 66vw;
|
||||
|
||||
display: flex;
|
||||
|
|
@ -244,6 +319,30 @@
|
|||
border-top-left-radius: 9px;
|
||||
}
|
||||
|
||||
.notify {
|
||||
position: absolute;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background-color: #58D9FF;
|
||||
top: -5px;
|
||||
left: -5px;
|
||||
border: 2px solid #EBEBEB;
|
||||
transform: scale(0);
|
||||
|
||||
animation-name: notify-anim;
|
||||
animation-duration: 5s;
|
||||
}
|
||||
|
||||
@keyframes notify-anim {
|
||||
0%, 90% {
|
||||
transform: scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
.context {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -1,51 +1,66 @@
|
|||
<template>
|
||||
<InputItem />
|
||||
<InputItem :initials="profile.initials"/>
|
||||
<Settings />
|
||||
|
||||
<div id="recIcon" />
|
||||
|
||||
<!-- List of message bubbles. -->
|
||||
<div id="messenger">
|
||||
<MessageItem v-for="message in messages" :message="message[1]" :key="message[0]" />
|
||||
<Message
|
||||
v-for="message in messages"
|
||||
:message="message[1]"
|
||||
:key="message[0]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, onUnmounted } from "vue";
|
||||
import MessageItem from "@/components/messageItem.vue";
|
||||
import InputItem from "@/components/inputItem/inputItem.vue";
|
||||
import Message from "@/components/message.vue";
|
||||
import InputItem from "@/components/inputItem.vue";
|
||||
import Settings from "@/components/settings.vue";
|
||||
import useMitt from "@/modules/mitt";
|
||||
import useMessages from '@/modules/messages';
|
||||
import useMessages from "@/modules/messages";
|
||||
|
||||
export default defineComponent({
|
||||
name: "Messenger",
|
||||
|
||||
props: ["profile", "newMessages"],
|
||||
|
||||
components: {
|
||||
MessageItem,
|
||||
Message,
|
||||
InputItem,
|
||||
Settings
|
||||
},
|
||||
setup() {
|
||||
|
||||
setup(props) {
|
||||
|
||||
// Listen for self-messages from inputItem.
|
||||
const { emitter } = useMitt();
|
||||
|
||||
// Handle messages in view.
|
||||
const { messages, updateMessageView } = useMessages();
|
||||
|
||||
// Update message view on new content.
|
||||
const onNewContent = (_event: any, payload: any) => {
|
||||
updateMessageView(payload.message)
|
||||
}
|
||||
const { messages, prepMessageView, updateMessageView } = useMessages();
|
||||
|
||||
onMounted(() => {
|
||||
const crimataId = props.profile.crimataId;
|
||||
console.log(`MSGR:Initializing messenger for ${crimataId}.`)
|
||||
|
||||
// Front end listener.
|
||||
// Load the message history.
|
||||
if (crimataId === window.localStorage.getItem("last_usr")) {
|
||||
prepMessageView(props.newMessages)
|
||||
} else {
|
||||
messages.value.clear()
|
||||
}
|
||||
|
||||
// New content listeners.
|
||||
emitter.on('self-message', (message) => updateMessageView(message));
|
||||
window.ipcRenderer.on("render-message", (_e: any, payload: any) => {
|
||||
updateMessageView(payload.message)
|
||||
});
|
||||
|
||||
// Back end listener.
|
||||
window.ipcRenderer.on("render-message", onNewContent);
|
||||
// Save the usr for next time.
|
||||
window.localStorage.setItem("last_usr", crimataId)
|
||||
|
||||
});
|
||||
|
||||
|
|
@ -58,11 +73,14 @@ export default defineComponent({
|
|||
return {
|
||||
messages
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
#messenger {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
<script lang="ts">
|
||||
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { useAuth } from "@/modules/auth";
|
||||
import { useIpc } from "@/modules/ipc";
|
||||
import { logoutRequest } from '@/modules/message';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue