From: Enrique Hernandez Date: Mon, 8 Mar 2021 00:41:22 +0000 (-0600) Subject: inputItem v1 X-Git-Tag: v0.9~51 X-Git-Url: https://andrewgundersen.net/repos?a=commitdiff_plain;h=f2a240d80386d447a240e5b90ca403aa6ff2bb8c;p=mime-chat inputItem v1 --- diff --git a/src/components/inputItem.vue b/src/components/inputItem.vue deleted file mode 100644 index 5e32f98..0000000 --- a/src/components/inputItem.vue +++ /dev/null @@ -1,166 +0,0 @@ - - - - - diff --git a/src/components/taInput/inputController.ts b/src/components/inputItem/inputController.ts similarity index 53% rename from src/components/taInput/inputController.ts rename to src/components/inputItem/inputController.ts index e1d1ce9..6fb5e8c 100644 --- a/src/components/taInput/inputController.ts +++ b/src/components/inputItem/inputController.ts @@ -7,18 +7,12 @@ import { ref, watch, onUnmounted, onMounted } from "vue"; import useKeyDownHandler from "@/modules/keyDownHandler/useKeyDownHandler"; -import useMediaStream from "@/modules/mediaStream"; -import useAudioVisualizer from './audioDetails/audioVisualizer'; -import useTextVisualizer from './textDetails/textVisualizer'; import useMitt from "@/modules/mitt"; import { useIpc } from '@/modules/ipc'; -let stream: MediaStream; - export default function useInputController() { - const visualizeStream = ref(false); - const paths = ref([]); - const audioBubbleWidth = ref(10); + const isRecording = ref(false); + const isTyping = ref(false); const { emitter } = useMitt(); const { post } = useIpc(); @@ -37,40 +31,19 @@ export default function useInputController() { if (input) post('message', message); } - function recordStream(record: boolean) { - // tell ipcMain to pause or resume stream recording. - post('update-recorder', record); - // toggle inputItem audio animation. - emitter.emit('input-audio-record', record); - } - - const { - visualizeStreamAsPaths, - expandBubble - } = useAudioVisualizer(visualizeStream); - const { keyDownHandler, input } = useKeyDownHandler(enterCallback); - const { - textInputXoffset, - textInputYoffset, - renderTextInput - } = useTextVisualizer(input); - // stops stream recording on space key up function keyupHandler(e: any) { - if (e.key === " " && visualizeStream.value) { + if (e.key === " " && isRecording.value) { - recordStream(false) - visualizeStream.value = false; - paths.value = [] - audioBubbleWidth.value = 10; + isRecording.value = false; + post('update-recorder', isRecording.value); input.value = '' } } onMounted(async () => { - stream = await useMediaStream({ audio: true }); // add window event keyboard listeners window.addEventListener("keydown", keyDownHandler); window.addEventListener('keyup', keyupHandler); @@ -84,27 +57,24 @@ export default function useInputController() { // determine whether to render text or audio based one the keyboard input watch(input, (input, prevInput) => { if (prevInput !== "" || prevInput.length > 0) { - if (!visualizeStream.value) { - renderTextInput(); + if (!isRecording.value) { + isTyping.value = true; } return; } - if (input === " " && visualizeStream.value === false) { - visualizeStream.value = true; - recordStream(true) - expandBubble(audioBubbleWidth); - visualizeStreamAsPaths(stream, paths, audioBubbleWidth); + if (input === " " && isRecording.value === false) { + // isTyping.value = false; + isRecording.value = true; + post('update-recorder', isRecording.value); return; } - renderTextInput(); + isTyping.value = true; }); - return { input, - visualizeStream, - audioBubbleWidth, - paths + isRecording, + isTyping } } diff --git a/src/components/inputItem/inputItem.vue b/src/components/inputItem/inputItem.vue new file mode 100644 index 0000000..32019ac --- /dev/null +++ b/src/components/inputItem/inputItem.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/src/components/messageView/index.vue b/src/components/messageView/index.vue deleted file mode 100644 index e231033..0000000 --- a/src/components/messageView/index.vue +++ /dev/null @@ -1,111 +0,0 @@ - - - - - diff --git a/src/components/taInput/audioDetails/audio.vue b/src/components/taInput/audioDetails/audio.vue deleted file mode 100644 index 896a896..0000000 --- a/src/components/taInput/audioDetails/audio.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/src/components/taInput/audioDetails/audioVisualizer.ts b/src/components/taInput/audioDetails/audioVisualizer.ts deleted file mode 100644 index 20f2318..0000000 --- a/src/components/taInput/audioDetails/audioVisualizer.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { Ref } from '@/types/vueRef/index'; -import AnimeFunc from "@/types/animejs/index"; -import { inject, ref } from "vue"; - -interface AudioPath { - identifier: string; - d: string; - offset: number; - color: string; - draw: boolean; -} -export default function useAudioVisualizer(draw: Ref) { - const audioContext = new AudioContext(); - const analyzer = audioContext.createAnalyser(); - analyzer.fftSize = 128; - const bufferLength = analyzer.frequencyBinCount; - const dataArray = new Uint8Array(bufferLength); - - // imports animejs safely - let anime: AnimeFunc; - const animeInject: AnimeFunc | undefined = inject("animejs"); - if (animeInject) anime = animeInject; - - /* - * Draws MediaStream audioTrack as 'AudioPath' objects - */ - function drawStream(paths: Ref, bubbleWidth: Ref): void { - const xInitial = ref(10); - const maxAmplitude = 15; - const maxBubbleWidth = 300; - - function shiftPathStream(pathList: NodeList): void { - for (let i = 0; i < pathList.length; i++) { - const stick = pathList[i] as HTMLElement; - const computedQuery = window.getComputedStyle(stick); - const matrix = new WebKitCSSMatrix(computedQuery.webkitTransform); - anime({ - targets: stick, - translateX: [matrix.m41, matrix.m41 - 6], - }) - } - } - function filterPathList(pathList: NodeList) { - for (let i = 0; i < pathList.length; i++) { - const stick = pathList[i] as HTMLElement; - const computedQuery = window.getComputedStyle(stick); - const matrix = new WebKitCSSMatrix(computedQuery.webkitTransform); - if (matrix.m41 < 10) { - anime({ - targets: stick, - opacity: 0, - duration: 0 - }) - } - } - - } - - function drawNewPath(): void { - - const calculateAmplitude = (): number => ( - Math.min(Math.max( - (dataArray.reduce((a, b) => a + b) / bufferLength) * 0.45, - 0), maxAmplitude) - ) - - const createAudioPath = (a: number, o: number): AudioPath => ({ - identifier: `path_${o}`, - d: `M0,25v${-a}`, - offset: o, - color: '#000', - draw: true - }) - - const amplitude = calculateAmplitude(); - const p: AudioPath = createAudioPath(amplitude, xInitial.value); - paths.value.push(p); - } - - paths.value = []; - function drawPathStream(): void { - - let streamPath; - if (!draw.value) { - window.clearTimeout(streamPath) - return; - } - setTimeout(() => { - requestAnimationFrame(drawPathStream); - analyzer.getByteFrequencyData(dataArray); - }, 1000 / 10) - - /* - * To Draw pathStream - */ - if (bubbleWidth.value === 300) { - xInitial.value = bubbleWidth.value - 10; - } else if (bubbleWidth.value > 20) { - xInitial.value = bubbleWidth.value; - } else { - xInitial.value += 3; - } - streamPath = setTimeout(async () => { - const pathList = document.querySelectorAll('path'); - filterPathList(pathList); - drawNewPath(); - if (bubbleWidth.value === maxBubbleWidth) { - shiftPathStream(pathList); - } - }, 200) - } - drawPathStream(); - } - - function increaseBubbleWidth(bubbleRef: Ref) { - const increase = () => { - - let animation; - if (!draw.value) { - if (animation) { - cancelAnimationFrame(animation) - } - return; - } - animation = requestAnimationFrame(increase); - if (bubbleRef.value < 300) { - bubbleRef.value++; - } - } - increase(); - } - - function expandBubble(bubbleWidth: Ref) { - increaseBubbleWidth(bubbleWidth); - } - - function visualizeStreamAsPaths(s: MediaStream, paths: Ref, bubbleWidth: Ref): void { - const source = audioContext.createMediaStreamSource(s); - source.connect(analyzer); - drawStream(paths, bubbleWidth); - } - - return { - visualizeStreamAsPaths, - expandBubble - } -} diff --git a/src/components/taInput/index.vue b/src/components/taInput/index.vue deleted file mode 100644 index 68b5c65..0000000 --- a/src/components/taInput/index.vue +++ /dev/null @@ -1,54 +0,0 @@ - - - diff --git a/src/components/taInput/textDetails/text.vue b/src/components/taInput/textDetails/text.vue deleted file mode 100644 index fa215fe..0000000 --- a/src/components/taInput/textDetails/text.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - - - diff --git a/src/components/taInput/textDetails/textAnime.ts b/src/components/taInput/textDetails/textAnime.ts deleted file mode 100644 index 8f5eafa..0000000 --- a/src/components/taInput/textDetails/textAnime.ts +++ /dev/null @@ -1,57 +0,0 @@ -import AnimeFunc from "@/types/animejs/index"; -import { inject } from "vue"; -import { Ref } from "@/types/vueRef/index"; -/* - * Anime js animations used by input textController -*/ -export default function useTextInputAnims() { - - // imports animejs safely - let anime: AnimeFunc; - const animeInject: AnimeFunc | undefined = inject("animejs"); - if (animeInject) anime = animeInject; - - const animateSend = (el: HTMLElement, elHeight: number, input: Ref) => { - anime({ - targets: el, - translateY: -elHeight + 15, - duration: 200, - easing: "easeInQuad", - complete: function() { - anime({ - targets: el, - translateY: 50, - duration: 200, - easing: "easeOutQuad", - complete: function() { - input.value = ""; - } - }) - } - }) - } - - const inputAppear = (el: HTMLElement) => { - anime({ - targets: el, - translateY: -10, - duration: 0 - }); - } - - const verticalShiftInput = (el: HTMLElement, yTrans: number) => { - anime({ - targets: el, - translateY: yTrans, - easing: "easeOutQuad", - duration: 150, - }); - } - - return { - animateSend, - verticalShiftInput, - inputAppear - } - -} diff --git a/src/components/taInput/textDetails/textVisualizer.ts b/src/components/taInput/textDetails/textVisualizer.ts deleted file mode 100644 index c0c919b..0000000 --- a/src/components/taInput/textDetails/textVisualizer.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * text rendering logic used by inputController -*/ - -import { ref, computed, onMounted, onUnmounted } from 'vue'; -import useTextInputAnims from "./textAnime"; -import { Ref } from "@/types/vueRef/index"; -import useMitt from "@/modules/mitt"; - -export default function useTextVisualizer(input: Ref) { - const inputHeight = ref(42); - const inputWidth = ref(0); - const { emitter } = useMitt(); - const { animateSend, verticalShiftInput, inputAppear } = useTextInputAnims(); - - async function renderTextInput() { - // first, get input dimensions - const inputDivs = await document.getElementsByClassName("inputBubble"); - const height = inputDivs[0].getBoundingClientRect().height; - inputWidth.value = inputDivs[0].getBoundingClientRect().width; - // then, query for foreignObject div - const foreignObjectDiv = document.getElementsByClassName( - "inputContainer" - ); - const foreignEl = foreignObjectDiv[0] as HTMLElement; - if (height !== inputHeight.value) { - inputHeight.value = height; - } - if (inputHeight.value === 0) { - inputAppear(foreignEl) - } else if (inputHeight.value > 36) { - const yTrans = -inputHeight.value + 30; - verticalShiftInput(foreignEl, yTrans); - } - } - - onMounted(() => { - emitter.on("animate-send", () => { - const inputEl = document.getElementsByClassName("inputContainer"); - const foreignEl = inputEl[0] as HTMLElement; - animateSend(foreignEl, inputHeight.value, input); - }); - }); - - onUnmounted(() => { - emitter.all.clear(); - }); - - const textInputXoffset = computed(() => { - return `calc(50% - ${inputWidth.value / 2})`; - }); - - const textInputYoffset = computed(() => { - return `calc(97% - ${inputHeight.value})`; - }); - - return { - textInputXoffset, - textInputYoffset, - renderTextInput - } -} diff --git a/src/components/textBubble/bubbleDetails/drawer.ts b/src/components/textBubble/bubbleDetails/drawer.ts deleted file mode 100644 index 8343fb6..0000000 --- a/src/components/textBubble/bubbleDetails/drawer.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { ref, onMounted } from "vue"; -import { Ref } from "@/types/vueRef/index"; - -/** - * handles visualization of individual svg text bubbles - */ -export default function useBubbleDrawer({ - mr, - tr, -}: { - mr: Ref; - tr: Ref; -}) { - const signatureTranslate = ref(""); - let messageRect: SVGSVGElement & SVGRectElement; - let messageText: SVGSVGElement & SVGTextElement; - - onMounted(async () => { - messageRect = (mr.value as unknown) as SVGSVGElement & SVGRectElement; - messageText = (tr.value as unknown) as SVGSVGElement & SVGTextElement; - }); - - function adjustMessageRect(): void { - // must get dimensions of text box to fit bubble around - const padding = 12.5; - const textBox = messageText.getBBox(); - messageRect.setAttribute("x", String(textBox.x - padding)); - messageRect.setAttribute("y", String(textBox.y - padding)); - messageRect.setAttribute("width", String(textBox.width + 2 * padding)); - messageRect.setAttribute("height", String(textBox.height + 2 * padding)); - } - - function translateMsgSignature(): void { - if (messageRect.getAttribute("height") !== null) { - const height = Number(messageRect.getAttribute("height")); - signatureTranslate.value = `translate(-10 ${height})`; - } - } - - async function drawMessage() { - // ignore lint error: await needed for proper render - await adjustMessageRect(); - translateMsgSignature(); - } - - return { - drawMessage, - signatureTranslate, - }; -} diff --git a/src/modules/keyDownHandler/useKeyDownHandler.ts b/src/modules/keyDownHandler/useKeyDownHandler.ts index 21dd591..65c4f2e 100644 --- a/src/modules/keyDownHandler/useKeyDownHandler.ts +++ b/src/modules/keyDownHandler/useKeyDownHandler.ts @@ -1,10 +1,10 @@ -import { ref } from "vue"; +import { ref, onMounted } from "vue"; import keyboardNameMap from "./keyBoardMaps/keyboardNameMap"; import keyboardCharMap from "./keyBoardMaps/keyboardCharMap"; interface KeyDownEvent { - keyCode: number; - shiftKey: boolean; + keyCode: number; + shiftKey: boolean; } // This catches keys from a physical keyboard, a soft keyboard on a tablet, or a @@ -13,6 +13,12 @@ export default function useKeyDownHandler(enterCallback?: (input: string) => voi const input = ref(""); + let textInput: HTMLInputElement | null; + + onMounted(() => { + textInput = document.getElementById('textInput') as HTMLInputElement; + }) + function keyDownHandler(e: KeyDownEvent) { // keyboardCharMap is an array of arrays, with each inner // array having 2 columns - un-shifted, and shifted values. @@ -20,6 +26,8 @@ export default function useKeyDownHandler(enterCallback?: (input: string) => voi // See the "keyboardCharMap", below, for printable characters. // MODIFY keyboardCharMap to suit your needs if you want // more/less/different characters to be considered "printable". + if (textInput) textInput.focus() + let iCol = 0; if (e.shiftKey) { iCol = 1; @@ -32,11 +40,14 @@ export default function useKeyDownHandler(enterCallback?: (input: string) => voi switch (cmd) { case "ENTER": if (enterCallback) enterCallback(input.value); + if (textInput) textInput.value = '' + input.value = " "; break; case "BACK_SPACE": input.value = input.value.slice(0, -1); break; case "ESCAPE": + if (textInput) textInput.value = '' input.value = ""; break; default: diff --git a/src/modules/mediaStream.ts b/src/modules/mediaStream.ts deleted file mode 100644 index afc0dc5..0000000 --- a/src/modules/mediaStream.ts +++ /dev/null @@ -1,13 +0,0 @@ -export default async function useMediaStream(constraints: { - audio: boolean; - video?: boolean; -}): Promise { - try { - const stream = await navigator.mediaDevices.getUserMedia(constraints); - return stream; - } catch (e) { - return e; - } - // var audioTack = stream.getAudioTracks()[0]; - // console.log(audioTrack.getSettings()) -} diff --git a/src/modules/queue.ts b/src/modules/queue.ts deleted file mode 100644 index 8b734b9..0000000 --- a/src/modules/queue.ts +++ /dev/null @@ -1,78 +0,0 @@ -export interface DataNode { - data: T; - next: DataNode | null; -} - -export interface QueueI { - enqueue(data: T): void; - dequeue(): T | null; - peek(): T | null; - size(): number; -} - -export class Queue implements QueueI { - private _size: number; - private head: DataNode | null; - private tail: DataNode | null; - constructor() { - this._size = 0; - this.head = this.tail = null; - } - - enqueue(data: T) { - - const node: DataNode = { - data, - next: null - } - if (this.head === null) { - this.head = this.tail = node; - } else { - if (this.tail) { - this.tail.next = node; - this.tail = this.tail.next; - } - - } - ++this._size; - } - - dequeue(): T | null { - - let item: T | null = null; - - if (this._size === 0) { - return null; - } - - if (this.head) { - item = this.head.data; - this.head = this.head.next; - --this._size; - - if (!this._size) { - this.tail = null; - } - } - return item; - } - - peek(): T | null { - - let item: T | null = null; - - if (this._size === 0) { - return null; - } - - if (this.head) { - item = this.head.data; - } - - return item; - } - - size(): number { - return this._size; - } -} diff --git a/src/modules/scrollView.ts b/src/modules/scrollView.ts deleted file mode 100644 index 271d6b9..0000000 --- a/src/modules/scrollView.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { ref, computed, onMounted, onUnmounted } from "vue"; - -/** - * handles visualization of view messages through - * vue transition callbacks and anime-js animations - */ -export default function useScrollView({ targetId }: { targetId: string }) { - - const scroll = ref(0); - let scrollTarget: HTMLElement | SVGElement | null; - const targetHeight = ref(0); - let topBound: number; - const scrollStartHeight = 445; - - const scrollView = computed(() => { - - if (clampedScroll.value === 0) { - scroll.value = 0; - } else if (clampedScroll.value === topBound) { - scroll.value = topBound; - } - - // x, y, width, height - // width and height should be dynamic - return `0 ${clampedScroll.value} 350 500`; - }); - - const clampedScroll = computed(() => { - if (targetHeight.value === 0) { return 0; } - topBound = -targetHeight.value + 450; - return Math.max(topBound, Math.min(scroll.value, 0)) as number; - }) - - const getHeight = () => { - if (scrollTarget) { - return scrollTarget.getBoundingClientRect().height as number; - } - } - - const getWidth = () => { - if (scrollTarget) { - return scrollTarget.getBoundingClientRect().width as number; - } - } - - const updateView = (verticalScroll: number) => { - - if (scrollTarget) { - - const heightResult = getHeight(); - const widthResult = getWidth(); - - console.log(heightResult); - console.log(widthResult); - - if (heightResult) { - // only scroll if renderer scrollStart - if (heightResult > scrollStartHeight) { - targetHeight.value = heightResult; - scroll.value += verticalScroll; - } - } - } - } - - const scrollUpdate = (e: any): void => { - const verticalScroll = e.deltaY * 0.25; - updateView(verticalScroll); - } - - onMounted(() => { - scrollTarget = document.getElementById("targetId"); - if (scrollTarget) { - window.addEventListener("wheel", scrollUpdate); - } - }); - - onUnmounted(() => { - window.removeEventListener("wheel", scrollUpdate); - }) - - return { - scrollView - } - -} diff --git a/src/modules/textWrap.ts b/src/modules/textWrap.ts deleted file mode 100644 index bf795e0..0000000 --- a/src/modules/textWrap.ts +++ /dev/null @@ -1,17 +0,0 @@ -export default function useTextWrap() { - // text wraps a string to a given width - function textWrap({ s, w }: { s: string; w: number }): string[] { - // return tspan elements for text with correct size - const wrap = (s: string, w: number) => - s.replace( - new RegExp(`(?![^\\n]{1,${w}}$)([^\\n]{1,${w}})\\s`, "g"), - "$1\n" - ); - const result = wrap(s, w).split("\n"); - return result; - } - - return { - textWrap - }; -} diff --git a/src/router.ts b/src/router.ts index ee94a61..6f689bf 100644 --- a/src/router.ts +++ b/src/router.ts @@ -35,21 +35,21 @@ const router = createRouter({ }); // route auth check -router.beforeEach((to, from, next) => { - const { accessToken } = useAuth(); - - // Not logged into a guarded route? - if (to.meta.requiresAuth && !accessToken.value) { - next({ name: 'login' }) - } - - // Logged in for an auth route - else if ((to.name == 'login' || to.name == 'register') && accessToken.value){ - next({ name: 'home' }); - } - - // Carry On... - else next(); -}) +// router.beforeEach((to, from, next) => { +// const { accessToken } = useAuth(); +// +// // Not logged into a guarded route? +// if (to.meta.requiresAuth && !accessToken.value) { +// next({ name: 'login' }) +// } +// +// // Logged in for an auth route +// else if ((to.name == 'login' || to.name == 'register') && accessToken.value){ +// next({ name: 'home' }); +// } +// +// // Carry On... +// else next(); +// }) export default router; diff --git a/src/views/messenger.vue b/src/views/messenger.vue index e765719..16e16fe 100644 --- a/src/views/messenger.vue +++ b/src/views/messenger.vue @@ -1,34 +1,27 @@