Compare commits

...
13 changed files with 924 additions and 12894 deletions

26
.gitignore vendored
View file

@ -1,5 +1,29 @@
.DS_Store
/node_modules
/out
/.log
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-project

2
.npmrc
View file

@ -1,2 +1,2 @@
@crimata:registry=https://gitlab.com/api/v4/projects/28849281/packages/npm/
//gitlab.com/api/v4/projects/28849281/packages/npm
//gitlab.com/api/v4/projects/28849281/packages/npm/:_authToken=${API_TOKEN}

62
README.md Normal file
View file

@ -0,0 +1,62 @@
# 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
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.

View file

@ -1,8 +0,0 @@
{
"folders":
[
{
"path": "."
}
]
}

52
notarize.js Normal file
View file

@ -0,0 +1,52 @@
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);
}
})();

12592
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,54 +1,25 @@
{
"name": "crimata",
"name": "Crimata",
"productName": "crimata-messenger",
"version": "1.0.0",
"private": true,
"description": "Cross-platform messenger app (Electron, Vue3)",
"author": {
"name": "Andrew Gundersen"
},
"main": "src/main.js",
"scripts": {
"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"
"start": "electron ."
},
"dependencies": {
"@crimata/nodeaudio": "0.0.0",
"axios": "^0.21.1",
"base64-arraybuffer": "^1.0.1",
"electron-store": "^8.0.0",
"ws": "^7.3.1",
"electron-squirrel-startup": "^1.0.0"
"ws": "^7.3.1"
},
"config": {
"forge": {
"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": {}
}
]
}
"devDependencies": {
"electron-notarize": "^1.1.1",
"electron-osx-sign": "^0.6.0"
}
}

View file

@ -5,8 +5,6 @@ const store = require("./utils/store");
const { launchSession, endSession } = require("./session");
const { backgroundMitt, ipcEmit } = require("./utils/emitter");
store.set("account", process.env.ACCOUNT);
async function auth(_e, creds)
{
const { error, data } = await post("/auth", creds);

View file

@ -2,10 +2,10 @@ const { app } = require("electron");
const DOMAIN = "crimata.com";
/* If PROD env variable exists */
const prod = process.env.PROD;
const prod = !process.defaultApp;
// const prod = true;
module.exports = {
PLATFORM: prod ? `https://app.${DOMAIN}` : `http://localhost:5000`,
API: prod ? `https://${DOMAIN}/api` : `http://localhost:5001`
PLATFORM: prod ? `https://app.${DOMAIN}` : `http://localhost:8760`,
API: prod ? `https://${DOMAIN}/api` : `http://localhost:8761`
}

View file

@ -5,7 +5,7 @@ const store = require("./utils/store");
const { initTray } = require("./tray");
const { createWin } = require("./window");
const { initAccount } = require("./account");
// const { terminateAudio } = require("./audio");
const { terminateAudio } = require("./audio");
// Assert a light theme
nativeTheme.themeSource = "light";
@ -17,12 +17,19 @@ app.on("ready", () =>
createWin();
initAccount();
/* Check for an update every minunte */
setInterval(autoUpdater.checkForUpdates, 60000);
});
// app.on("will-quit", terminateAudio);
app.on("will-quit", terminateAudio);
// When user clicks app icon (re-open)
app.on("activate", createWin);
// Prevents app from quitting on window close event
app.on('window-all-closed', (e) => e.preventDefault());
// Update when a new update is downloaded.
autoUpdater.on("update-downloaded", update);

View file

@ -36,7 +36,6 @@ html, body {
-webkit-font-smoothing: antialiased;
height: 100vh; /* 100% for website */
width: 100vw; /* 100% for website */
/* Does not work on Linux */
border-radius: 15px;
}
@ -93,8 +92,6 @@ html, body {
margin-left: 20px;
margin-top: 20px;
z-index: 2;
/* Needed for Linux even with higher Z index */
-webkit-app-region: no-drag;
}
.header-menu-button {
@ -230,6 +227,7 @@ html, body {
border-radius: 50%;
/* Set opacity here to not affect child. */
background-color: rgba(235, 235, 235, 0.75);
cursor: pointer;
box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.15);
}
@ -296,8 +294,10 @@ html, body {
margin-top: 19px;
z-index: 2;
background-color: Transparent;
/* Needed for Linux */
-webkit-app-region: no-drag;
}
.settings-icon:hover {
cursor: pointer;
}
.settings-account {
@ -314,6 +314,10 @@ html, body {
font-size: 14px;
}
.settings-logout-button:hover {
cursor: pointer;
}
.settings-version {
position: absolute;
left: 50%;

View file

@ -3,7 +3,7 @@ const { Notification, ipcMain } = require("electron");
const store = require("./utils/store");
const { backgroundMitt, ipcEmit } = require("./utils/emitter");
const { connectToPlatform, disconnectFromPlatform } = require("./io");
// const { initAudio, terminateAudio, playback, streamState } = require("./audio");
const { initAudio, terminateAudio, playback, streamState } = require("./audio");
const util = require('util');
@ -25,12 +25,10 @@ backgroundMitt.on("message", (message) => messageQueue.push(message));
function handleMessageQueue()
{
// if (!streamState.pb && !streamState.rec)
// {
if (!streamState.pb && !streamState.rec)
{
const update = messageQueue.shift();
console.log(update);
if (update)
{
if (update.person)
@ -69,30 +67,30 @@ function handleMessageQueue()
}).show();
/* Ideally, we want a more native solution than this */
// if (current.modifier == "ai" && content.category == "audio")
// {
// playback(content.blob, current.id);
// }
if (current.modifier == "ai" && content.category == "audio")
{
playback(content.blob, current.id);
}
return;
}
ipcEmit("message", update);
}
// }
}
}
function launchSession(account)
{
connectToPlatform(account);
// initAudio();
initAudio();
processContentId = setInterval(handleMessageQueue, 100);
}
function endSession()
{
clearInterval(processContentId);
// terminateAudio();
terminateAudio();
disconnectFromPlatform();
ui = null;
}

14
src/update.js Normal file
View file

@ -0,0 +1,14 @@
const { app, autoUpdater } = require("electron");
autoUpdater.setFeedURL({ "https://crimata.com" });
async function update()
{
await dialog.showMessageBox({
buttons: ["Ok"],
title: "App Update",
detail: "A new version of the app is available"
});
autoUpdater.quitAndInstall();
}