updating login

This commit is contained in:
Andrew Gundersen 2021-03-25 15:13:15 -05:00
commit bb9769e917
22 changed files with 316 additions and 362 deletions

View file

@ -18,8 +18,6 @@ const audioContainer = {
input: '',
}
const encoding = "hex";
const audioOptions = {
channelCount: 1,
sampleFormat: 16,
@ -28,21 +26,73 @@ const audioOptions = {
closeOnError: false,
}
// callback run on space bar key up and down.
const updateRecorder = (_event, payload: { isRecording: boolean; uid: string | null;
}): void => {
record = payload.isRecording;
if (!record) {
if (payload.uid) sendAudio(audioContainer.input, payload.uid);
}
// Returns recorded audio to frontend and sets record to false.
const onRecordingEnd = async (_event: any, payload: any) => {
return new Promise((resolve, reject) => {
try {
resolve(audioContainer.input);
record = false;
} catch (e) {
reject()
}
});
};
// listen for space key up/down event.
ipcMain.removeAllListeners('update-recorder');
ipcMain.on('update-recorder', updateRecorder);
// Main audio function run by run.ts module.
export function initAudioIO(): void {
console.log("AUDIO:Starting io streams.")
if (!ai) {
// Initialize and start input stream.
ai = new portAudio.AudioIO({ inOptions: audioOptions });
ai.setEncoding("hex");
ai.start();
// On each data chunk...
ai.on('data', (chunk: string) => {
// If recording, we capture the data.
if (record) {
console.log('Recording...')
audioContainer.input += chunk;
}
// Else, we don't capture and also clear audioContainer.
else {
if (audioContainer.input.length) {
audioContainer.input = "";
}
}
});
}
if (!ao) {
// Initialize and start input stream.
ao = new portAudio.AudioIO({ outOptions: audioOptions });
ao.start();
}
// Listen to record.
console.log("AUDIO:Adding recording listeners.")
ipcMain.removeAllListeners('start-recording');
ipcMain.on('start-recording', () => record = true);
ipcMain.removeHandler('stop-recording');
ipcMain.handle('stop-recording', onRecordingEnd);
}
// ---Audio playback--------------------------------------------
// Split Buffer into an array of len-sized Buffers.
function bufSplit(buf: Buffer, len: number): Array<Buffer> {
@ -59,32 +109,6 @@ function bufSplit(buf: Buffer, len: number): Array<Buffer> {
return chunks;
}
// Main audio function run by run.ts module.
export function initAudioIO(): void {
if (!ai) {
ai = new portAudio.AudioIO({ inOptions: audioOptions });
// base64 encoding needed for google speech to text.
ai.setEncoding(encoding);
ai.start();
ai.on('data', (chunk: string) => {
if (record) {
console.log('recording...')
audioContainer.input += chunk;
} else {
if (audioContainer.input.length) audioContainer.input = "";
}
});
}
if (!ao) {
ao = new portAudio.AudioIO({ outOptions: audioOptions });
ao.start();
}
}
// Audio playback.
export function play(input: Buffer): void {
let i = 0;
@ -128,8 +152,11 @@ export function play(input: Buffer): void {
}
}
// -------------------------------------------------------------
// Get's called on window close.
export function stopStream() {
console.log("AUDIO:Stopping audio stream.")
if(ai != null) {
ai.quit();
ai = null;
@ -140,3 +167,32 @@ export function stopStream() {
}
}
// // Returns recorded audio to frontend.
// const getAudio = async (_event: any, payload: any) => {
// return new Promise((resolve, reject) => {
// // Handle auth response from server.
// backgroundMitt.once('auth-res', (res: string) => {
// if (res == "locked") {
// reject(res);
// } else {
// console.log('Success!');
// auth = true;
// resolve(res);
// }
// });
// if (typeof payload !== "string") {
// payload = JSON.stringify(payload)
// }
// // Send token to backend
// socket.send(payload);
// });
// };

View file

@ -1,6 +0,0 @@
/* eslint-disable */
const EventEmitter = require('events');
class BackgroundMitt extends EventEmitter { }
export const backgroundMitt = new BackgroundMitt();

View file

@ -2,34 +2,59 @@
"use strict";
import { app } from "electron";
import { main } from './run';
import { backgroundMitt } from './emitter';
import { stopStream } from './audio';
import { createWindow } from './window';
import { initSession } from './session';
import { initAudioIO, stopStream } from './audio';
import { backgroundMitt } from '@/modules/emitter';
let winActive: boolean;
let win: boolean;
// Listen for window creation.
backgroundMitt.on('window-active', (state: boolean) => {
winActive = state;
win = state;
});
// Run when electron app is initialized.
async function main() {
console.log("MAIN:Initializing Electron App.")
// Must wait til window is created.
await createWindow();
// Instantiate socket session with crimata-platorm.
initSession();
// Begin audio stream.
initAudioIO();
}
// Root function of app.
export function initApp(dev: boolean): void {
// On initial startup.
app.on("ready", () => {
main();
main()
});
// Quit when all windows are closed.
// Quit app on window closed.
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
stopStream();
app.quit();
}
console.log("MAIN:Quitting app.")
app.quit()
});
// Shutdown audio streams peacefully.
app.on("before-quit", () => {
stopStream()
});
// When user clicks app icon (re-open)
app.on("activate", () => {
if (winActive === false) {
main();
if (!win) {
createWindow();
}
});
// Exit cleanly on request from parent process in development mode.

View file

@ -1,23 +0,0 @@
"use strict";
import { createWindow } from './window';
import agentInterface from './session';
import { initAudioIO } from './audio';
/*
* The main function will be run after electron app is ready.
*/
export async function main() {
const { initSession } = agentInterface()
// create main window.
await createWindow();
// Instantiate socket session with crimata-platorm.
initSession();
// Begin audio stream.
initAudioIO();
}

View file

@ -1,3 +1,12 @@
/*
* Creates a websocket session with Crimata Servers.
*
* Connects to Servers and attempts token authentication. Will send the result
* of the authentication to the window. It will then serve as a communication
* interface between the window and the servers. It will automatically try to
* reconnect on websocket disconnect.
*/
import { backgroundMitt } from './emitter';
import { ipcMain, IpcMainEvent } from "electron";
@ -5,13 +14,18 @@ import useWebSockets from "@/modules/ws";
import { handleAuthMessage, handleStandardMessage, handleProfileMessage, handleAnnotation } from "./handlers";
// Key for key-based auth.
let key: string;
// Calls appropriate endpoint for a server message.
const onServerMessage = (data: string): void => {
const onMessage = (data: string) => {
const message = JSON.parse(data)
if (message.key) {
backgroundMitt.emit('auth-response', message);
if (message.hasOwnProperty("key")) {
handleAuthMessage(message)
}
else if (message.content) {
@ -28,27 +42,43 @@ const onServerMessage = (data: string): void => {
};
const { createSocket, sendMessage } = useWebSockets(onServerMessage);
// Handle messages from client.
const onClientMessage = (_event: IpcMainEvent, payload: any) {
sendMessage(JSON.stringify(payload))
// Attempt token authentication onOpen.
const onOpen = () => {
if (key) {
sendMessage({
"key": key,
"usr": false,
"pwd": false
})
}
}
// Routes messages to and from Crimata Servers.
export default function agentInterface() {
const initSession = () => {
const { createSocket, sendMessage } = useWebSockets(onMessage, onOpen);
ipcMain.removeAllListeners()
// Handle messages from window/client.
const onMessageFromWindow = (_event: IpcMainEvent, payload: any) => {
console.log("New client message")
ipcMain.on("client-message", onClientMessage);
const success = sendMessage(payload)
createSocket()
if (!success) {
console.log("Unable to send message: ", payload)
}
}
return {
initSession
}
// Call this to initialize session with Crimata servers.
export const initSession = (key: string) => {
// Set the key.
key = key;
// Open socket connection.
createSocket()
// Attach listeners for frontend.
ipcMain.removeAllListeners("client-message")
ipcMain.on("client-message", onMessageFromWindow);
}

View file

@ -16,7 +16,6 @@ let win: BrowserWindow | null;
// Called when a NavBar button is pressed.
const onNavBar = (_event: any, action: string): void => {
console.log("onNavBar")
if (win) {
if (action === "close") {
win.close()
@ -59,18 +58,25 @@ const saveWindowState = () => {
// Do this on window mount.
const onWindowMount = (): void => {
console.log("BW:Adding window listeners. ")
// Must tell initApp that window exists.
backgroundMitt.emit('window-active', true);
// Handle win nav-bar event.
ipcMain.removeHandler('nav-bar'); // avoid setting duplicate handlers
ipcMain.handle('nav-bar', onNavBar);
ipcMain.removeHandler("nav-bar") // avoid setting duplicate handlers
ipcMain.handle("nav-bar", onNavBar);
// Gateway for messages to the frontend.
backgroundMitt.removeAllListeners('ipc-renderer')
backgroundMitt.on('ipc-renderer', renderMessage);
console.log("BW:Listeners created.")
}
// Do this on window dismount (close).
const onWindowDismount = (): void => {
console.log("BW:Window closed.")
win = null;
backgroundMitt.emit('window-active', false);
}
@ -78,6 +84,7 @@ const onWindowDismount = (): void => {
// function used by run.ts to create the main window.
export async function createWindow(): Promise<void> {
return new Promise((resolve, _reject) => {
console.log("BW:Creating browser window. ")
// avoid creating duplicate windows.
if (win) resolve();
@ -122,6 +129,7 @@ export async function createWindow(): Promise<void> {
if (win) win.show()
})
// For showing/hiding the splash screen.
win.webContents.on('did-finish-load', () => {
if (win) win.webContents.send('window-ready', {
message: true