Compare commits
16 changed files with 12971 additions and 953 deletions
26
.gitignore
vendored
26
.gitignore
vendored
|
|
@ -1,29 +1,5 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/node_modules
|
/node_modules
|
||||||
/.log
|
/out
|
||||||
|
|
||||||
crash.log
|
|
||||||
|
|
||||||
# local env files
|
|
||||||
.env.local
|
|
||||||
.env.*.local
|
|
||||||
.env
|
|
||||||
|
|
||||||
# Log files
|
|
||||||
npm-debug.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.idea
|
|
||||||
.vscode
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
||||||
|
|
||||||
# Dist
|
|
||||||
*.app
|
|
||||||
|
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
*.sublime-project
|
|
||||||
|
|
|
||||||
2
.npmrc
2
.npmrc
|
|
@ -1,2 +1,2 @@
|
||||||
@crimata:registry=https://gitlab.com/api/v4/projects/28849281/packages/npm/
|
@crimata:registry=https://gitlab.com/api/v4/projects/28849281/packages/npm/
|
||||||
//gitlab.com/api/v4/projects/28849281/packages/npm/:_authToken=${API_TOKEN}
|
//gitlab.com/api/v4/projects/28849281/packages/npm
|
||||||
66
README.md
66
README.md
|
|
@ -1,66 +0,0 @@
|
||||||
# crimata-electron
|
|
||||||
|
|
||||||
## Project setup
|
|
||||||
```
|
|
||||||
yarn install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
|
||||||
```
|
|
||||||
yarn electron:serve
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and minifies for production
|
|
||||||
```
|
|
||||||
yarn electron:build
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- ### Run your unit tests
|
|
||||||
```
|
|
||||||
yarn test:unit
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lints and fixes files
|
|
||||||
```
|
|
||||||
yarn lint
|
|
||||||
``` -->
|
|
||||||
|
|
||||||
### Customize configuration
|
|
||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
||||||
|
|
||||||
## Sign and Notarize
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
* Apple Developer Account ($99)
|
|
||||||
* Valid Apple Developer ID Application Certificate on keychain
|
|
||||||
|
|
||||||
Clear debris from app before signing:
|
|
||||||
|
|
||||||
xattr -cr Electron.app
|
|
||||||
|
|
||||||
Sign and Notarize:
|
|
||||||
|
|
||||||
node notarize.js
|
|
||||||
|
|
||||||
Debug electron-osx-sign:
|
|
||||||
|
|
||||||
export DEBUG=electron-osx-sign*
|
|
||||||
|
|
||||||
### Some things to note:
|
|
||||||
|
|
||||||
Notarize only when distributing outside the Mac App Store.
|
|
||||||
|
|
||||||
#### Gatekeeper Assess
|
|
||||||
Electron-osx-sign seems to have a bug where the sign will fail if "gatekeeper-assess" is true (default).
|
|
||||||
|
|
||||||
#### Entitlements.plist
|
|
||||||
Not to be confused with Info.plist, this file specifies entitlements the app can have in hardened runtime (e.g. Can I use the microphone?). Only including the ones Electron reccommends seems to work (including audio of course and omitting allow-unsigned-executable-memory).
|
|
||||||
|
|
||||||
#### The Benifit of Electron OSX Sign
|
|
||||||
Without this package, we would have to manually go in and figure out how to sign each level of the app. While it didn't work out of the box (gatekeeper-assess) it seems to be good otherwise. However, there is a bug where it puts multiple runtime flags on each command - not catastrophic though.
|
|
||||||
|
|
||||||
#### Apple Password
|
|
||||||
This must be an app specific password, not your normal Apple ID password.
|
|
||||||
|
|
||||||
#### --Signiture-Flags OSX Sign
|
|
||||||
Not exactly sure what this does or why its important, but Electron includes it.
|
|
||||||
8
electron.sublime-project
Normal file
8
electron.sublime-project
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"folders":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
52
notarize.js
52
notarize.js
|
|
@ -1,52 +0,0 @@
|
||||||
const exec = require('child_process').exec;
|
|
||||||
const sign = require("electron-osx-sign").signAsync;
|
|
||||||
const notarize = require("electron-notarize").notarize;
|
|
||||||
|
|
||||||
const app = "Crimata.app";
|
|
||||||
const dir = `${app}/Contents/Resources/app`;
|
|
||||||
|
|
||||||
const runShellCommand = (cmd) => (new Promise((resolve, reject) => {
|
|
||||||
exec(cmd, (error, stdout, stderr) => {
|
|
||||||
error ? reject(stderr) : resolve(stdout);
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
const signConfig = {
|
|
||||||
"app": app,
|
|
||||||
"hardened-runtime": true,
|
|
||||||
"gatekeeper-assess": false,
|
|
||||||
"signature-flags": "library",
|
|
||||||
"entitlements": "entitlements.plist",
|
|
||||||
"entitlements-inherit": "entitlements.plist",
|
|
||||||
};
|
|
||||||
|
|
||||||
const notarizeConfig = {
|
|
||||||
appPath: app,
|
|
||||||
appleId: "[email protected]",
|
|
||||||
appBundleId: "com.crimata.CrimataMessenger",
|
|
||||||
appleIdPassword: process.env["AC_PASSWORD"]
|
|
||||||
};
|
|
||||||
|
|
||||||
(async function () {
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
console.log("Building...");
|
|
||||||
await runShellCommand(`rm -rf ${dir} && mkdir ${dir} && cp -r {package.json,src,node_modules} ${dir}
|
|
||||||
`);
|
|
||||||
|
|
||||||
console.log("Cleaning...");
|
|
||||||
await runShellCommand(`xattr -cr ${app}`);
|
|
||||||
|
|
||||||
console.log("Signing...");
|
|
||||||
await sign(signConfig);
|
|
||||||
|
|
||||||
console.log("Notarizing...");
|
|
||||||
await notarize(notarizeConfig);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
12612
package-lock.json
generated
12612
package-lock.json
generated
File diff suppressed because it is too large
Load diff
53
package.json
53
package.json
|
|
@ -1,25 +1,54 @@
|
||||||
{
|
{
|
||||||
"name": "Crimata",
|
"name": "crimata",
|
||||||
"productName": "crimata-messenger",
|
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
|
||||||
"description": "Cross-platform messenger app (Electron, Vue3)",
|
"description": "Cross-platform messenger app (Electron, Vue3)",
|
||||||
"author": {
|
|
||||||
"name": "Andrew Gundersen"
|
|
||||||
},
|
|
||||||
"main": "src/main.js",
|
"main": "src/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron ."
|
"start": "electron-forge start",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"package": "electron-forge package",
|
||||||
|
"make": "electron-forge make"
|
||||||
|
},
|
||||||
|
"author": "Andrew Gundersen",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@electron-forge/cli": "^6.0.0-beta.63",
|
||||||
|
"@electron-forge/maker-deb": "^6.0.0-beta.63",
|
||||||
|
"@electron-forge/maker-rpm": "^6.0.0-beta.63",
|
||||||
|
"@electron-forge/maker-squirrel": "^6.0.0-beta.63",
|
||||||
|
"@electron-forge/maker-zip": "^6.0.0-beta.63",
|
||||||
|
"electron": "^18.2.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@crimata/nodeaudio": "0.0.0",
|
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"base64-arraybuffer": "^1.0.1",
|
"base64-arraybuffer": "^1.0.1",
|
||||||
"electron-store": "^8.0.0",
|
"electron-store": "^8.0.0",
|
||||||
"ws": "^7.3.1"
|
"ws": "^7.3.1",
|
||||||
|
"electron-squirrel-startup": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"config": {
|
||||||
"electron-notarize": "^1.1.1",
|
"forge": {
|
||||||
"electron-osx-sign": "^0.6.0"
|
"packagerConfig": {},
|
||||||
|
"makers": [
|
||||||
|
{
|
||||||
|
"name": "@electron-forge/maker-squirrel",
|
||||||
|
"config": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "@electron-forge/maker-zip",
|
||||||
|
"platforms": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "@electron-forge/maker-deb",
|
||||||
|
"config": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "@electron-forge/maker-rpm",
|
||||||
|
"config": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ const store = require("./utils/store");
|
||||||
const { launchSession, endSession } = require("./session");
|
const { launchSession, endSession } = require("./session");
|
||||||
const { backgroundMitt, ipcEmit } = require("./utils/emitter");
|
const { backgroundMitt, ipcEmit } = require("./utils/emitter");
|
||||||
|
|
||||||
|
store.set("account", process.env.ACCOUNT);
|
||||||
|
|
||||||
async function auth(_e, creds)
|
async function auth(_e, creds)
|
||||||
{
|
{
|
||||||
const { error, data } = await post("/auth", creds);
|
const { error, data } = await post("/auth", creds);
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ const { app } = require("electron");
|
||||||
|
|
||||||
const DOMAIN = "crimata.com";
|
const DOMAIN = "crimata.com";
|
||||||
|
|
||||||
const prod = !process.defaultApp;
|
/* If PROD env variable exists */
|
||||||
// const prod = true;
|
const prod = process.env.PROD;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
PLATFORM: prod ? `https://app.${DOMAIN}` : `http://localhost:8760`,
|
PLATFORM: prod ? `https://app.${DOMAIN}` : `http://localhost:5000`,
|
||||||
API: prod ? `https://${DOMAIN}/api` : `http://localhost:8761`
|
API: prod ? `https://${DOMAIN}/api` : `http://localhost:5001`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ const store = require("./utils/store");
|
||||||
const { initTray } = require("./tray");
|
const { initTray } = require("./tray");
|
||||||
const { createWin } = require("./window");
|
const { createWin } = require("./window");
|
||||||
const { initAccount } = require("./account");
|
const { initAccount } = require("./account");
|
||||||
const { terminateAudio } = require("./audio");
|
// const { terminateAudio } = require("./audio");
|
||||||
|
|
||||||
// Assert a light theme
|
// Assert a light theme
|
||||||
nativeTheme.themeSource = "light";
|
nativeTheme.themeSource = "light";
|
||||||
|
|
@ -19,7 +19,7 @@ app.on("ready", () =>
|
||||||
initAccount();
|
initAccount();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on("will-quit", terminateAudio);
|
// app.on("will-quit", terminateAudio);
|
||||||
|
|
||||||
// When user clicks app icon (re-open)
|
// When user clicks app icon (re-open)
|
||||||
app.on("activate", createWin);
|
app.on("activate", createWin);
|
||||||
|
|
|
||||||
23
src/render/components/control/valid.js
Normal file
23
src/render/components/control/valid.js
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
export const isEmail = (value) => {
|
||||||
|
console.log(value);
|
||||||
|
if (!/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/.test(value)) {
|
||||||
|
return "Not a valid email."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isPassword = (value) => {
|
||||||
|
if (!/^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,16}$/.test(value)) {
|
||||||
|
return "Password must have symbol, number, uppercase and be 6-16 length.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name is optional and therefore doesn't return error if no value.
|
||||||
|
*/
|
||||||
|
export const isName = (value) => {
|
||||||
|
if (value) {
|
||||||
|
if (!/^([a-zA-Z ]){5,30}$/.test(value)) {
|
||||||
|
return "Name must be at least 5 long.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,83 +1,86 @@
|
||||||
|
|
||||||
|
// Basic debounce implentation
|
||||||
const debounce = (fn, delay) => {
|
const debounce = (fn, delay) => {
|
||||||
|
|
||||||
let timeoutId;
|
let timeoutId;
|
||||||
|
return (...args) => {
|
||||||
const wrapper = (...args) => {
|
if (timeoutId) clearTimeout(timeoutId);
|
||||||
|
|
||||||
if (timeoutId) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
|
|
||||||
timeoutId = setTimeout(() => {
|
timeoutId = setTimeout(() => {
|
||||||
fn(...args);
|
fn(...args);
|
||||||
}, delay);
|
}, delay);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamic form component with auto submission and validation.
|
||||||
const SmartForm =
|
*
|
||||||
|
* props
|
||||||
|
* .fields => List of field objects
|
||||||
|
* .channel => e.g. "/login"
|
||||||
|
* .modifier => Form description
|
||||||
|
*/
|
||||||
|
const SmartForm =
|
||||||
{
|
{
|
||||||
props: ["fields", "channel", "modifier"],
|
props: ["fields", "channel", "modifier"],
|
||||||
|
|
||||||
setup(props)
|
setup(props)
|
||||||
{
|
{
|
||||||
let logsEl;
|
// Error log below form
|
||||||
|
const log = Vue.ref(props.modifier);
|
||||||
|
|
||||||
const submit = debounce(async (data) => {
|
/**
|
||||||
|
* Valid and submit form data to channel.
|
||||||
|
*/
|
||||||
|
const submit = async () => {
|
||||||
|
|
||||||
let object = {};
|
// Validate each field
|
||||||
data.forEach(function(value, key){
|
for (let field of props.fields) {
|
||||||
object[key] = value;
|
const error = field.valid(field.value);
|
||||||
});
|
if (error) return error;
|
||||||
|
|
||||||
const err = await window.mainApi.invoke(props.channel, object)
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
logsEl.innerText = err;
|
|
||||||
logsEl.style.color = "red";
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logsEl.style.color = "green";
|
// Reduce fields into the form
|
||||||
logsEl.innerText = props.modifier;
|
const form = props.fields.reduce((v, n) => {
|
||||||
|
v[n.name] = n.value;
|
||||||
|
return v;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
console.log("Submitting =>", form);
|
||||||
|
return await window.mainApi.invoke(props.channel, form);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for submit that is debounced and updates UI elements
|
||||||
|
*/
|
||||||
|
const preSub = debounce(async () => {
|
||||||
|
|
||||||
|
const error = await submit();
|
||||||
|
|
||||||
|
log.value = error ? error : props.modifier
|
||||||
|
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
Vue.onMounted(() => {
|
return { preSub, log };
|
||||||
|
|
||||||
const el = document.getElementById("smart-form");
|
|
||||||
|
|
||||||
logsEl = el.querySelector(".smart-form-logs");
|
|
||||||
|
|
||||||
logsEl.innerText = props.modifier;
|
|
||||||
|
|
||||||
el.addEventListener("input", () => {
|
|
||||||
submit(new FormData(el))
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
template: `
|
template: `
|
||||||
<form id="smart-form" class="smart-form">
|
<form id="smart-form" class="smart-form" v-on:input="preSub">
|
||||||
|
|
||||||
<div v-for="field in fields" style="display:flex">
|
<div v-for="field in fields" style="display:flex">
|
||||||
|
|
||||||
<input type="text" class="text-field"
|
<input type="text" class="text-field"
|
||||||
|
v-model="field.value"
|
||||||
:name="field.name"
|
:name="field.name"
|
||||||
:value="field.value"
|
|
||||||
:placeholder="field.placeholder"
|
:placeholder="field.placeholder"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="smart-form-logs"></div>
|
<div class="smart-form-logs">{{ log }}</div>
|
||||||
|
|
||||||
</form>`
|
</form>`
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SmartForm;
|
export default SmartForm;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import SmartForm from "./form.js";
|
import SmartForm from "./form.js";
|
||||||
|
import { isEmail, isPassword, isName } from "./control/valid.js";
|
||||||
|
|
||||||
const Login =
|
const Login =
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +9,7 @@ const Login =
|
||||||
|
|
||||||
setup()
|
setup()
|
||||||
{
|
{
|
||||||
return;
|
return { isEmail, isPassword, isName };
|
||||||
},
|
},
|
||||||
|
|
||||||
template: `
|
template: `
|
||||||
|
|
@ -19,16 +20,19 @@ const Login =
|
||||||
name: 'email',
|
name: 'email',
|
||||||
value: null,
|
value: null,
|
||||||
placeholder: 'Email',
|
placeholder: 'Email',
|
||||||
|
valid: isEmail
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'password',
|
name: 'password',
|
||||||
value: null,
|
value: null,
|
||||||
placeholder: 'Password'
|
placeholder: 'Password',
|
||||||
|
valid: isPassword
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
value: null,
|
value: null,
|
||||||
placeholder: 'Name'
|
placeholder: 'Name',
|
||||||
|
valid: isName
|
||||||
}]"
|
}]"
|
||||||
:channel="'auth'"
|
:channel="'auth'"
|
||||||
:modifier="'Login or enter name to register.'"
|
:modifier="'Login or enter name to register.'"
|
||||||
|
|
@ -37,4 +41,4 @@ const Login =
|
||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Login;
|
export default Login;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ const Settings =
|
||||||
},
|
},
|
||||||
|
|
||||||
template: `
|
template: `
|
||||||
<div v-if="active" id="settings" >
|
<div v-if="active" id="settings">
|
||||||
|
|
||||||
<button class="settings-logout-button button" @click="logout">
|
<button class="settings-logout-button button" @click="logout">
|
||||||
Logout
|
Logout
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ html, body {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
height: 100vh; /* 100% for website */
|
height: 100vh; /* 100% for website */
|
||||||
width: 100vw; /* 100% for website */
|
width: 100vw; /* 100% for website */
|
||||||
|
/* Does not work on Linux */
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,6 +93,8 @@ html, body {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
/* Needed for Linux even with higher Z index */
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-menu-button {
|
.header-menu-button {
|
||||||
|
|
@ -227,7 +230,6 @@ html, body {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
/* Set opacity here to not affect child. */
|
/* Set opacity here to not affect child. */
|
||||||
background-color: rgba(235, 235, 235, 0.75);
|
background-color: rgba(235, 235, 235, 0.75);
|
||||||
cursor: pointer;
|
|
||||||
box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.15);
|
box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -294,10 +296,8 @@ html, body {
|
||||||
margin-top: 19px;
|
margin-top: 19px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
background-color: Transparent;
|
background-color: Transparent;
|
||||||
}
|
/* Needed for Linux */
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
.settings-icon:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-account {
|
.settings-account {
|
||||||
|
|
@ -314,10 +314,6 @@ html, body {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-logout-button:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-version {
|
.settings-version {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ const { Notification, ipcMain } = require("electron");
|
||||||
const store = require("./utils/store");
|
const store = require("./utils/store");
|
||||||
const { backgroundMitt, ipcEmit } = require("./utils/emitter");
|
const { backgroundMitt, ipcEmit } = require("./utils/emitter");
|
||||||
const { connectToPlatform, disconnectFromPlatform } = require("./io");
|
const { connectToPlatform, disconnectFromPlatform } = require("./io");
|
||||||
const { initAudio, terminateAudio, playback, streamState } = require("./audio");
|
// const { initAudio, terminateAudio, playback, streamState } = require("./audio");
|
||||||
|
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
|
||||||
|
|
@ -25,10 +25,12 @@ backgroundMitt.on("message", (message) => messageQueue.push(message));
|
||||||
|
|
||||||
function handleMessageQueue()
|
function handleMessageQueue()
|
||||||
{
|
{
|
||||||
if (!streamState.pb && !streamState.rec)
|
// if (!streamState.pb && !streamState.rec)
|
||||||
{
|
// {
|
||||||
const update = messageQueue.shift();
|
const update = messageQueue.shift();
|
||||||
|
|
||||||
|
console.log(update);
|
||||||
|
|
||||||
if (update)
|
if (update)
|
||||||
{
|
{
|
||||||
if (update.person)
|
if (update.person)
|
||||||
|
|
@ -66,30 +68,31 @@ function handleMessageQueue()
|
||||||
body: content.text
|
body: content.text
|
||||||
}).show();
|
}).show();
|
||||||
|
|
||||||
if (content.category == "audio")
|
/* Ideally, we want a more native solution than this */
|
||||||
{
|
// if (current.modifier == "ai" && content.category == "audio")
|
||||||
playback(current.id, content.blob);
|
// {
|
||||||
}
|
// playback(content.blob, current.id);
|
||||||
|
// }
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcEmit("message", update);
|
ipcEmit("message", update);
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchSession(account)
|
function launchSession(account)
|
||||||
{
|
{
|
||||||
connectToPlatform(account);
|
connectToPlatform(account);
|
||||||
initAudio();
|
// initAudio();
|
||||||
processContentId = setInterval(handleMessageQueue, 100);
|
processContentId = setInterval(handleMessageQueue, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function endSession()
|
function endSession()
|
||||||
{
|
{
|
||||||
clearInterval(processContentId);
|
clearInterval(processContentId);
|
||||||
terminateAudio();
|
// terminateAudio();
|
||||||
disconnectFromPlatform();
|
disconnectFromPlatform();
|
||||||
ui = null;
|
ui = null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue