From d851db2fccf166927d862756eb7ecaf0db3934d3 Mon Sep 17 00:00:00 2001 From: riqo Date: Mon, 14 Jun 2021 08:52:01 -0500 Subject: [PATCH] update sockets, account, auth --- build/config.gypi | 79 ------------------ package.json | 4 +- public/index.html | 6 +- src/account.ts | 105 +++++++++++++++++++++++ src/api/account.ts | 41 ++++----- src/auth.ts | 13 +++ src/composables/http.ts | 7 +- src/composables/ipcHandler.ts | 50 +++++++++++ src/composables/json.ts | 10 ++- src/composables/store.ts | 19 +++++ src/composables/websockets.ts | 49 +++++++++-- src/config.ts | 17 ++++ src/init.ts | 4 +- src/ipc/account.ts | 152 +++++++--------------------------- src/ipc/index.ts | 23 ++++- src/ipc/session.ts | 6 +- src/main.ts | 60 ++++---------- src/session.ts | 49 +++++++---- src/types.ts | 23 +++++ src/window.ts | 20 +++-- 20 files changed, 411 insertions(+), 326 deletions(-) delete mode 100644 build/config.gypi create mode 100644 src/account.ts create mode 100644 src/auth.ts create mode 100644 src/composables/ipcHandler.ts create mode 100644 src/composables/store.ts create mode 100644 src/config.ts diff --git a/build/config.gypi b/build/config.gypi deleted file mode 100644 index 6f84ed7..0000000 --- a/build/config.gypi +++ /dev/null @@ -1,79 +0,0 @@ -# Do not edit. File was generated by node-gyp's "configure" step -{ - "target_defaults": { - "cflags": [], - "default_configuration": "Release", - "defines": [], - "include_dirs": [], - "libraries": [] - }, - "variables": { - "asan": 0, - "build_v8_with_gn": "false", - "coverage": "false", - "dcheck_always_on": 0, - "debug_nghttp2": "false", - "debug_node": "false", - "enable_lto": "false", - "enable_pgo_generate": "false", - "enable_pgo_use": "false", - "error_on_warn": "false", - "force_dynamic_crt": 0, - "host_arch": "x64", - "icu_data_in": "../../deps/icu-tmp/icudt67l.dat", - "icu_endianness": "l", - "icu_gyp_path": "tools/icu/icu-generic.gyp", - "icu_path": "deps/icu-small", - "icu_small": "false", - "icu_ver_major": "67", - "is_debug": 0, - "llvm_version": "0.0", - "napi_build_version": "6", - "node_byteorder": "little", - "node_debug_lib": "false", - "node_enable_d8": "false", - "node_install_npm": "true", - "node_module_version": 83, - "node_no_browser_globals": "false", - "node_prefix": "/", - "node_release_urlbase": "https://nodejs.org/download/release/", - "node_shared": "false", - "node_shared_brotli": "false", - "node_shared_cares": "false", - "node_shared_http_parser": "false", - "node_shared_libuv": "false", - "node_shared_nghttp2": "false", - "node_shared_openssl": "false", - "node_shared_zlib": "false", - "node_tag": "", - "node_target_type": "executable", - "node_use_bundled_v8": "true", - "node_use_dtrace": "true", - "node_use_etw": "false", - "node_use_node_code_cache": "true", - "node_use_node_snapshot": "true", - "node_use_openssl": "true", - "node_use_v8_platform": "true", - "node_with_ltcg": "false", - "node_without_node_options": "false", - "openssl_fips": "", - "openssl_is_fips": "false", - "shlib_suffix": "83.dylib", - "target_arch": "x64", - "v8_enable_31bit_smis_on_64bit_arch": 0, - "v8_enable_gdbjit": 0, - "v8_enable_i18n_support": 1, - "v8_enable_inspector": 1, - "v8_enable_pointer_compression": 0, - "v8_no_strict_aliasing": 1, - "v8_optimized_debug": 1, - "v8_promise_internal_field_count": 1, - "v8_random_seed": 0, - "v8_trace_maps": 0, - "v8_use_siphash": 1, - "want_separate_host_toolset": 0, - "xcode_version": "11.0", - "nodedir": "/Users/Enrique/Library/Caches/node-gyp/14.4.0", - "standalone_static_library": 1 - } -} diff --git a/package.json b/package.json index 38c1348..2b4b7fd 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "postinstall": "electron-builder install-app-deps", "postuninstall": "electron-builder install-app-deps" }, - "main": "background.js", + "main": "init.js", "dependencies": { "@google-cloud/speech": "^4.2.0", "@types/animejs": "^3.1.2", @@ -73,7 +73,7 @@ "lintOnSave": false, "pluginOptions": { "electronBuilder": { - "preload": "src/preload.ts", + "preload": "src/renderer/preload.ts", "builderOptions": { "appId": "com.crimata.ElectronUpdaterApp", "artifactName": "${productName}-${version}.${ext}", diff --git a/public/index.html b/public/index.html index 48809d8..8f79d27 100644 --- a/public/index.html +++ b/public/index.html @@ -11,11 +11,7 @@ - -
+
diff --git a/src/account.ts b/src/account.ts new file mode 100644 index 0000000..4884135 --- /dev/null +++ b/src/account.ts @@ -0,0 +1,105 @@ + +import { postAuth, postLogin, postLogout } from "@/api/account"; +import { endSession, launchSession } from "@/session"; +import { getToken, clearToken, setToken } from "@/composables/store"; +import { parseAuthRes } from "./auth"; + +export const accountAuth = async (): Promise => { + + /* attempt to get a login token from the store */ + const token = getToken(); + + /* try to login with it, returns platform secret and new token on success */ + if (token) { + try { + + const res = await postAuth(token); + + const parsed = parseAuthRes(res); + + setToken(parsed.token) + + return { + profile: parsed.profile, + token: parsed.token + }; + + } catch(e) { + console.log('[ACCOUNT]', e); + clearToken(); + throw(new Error('Failed to authenticate.')); + + } + } else { + throw(new Error('Unable to authenticate.')); + } +}; + +export const accountLogin: IpcHandlerCallback = async (payload) => { + const account = payload as AccountCredentials; + try { + + // attempt login with email password + const res = await postLogin(account.email, account.password); + const parsed = parseAuthRes(res); + + // save jwt token and profile + setToken(parsed.token) + + // launch session + launchSession(parsed.token) + + // return profile to renderer + return parsed.profile; + + } catch(e) { + throw e; + } +} + +// export const accountLogin = async (account: Account): Promise => { +// +// try { +// +// // attempt login with email password +// const res = await postLogin(account.email, account.password); +// const parsed = parseAuthRes(res); +// +// // save jwt token and profile +// setToken(parsed.token) +// +// // launch session +// launchSession(parsed.token) +// +// // return profile to renderer +// return parsed.profile; +// +// } catch(e) { +// console.log('[ACCOUNT]', e); +// throw (new Error('Failed to authenticate')); +// } +// +// } + +export const accountLogout = async (): Promise => { + + try { + // post logout to backend + await postLogout(); + + // remove key and crimataId + clearToken(); + + // kill crimata platform session + endSession(); + + return; + + } catch(e) { + console.log('[ACCOUNT]', e); + return (new Error('Failed to logout. Please try again.')); + } + +} + + diff --git a/src/api/account.ts b/src/api/account.ts index 98d3c69..a907dfb 100644 --- a/src/api/account.ts +++ b/src/api/account.ts @@ -1,36 +1,31 @@ import { useHttp } from "@/composables/http"; import axios from "axios"; +import {config} from "@/config"; const { post } = useHttp(); -export const usrPwdAuth = async (email: string, password: string) => { +export const postAuth = async (token: string) => ( + await axios({ + url: config.BUSINESS_URL + config.BUSINESS_PREFIX + '/account/authenticate', + headers: { + Cookie: `jwt=${token}` + }, + method: 'POST', + }) +).data; - try { - return await post('/account/login', { email, password }) - } catch (e) { - return null; - } +export const postLogin = async (email: string, password: string) => ( + await post('/account/login', { email, password }) +).data; + + +export const postLogout = + async (): Promise => (await post('/account/logout')); + -} -export const tokenAuth = async (cid: string, token: string) => { - try { - return await axios({ - url: "http://127.0.0.1:3000/api/account/profile", - headers: { - Cookie: `jwt=${token}` - }, - method: 'GET', - data: { - cid, - } - }) - } catch (e) { - return null; - } -} \ No newline at end of file diff --git a/src/auth.ts b/src/auth.ts new file mode 100644 index 0000000..14ed36a --- /dev/null +++ b/src/auth.ts @@ -0,0 +1,13 @@ + +export const parseAuthRes = (authRes: any) => { + const token = authRes.headers['set-cookie'][0].split(";")[0].split("=")[1] as string; + const profile = authRes.data as Profile; + return { + token, + profile + } +}; + + + + diff --git a/src/composables/http.ts b/src/composables/http.ts index a9519a8..e789afa 100644 --- a/src/composables/http.ts +++ b/src/composables/http.ts @@ -1,10 +1,8 @@ import axios, { AxiosRequestConfig } from 'axios'; +import {config} from "@/config"; -const preFix = '/api'; - -const baseURL = "http://127.0.0.1:3000" + preFix; - +const baseURL = config.BUSINESS_URL + config.BUSINESS_PREFIX; interface Request { endpoint: string; @@ -12,7 +10,6 @@ interface Request { config?: Record; } - const makeQuery = (reqQuery: Record) => { let result = ''; diff --git a/src/composables/ipcHandler.ts b/src/composables/ipcHandler.ts new file mode 100644 index 0000000..b588102 --- /dev/null +++ b/src/composables/ipcHandler.ts @@ -0,0 +1,50 @@ + +import { ipcMain, IpcMainInvokeEvent } from "electron"; + +export class IpcHandler implements IIpcHandler { + + readonly channel: string; + + readonly _handlerCallback: IpcHandlerCallback; + + constructor(options: { + channel: string; + handlerCallback: IpcHandlerCallback; + }) { + this.channel = options.channel; + this._handlerCallback = options.handlerCallback; + } + + handle() { + ipcMain.handle(this.channel, this._onInvoke); + } + + remove() { + ipcMain.removeHandler(this.channel); + } + + private async _onInvoke(_e: IpcMainInvokeEvent, payload?: string | null): Promise { + + return new Promise(async (resolve, reject) => { + + console.log(`[IPC]:${this.channel}`); + + try { + + const params = payload ? JSON.parse(payload) : null; + + const res = await this._handlerCallback(params); + + resolve(res as unknown as ReturnType); + + } catch(e) { + console.log(`[IPC]:${this.channel}`, e); + reject(e); + } + }); + } + +} + + + diff --git a/src/composables/json.ts b/src/composables/json.ts index 43b3804..06ab4b9 100644 --- a/src/composables/json.ts +++ b/src/composables/json.ts @@ -1,9 +1,13 @@ + +import {config} from "@/config"; +import fs from 'fs'; + export const saveToJson = (fileName: string, data: any) => { - fs.writeFile(configPath + fileName, JSON.stringify(data), (err) => { + fs.writeFile(config.configPath + fileName, JSON.stringify(data), (err) => { if (err) { console.log("Error when saving to json.") - } + } }) -} \ No newline at end of file +} diff --git a/src/composables/store.ts b/src/composables/store.ts new file mode 100644 index 0000000..88b9c17 --- /dev/null +++ b/src/composables/store.ts @@ -0,0 +1,19 @@ +const Store = require('electron-store'); + +const schema = { + key: { + type: 'string', + }, +}; + +const store = new Store({ + schema, + encryptionKey: "super user test" +}); + +export const getToken = (): string | undefined => (store.get("token")); + +export const clearToken = (): void => (store.delete("token")); + +export const setToken = (token: string): void => (store.set('token', token)); + diff --git a/src/composables/websockets.ts b/src/composables/websockets.ts index d034027..8208109 100644 --- a/src/composables/websockets.ts +++ b/src/composables/websockets.ts @@ -3,9 +3,18 @@ import WebSocket from 'ws'; -export default function useWebSockets(onMessageCallback: (s: string) => void) { - let socket: WebSocket | null = null; +const _connectionCheckTimeout = 4000; +const _reconnectTimeout = 1000; +let _connectionCheckInterval: ReturnType; + + +export default function useWebSockets( + messageCallback: (message: string) => void, + connectionStatusCallback: (alive: boolean) => void, +) { + + let socket: WebSocket; const send = async (data: Record): Promise => { return new Promise((resolve, reject) => { @@ -21,30 +30,52 @@ export default function useWebSockets(onMessageCallback: (s: string) => void) { const connect = (socketUrl: string, secret: string) => { + // avoid setting multiple interval; + if (_connectionCheckInterval) clearInterval(_connectionCheckInterval); + /* create a new socket */ - socket = new WebSocket(socketUrl) + socket = new WebSocket(socketUrl); /* add event listeners */ - socket.on("open", () => { - if (socket) + socket.send(secret); + + // ping server + _connectionCheckInterval = setInterval(() => { + + socket.ping(null, true, (e: Error) => { + if (e) { + socket.close(); + connectionStatusCallback(false); + setTimeout(() => connect(socketUrl, secret), _reconnectTimeout); + } + }); + + }, _connectionCheckTimeout); + }); socket.on("message", (event: WebSocket.MessageEvent) => { - onMessageCallback(event.data.toString()) + messageCallback(event.data.toString()) }); - socket.on("close", () => { - return + socket.on("close", (event: WebSocket.CloseEvent) => { + connectionStatusCallback(false); + clearInterval(_connectionCheckInterval); + if (!event.wasClean) { + setTimeout(() => connect(socketUrl, secret), _reconnectTimeout); + } + }); + socket.on("pong", () => connectionStatusCallback(true)); + } const close = () => { if (socket) { socket.close(); - socket = null; } } diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..b0eb27e --- /dev/null +++ b/src/config.ts @@ -0,0 +1,17 @@ + +import { app } from "electron"; + +const env = process.env; + +const PLATFORM_PORT = env.PLATFORM_PORT || 8760; +const PLATFORM_IP = env.PLATFORM_IP || 'http://127.0.0.1'; + +const BUSINESS_PORT = env.BUSINESS_PORT || 3010; +const BUSINESS_IP = env.BUSINESS_IP || 'http://127.0.0.1'; + +export const config = { + PLATFORM_URL: `${PLATFORM_IP}:${PLATFORM_PORT}`, + BUSINESS_URL: `${BUSINESS_IP}:${BUSINESS_PORT}`, + BUSINESS_PREFIX: '/api', + configPath: app.getPath('userData') +} diff --git a/src/init.ts b/src/init.ts index 3d0b721..e68e766 100644 --- a/src/init.ts +++ b/src/init.ts @@ -9,8 +9,6 @@ import { app, protocol } from "electron"; import createWindow from "./window"; import main from "./main"; -require('dotenv').config(); - console.log('Starting Crimata electron app.'); // Scheme must be registered before the app is ready @@ -43,4 +41,4 @@ if (isDev) { process.on("SIGTERM", () => { app.quit(); }); -} \ No newline at end of file +} diff --git a/src/ipc/account.ts b/src/ipc/account.ts index 3860019..531d1a7 100644 --- a/src/ipc/account.ts +++ b/src/ipc/account.ts @@ -1,126 +1,32 @@ "use strict"; -import { submit, fetchProfile, logout } from "../api/account"; -import { ipcMain, IpcMainInvokeEvent } from "electron"; -import { store } from "@/composables/store"; - - -const parseAuthRes = (authRes: any) => { - const token = authRes.headers['set-cookie'][0].split(";")[0].split("=")[1] as string; - const profile = authRes.data as Profile; - return { - token, - profile - } -}; - - - - - -/** - * Get user profile from store and try to login with it. - */ -const onTokenLogin = async ( - _event: IpcMainInvokeEvent, - _payload: null -): Promise => ( - - new Promise(async (resolve, reject) => { - console.log('[IPC]: user-profile'); - - // get jwt token and crimataId from store - const token = store.get('key'); - const crimataId = store.get('crimataId'); - - // authenticate and fetch profile - try { - - // attempt login with email token - const res = await fetchProfile(crimataId, token); - const parsed = parseAuthRes(res); - - // return profile to renderer - resolve(parsed.profile); - - } catch(e) { - reject(new Error('Failed to fetch profile.')); - } - }) -) - - -const onLogin = async ( - _event: IpcMainInvokeEvent, - payload: string -): Promise => ( - - new Promise(async (resolve, reject) => { - console.log('[IPC]: user-login'); - - const account = JSON.parse(payload); - - if ( account.password && account.email ) { - try { - - // attempt login with email password - const res = await submit(account.email, account.password); - const parsed = parseAuthRes(res); - - // save jwt token and profile - store.set('key', parsed.token); - store.set('crimataId', parsed.profile.crimataId); - - // init session - - // return profile to renderer - resolve(parsed.profile); - - } catch(e) { - console.log('[API]', e); - reject(new Error('Failed to authenticate')); - } - } - }) -) - -const onLogout = async ( - _event: IpcMainInvokeEvent, - _payload: null -): Promise => ( - - new Promise(async (resolve, reject) => { - console.log('[IPC]: user-logout'); - - try { - // post logout to backend - await logout(); - - // remove key and crimataId - store.delete('key'); - store.delete('crimataId'); - - // TODO: kill crimata platform session - // endSession(); - - resolve(); - } catch(e) { - reject(new Error('Failed to logout. Please try again.')); - } - }) -) - - -export default function useAccountListeners(): void { - - ipcMain.removeHandler("user-profile"); - ipcMain.handle("user-profile", onProfile); - - ipcMain.removeHandler("user-login"); - ipcMain.handle("user-login", onLogin); - - ipcMain.removeHandler("user-logout"); - ipcMain.handle("user-logout", onLogout); - -} +import { accountLogin, accountLogout } from "@/account"; +import {IpcHandler} from "@/composables/ipcHandler"; + +const LOGIN_CHANNEL = "account-login"; +const LOGOUT_CHANNEL = "account-logout"; + +const loginHandler = new IpcHandler({ + channel: LOGIN_CHANNEL, + handlerCallback: accountLogin +}); + +const logoutHandler = new IpcHandler({ + channel: LOGOUT_CHANNEL, + handlerCallback: accountLogout +}); + +const handlers = [loginHandler, logoutHandler]; + +export default handlers; + +// export default function useAccountListeners(): void { +// +// ipcMain.removeHandler(LOGIN_HANDLER); +// ipcMain.handle(LOGIN_HANDLER, onLogin); +// +// ipcMain.removeHandler(LOGOUT_HANDLER); +// ipcMain.handle(LOGOUT_HANDLER, onLogout); +// +// } diff --git a/src/ipc/index.ts b/src/ipc/index.ts index 9152ef2..73a5901 100644 --- a/src/ipc/index.ts +++ b/src/ipc/index.ts @@ -1,17 +1,36 @@ "use strict"; -import useAccountListeners from "./account"; +import { IpcHandler } from "@/composables/ipcHandler"; +import handlers from "./account"; import useSessionListeners from "./session"; // import useAudioListeners from "./audio"; +interface IPCHandlers { + [channel: string]: IpcHandler; +} + +const ipcHandlers: IPCHandlers = {}; + +const _initHandlers = () => { + handlers.forEach((h) => { + if (!(h.channel in ipcHandlers)) { + ipcHandlers[h.channel] = h; + h.handle(); + } + }); +} export default function useIpc(): void { - useAccountListeners(); + _initHandlers(); + + // useAccountListeners(); useSessionListeners(); // useAudioListeners(); } + + diff --git a/src/ipc/session.ts b/src/ipc/session.ts index fa50aa1..bbaf0e9 100644 --- a/src/ipc/session.ts +++ b/src/ipc/session.ts @@ -10,11 +10,11 @@ function onSendMessage(_event: IpcMainEvent, payload: Message): void { } // Login attempt, returns success or not. -function onLogin(_event: IpcMainEvent, payload: LoginPayload) => { - authenticate(payload.email, payload.password); +function onLogin(_event: IpcMainEvent, payload: LoginPayload): void { + console.log('hello') } export default function useSessionListeners(): void { ipcMain.removeAllListeners("client-message"); ipcMain.on("client-message", onSendMessage); -} \ No newline at end of file +} diff --git a/src/main.ts b/src/main.ts index 9d6414c..b015cd9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,41 +1,21 @@ /** * Where the background logic really begins, gets called by app.onReady(). - * + * * Handles authentication. If profile is set, we launch a session, which consis * of opening a connection with the platform, initializing the audio streams. - * + * * The session is primarily an interface between the frontend and the platform, * relaying messages from one to the other. - * + * */ -import { tokenAuth, usrPwdAuth } from "@/api/account"; -import { launchSession, endSession } from "@/session"; import useIpc from "@/ipc/index"; -import store from "@/composables/store"; +import { accountAuth } from "./account"; +import { launchSession } from "./session"; +import ipcEmit from "./composables/emitter"; +import createWindow from "./window"; -/* authenticate the user */ -export async function authenticate(email: string, password: string) { - - /* attempt normal login */ - const platformKey, token, crimataId = await usrPwdAuth(email, password); - - /* launch if successful */ - if (platformKey) - launchSession(platformKey, crimataId); - - /* save the token */ - store.set("token", token); - -} - -/* logout the user, end the session */ -export function deauthenticate() { - - /* terminate the session */ - endSession(); - -} +let authState: AuthState | null; export default async function main() { @@ -45,18 +25,14 @@ export default async function main() { /* launch browser window */ await createWindow(); - /* attempt to get a login token from the store */ - const token = store.get("token"); - - /* try to login with it, returns platform secret and new token on success */ - if (token) - const newToken, profile = await tokenAuth(token); + try { + authState = await accountAuth() as AuthState; + } catch(e) { + console.log('AUTH:', e); + authState = null; + } finally { + if (authState) launchSession(authState.token as string); + ipcEmit("set-profile", authState?.profile); + } - /* if secret, we launch a session */ - if (newToken) - launchSession(newToken, profile); - - /* finally, save the most recent token */ - store.set("token", newToken); - -} \ No newline at end of file +} diff --git a/src/session.ts b/src/session.ts index afebe5b..158c41e 100644 --- a/src/session.ts +++ b/src/session.ts @@ -2,24 +2,34 @@ -import useAudio from "@/audio"; -import Canvas from "@/composables/convas"; +// import useAudio from "@/audio"; import ipcEmit from "@/composables/emitter"; +import useWebsockets from "./composables/websockets"; +import {config} from "@/config"; /* data structure of messages that's tied to the UI */ -let msgrState: UIState | null = null; +const uiState: any | null = null; /* start and stop audio functionality */ -const { initAudio, closeAudio } = useAudio(); +// const { initAudio, closeAudio } = useAudio(); + +let isInitMessage: any; + +let deauthenticate: any; +let isAddMessage: any /** * Controls for interfacing with the platform. * Takes an onMessage callback which we define below. */ -const { connect, send, close } = useWebsockets((content: any) => { + + +const onMessageCallback = (message: string) => { + + const content = JSON.parse(message); /* if the platform fails to authenticate, we must back down */ - if (content === "auth_error") { + if (content === "CLOSE_AUTH_FAIL") { deauthenticate(); return; } @@ -28,8 +38,8 @@ const { connect, send, close } = useWebsockets((content: any) => { if (isInitMessage(content)) { uiState.set(content); } - - + + else if (isAddMessage(content)) { uiState.add(content); } @@ -37,10 +47,15 @@ const { connect, send, close } = useWebsockets((content: any) => { else { uiState.update(content); } +} + +const onConnectionStatusCallback = (alive: boolean) => { + ipcEmit('connection-state', alive); +} -}); +const { connect, send, close } = useWebsockets(onMessageCallback, onConnectionStatusCallback); -/* send a message to the platform */ +/* send a message to the platform */ export function sendMessage(message: Message) { /* socket send */ @@ -48,24 +63,22 @@ export function sendMessage(message: Message) { } + /* launch a new session (the main process for authenticated users) */ -export function launchSession(platformKey: string, crimata_id: string) { +export function launchSession(platformKey: string) { /* connect to the platform */ - connect(PLATFORM_URL, platformKey); + connect(config.PLATFORM_URL, platformKey); /* initialize the audio streams */ - initAudio(); - - /* push profile to window */ - if (win) - ipcEmit("update-auth", crimata_id); + // initAudio(); } + export function endSession() { - closeAudio(); + // closeAudio(); close(); diff --git a/src/types.ts b/src/types.ts index e8682b8..583371e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,3 +1,4 @@ + interface Message { text: boolean | string; context: boolean | string; @@ -28,3 +29,25 @@ interface LoginPayload { email: string; password: string; } + +interface AuthState { + profile: Profile | null; + token: string | null; +} + +interface AccountCredentials { + email: string; + password: string; +} + +interface IpcHandlerCallback { + (payload: I | null): Promise; +} + +interface IIpcHandler { + handle(): void; + remove(): void; + readonly _handlerCallback: IpcHandlerCallback; +} + + diff --git a/src/window.ts b/src/window.ts index 4c69387..807064a 100644 --- a/src/window.ts +++ b/src/window.ts @@ -1,10 +1,12 @@ "use strict"; -import { BrowserWindow, ipcMain } from "electron"; +import { BrowserWindow, ipcMain, app } from "electron"; import { createProtocol } from "vue-cli-plugin-electron-builder/lib"; -import { backgroundMitt } from './coposables/emitter'; -import { saveToJson } from "./coposables/json"; +import { backgroundMitt } from './composables/emitter'; +import { saveToJson } from "./composables/json"; import * as path from "path"; +import fs from 'fs'; +import { config } from "@/config"; const { autoUpdater } = require('electron-updater'); interface IpcRendererPayload { @@ -19,8 +21,8 @@ const loadWinState = (fileName: string): WindowState => { let state: WindowState; try { - state = JSON.parse(fs.readFileSync(configPath + fileName).toString()); - } + state = JSON.parse(fs.readFileSync(config.configPath + fileName).toString()); + } catch (error) { state = { @@ -32,8 +34,8 @@ const loadWinState = (fileName: string): WindowState => { } return state - -} + +} // Called when a NavBar button is pressed. const onNavBar = (_event: any, action: string): void => { @@ -110,8 +112,8 @@ export default async function createWindow(): Promise { win = new BrowserWindow({ width: winState.width, height: winState.height, - x: winState.x, - y: winState.y, + x: winState.x as number, + y: winState.y as number, resizable: true, backgroundColor: '#EBEBEB', frame: false, -- 2.43.0