adding a bunch of linting and starting project over with nothing
This commit is contained in:
Generated
+30667
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,19 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"es6": true,
|
"es2021": true,
|
||||||
"node": true
|
"node": true
|
||||||
},
|
},
|
||||||
"extends": [
|
"extends": ["plugin:react/recommended", "airbnb", "airbnb/hooks", "airbnb-typescript"],
|
||||||
"eslint:recommended",
|
"parser": "@typescript-eslint/parser",
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
"parserOptions": {
|
||||||
"plugin:@typescript-eslint/recommended",
|
"project": "./tsconfig.json"
|
||||||
"plugin:import/recommended",
|
},
|
||||||
"plugin:import/electron",
|
"plugins": ["react", "@typescript-eslint"],
|
||||||
"plugin:import/typescript",
|
"rules": {
|
||||||
"plugin:reac/recommended"
|
"no-shadow": "off",
|
||||||
],
|
"@typescript-eslint/no-shadow": ["error"],
|
||||||
"parser": "@typescript-eslint/parser"
|
"no-unused-vars": "warn",
|
||||||
|
"@typescript-eslint/no-unused-vars": "warn"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,14 +74,19 @@
|
|||||||
"@electron-forge/plugin-webpack": "6.0.0-beta.63",
|
"@electron-forge/plugin-webpack": "6.0.0-beta.63",
|
||||||
"@types/react": "^17.0.40",
|
"@types/react": "^17.0.40",
|
||||||
"@types/react-dom": "^17.0.13",
|
"@types/react-dom": "^17.0.13",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
||||||
"@typescript-eslint/parser": "^5.0.0",
|
"@typescript-eslint/parser": "^5.0.0",
|
||||||
"@vercel/webpack-asset-relocator-loader": "1.7.0",
|
"@vercel/webpack-asset-relocator-loader": "1.7.0",
|
||||||
"autoprefixer": "^10.4.4",
|
"autoprefixer": "^10.4.4",
|
||||||
"css-loader": "^6.0.0",
|
"css-loader": "^6.0.0",
|
||||||
"electron": "17.1.2",
|
"electron": "17.1.2",
|
||||||
"eslint": "^8.0.1",
|
"eslint": "^8.15.0",
|
||||||
"eslint-plugin-import": "^2.25.0",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
|
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||||
|
"eslint-plugin-import": "^2.26.0",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||||
|
"eslint-plugin-react": "^7.29.4",
|
||||||
|
"eslint-plugin-react-hooks": "^4.5.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^6.0.1",
|
"fork-ts-checker-webpack-plugin": "^6.0.1",
|
||||||
"mini-css-extract-plugin": "^2.6.0",
|
"mini-css-extract-plugin": "^2.6.0",
|
||||||
"node-loader": "^2.0.0",
|
"node-loader": "^2.0.0",
|
||||||
@@ -98,8 +103,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@getstation/electron-google-oauth2": "^2.1.0",
|
"@getstation/electron-google-oauth2": "^2.1.0",
|
||||||
"@nirvana/core": "*",
|
|
||||||
"@nirvana/components": "*",
|
"@nirvana/components": "*",
|
||||||
|
"@nirvana/core": "*",
|
||||||
"antd": "^4.20.2",
|
"antd": "^4.20.2",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"electron-squirrel-startup": "^1.0.0",
|
"electron-squirrel-startup": "^1.0.0",
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
import "./styles/index.css";
|
|
||||||
|
|
||||||
import * as React from "react";
|
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
|
|
||||||
import NirvanaApp from "./pages/nirvanaApp";
|
|
||||||
|
|
||||||
function render() {
|
|
||||||
ReactDOM.render(<NirvanaApp />, document.getElementById("root"));
|
|
||||||
}
|
|
||||||
|
|
||||||
render();
|
|
||||||
@@ -1,23 +1,24 @@
|
|||||||
// NOTE: DO NOT ADD ANY ELECTRON RELATED TYPESCRIPT HERE...KEEP IT ONLY TYPESCRIPT OTHERWISE
|
// NOTE: DO NOT ADD ANY ELECTRON RELATED TYPESCRIPT HERE...KEEP IT ONLY TYPESCRIPT OTHERWISE
|
||||||
// THE RENDERER WONT BE ABLE TO ACCESS THIS AS IT WILL THINK ITS PART OF MAIN PROCESS SINCE RENDERER CAN'T ACCESS NODE STUFF
|
// THE RENDERER WONT BE ABLE TO ACCESS THIS AS IT WILL THINK ITS PART
|
||||||
|
// OF MAIN PROCESS SINCE RENDERER CAN'T ACCESS NODE STUFF
|
||||||
// SINCE IT's NOT A NODE PROCESS
|
// SINCE IT's NOT A NODE PROCESS
|
||||||
|
|
||||||
enum Channels {
|
export enum Channels {
|
||||||
ACTIVATE_LOG_IN = "ACTIVATE_LOG_IN",
|
ACTIVATE_LOG_IN = 'ACTIVATE_LOG_IN',
|
||||||
GOOGLE_AUTH_TOKENS = "GOOGLE_AUTH_TOKENS",
|
GOOGLE_AUTH_TOKENS = 'GOOGLE_AUTH_TOKENS',
|
||||||
RESIZE_WINDOW = "RESIZE_WINDOW",
|
RESIZE_WINDOW = 'RESIZE_WINDOW',
|
||||||
ON_WINDOW_BLUR = "ON_WINDOW_BLUR",
|
ON_WINDOW_BLUR = 'ON_WINDOW_BLUR',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum STORE_ITEMS {
|
export enum StoreItems {
|
||||||
AUTH_SESSION_JWT = "AUTH_SESSION_JWT",
|
AUTH_SESSION_JWT = 'AUTH_SESSION_JWT',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Dimensions = { height: number; width: number };
|
export type Dimensions = { height: number; width: number };
|
||||||
|
|
||||||
export interface DimensionChangeRequest {
|
export interface DimensionChangeRequest {
|
||||||
setAlwaysOnTop: boolean;
|
setAlwaysOnTop: boolean;
|
||||||
setPosition?: "topRight" | "center";
|
setPosition?: 'topRight' | 'center';
|
||||||
dimensions: Dimensions;
|
dimensions: Dimensions;
|
||||||
addDimensions: boolean;
|
addDimensions: boolean;
|
||||||
}
|
}
|
||||||
@@ -28,5 +29,3 @@ export const OVERLAY_ONLY_INITIAL_PRESET: Dimensions = {
|
|||||||
height: 50,
|
height: 50,
|
||||||
width: 325,
|
width: 325,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Channels;
|
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
import { Dimensions, DimensionChangeRequest } from "./constants";
|
/* eslint-disable no-unused-vars */
|
||||||
import { electronAPI } from "./preload";
|
import { DimensionChangeRequest, STORE_ITEMS, Channels } from './constants';
|
||||||
|
|
||||||
export {};
|
export {};
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
import Channels, { STORE_ITEMS } from "./constants";
|
|
||||||
|
|
||||||
import ElectronGoogleOAuth2 from "@getstation/electron-google-oauth2";
|
|
||||||
import { browserWindow } from "../index";
|
|
||||||
import { ipcMain } from "electron";
|
|
||||||
import store from "./store";
|
|
||||||
|
|
||||||
const myApiOauth = new ElectronGoogleOAuth2(
|
|
||||||
"423533244953-banligobgbof8hg89i6cr1l7u0p7c2pk.apps.googleusercontent.com",
|
|
||||||
"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",
|
|
||||||
[""],
|
|
||||||
{ successRedirectURL: "http://localhost:3000/auth/success" }
|
|
||||||
);
|
|
||||||
|
|
||||||
// FRESH GOOGLE LOGIN...either no json web tokens or trying to sign in with another account.
|
|
||||||
export async function handleGoogleLogin() {
|
|
||||||
const tokens = await myApiOauth.openAuthWindowAndGetTokens();
|
|
||||||
|
|
||||||
browserWindow.webContents.send(Channels.GOOGLE_AUTH_TOKENS, tokens);
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import Channels, { Dimensions } from "./constants";
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
import { contextBridge, ipcRenderer } from "electron";
|
import { contextBridge, ipcRenderer } from 'electron';
|
||||||
|
import { Channels, Dimensions, StoreItems } from './constants';
|
||||||
import { STORE_ITEMS } from "./constants";
|
|
||||||
|
|
||||||
const electronAPI = {
|
const electronAPI = {
|
||||||
auth: {
|
auth: {
|
||||||
@@ -10,11 +9,11 @@ const electronAPI = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
store: {
|
store: {
|
||||||
get(val: STORE_ITEMS) {
|
get(val: StoreItems) {
|
||||||
return ipcRenderer.invoke("electron-store-get", val);
|
return ipcRenderer.invoke('electron-store-get', val);
|
||||||
},
|
},
|
||||||
set(property: STORE_ITEMS, val: any) {
|
set(property: StoreItems, val: any) {
|
||||||
ipcRenderer.send("electron-store-set", property, val);
|
ipcRenderer.send('electron-store-set', property, val);
|
||||||
},
|
},
|
||||||
// Other method you want to add like has(), reset(), etc.
|
// Other method you want to add like has(), reset(), etc.
|
||||||
},
|
},
|
||||||
@@ -26,7 +25,7 @@ const electronAPI = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
on(channel: Channels, func: any) {
|
on(channel: Channels, func: any) {
|
||||||
const validChannels = ["ipc-example"];
|
// const validChannels = ['ipc-example'];
|
||||||
// if (validChannels.includes(channel)) {
|
// if (validChannels.includes(channel)) {
|
||||||
// // Deliberately strip event as it includes `sender`
|
// // Deliberately strip event as it includes `sender`
|
||||||
// ipcRenderer.on(channel, (event, ...args) => func(...args));
|
// ipcRenderer.on(channel, (event, ...args) => func(...args));
|
||||||
@@ -45,6 +44,6 @@ const electronAPI = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld("electronAPI", electronAPI);
|
contextBridge.exposeInMainWorld('electronAPI', electronAPI);
|
||||||
|
|
||||||
export default electronAPI;
|
export default electronAPI;
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/* eslint-disable react/jsx-filename-extension */
|
||||||
|
import './styles/index.css';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import * as ReactDOM from 'react-dom';
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
ReactDOM.render(<div>this is the electron app</div>, document.getElementById('root'));
|
||||||
|
}
|
||||||
|
|
||||||
|
render();
|
||||||
@@ -1,19 +1,12 @@
|
|||||||
import {
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
BrowserWindow,
|
// eslint-disable-next-line object-curly-newline
|
||||||
Display,
|
import { BrowserWindow, Display, app, ipcMain, screen } from 'electron';
|
||||||
Menu,
|
|
||||||
app,
|
|
||||||
dialog,
|
|
||||||
globalShortcut,
|
|
||||||
ipcMain,
|
|
||||||
screen,
|
|
||||||
} from "electron";
|
|
||||||
import Channels, { DEFAULT_APP_PRESET } from "./electron/constants";
|
|
||||||
|
|
||||||
import { DimensionChangeRequest } from "./electron/constants";
|
import path from 'path';
|
||||||
import { handleGoogleLogin } from "./electron/handleLogin";
|
import ElectronGoogleOAuth2 from '@getstation/electron-google-oauth2';
|
||||||
import path from "path";
|
import { Channels, DEFAULT_APP_PRESET, DimensionChangeRequest } from './electron/constants';
|
||||||
import store from "./electron/store";
|
|
||||||
|
import store from './electron/store';
|
||||||
|
|
||||||
// This allows TypeScript to pick up the magic constant that's auto-generated by Forge's Webpack
|
// This allows TypeScript to pick up the magic constant that's auto-generated by Forge's Webpack
|
||||||
// plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on
|
// plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on
|
||||||
@@ -22,14 +15,29 @@ declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
|
|||||||
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
|
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
|
||||||
|
|
||||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
||||||
if (require("electron-squirrel-startup")) {
|
// eslint-disable-next-line global-require
|
||||||
|
if (require('electron-squirrel-startup')) {
|
||||||
// eslint-disable-line global-require
|
// eslint-disable-line global-require
|
||||||
app.quit();
|
app.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep a global reference of the window object, if you don't, the window will
|
// Keep a global reference of the window object, if you don't, the window will
|
||||||
// be closed automatically when the JavaScript object is garbage collected.
|
// be closed automatically when the JavaScript object is garbage collected.
|
||||||
export let browserWindow: BrowserWindow;
|
let browserWindow: BrowserWindow;
|
||||||
|
|
||||||
|
const myApiOauth = new ElectronGoogleOAuth2(
|
||||||
|
'423533244953-banligobgbof8hg89i6cr1l7u0p7c2pk.apps.googleusercontent.com',
|
||||||
|
'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',
|
||||||
|
[''],
|
||||||
|
{ successRedirectURL: 'http://localhost:3000/auth/success' },
|
||||||
|
);
|
||||||
|
|
||||||
|
// FRESH GOOGLE LOGIN...either no json web tokens or trying to sign in with another account.
|
||||||
|
export default async function handleGoogleLogin() {
|
||||||
|
const tokens = await myApiOauth.openAuthWindowAndGetTokens();
|
||||||
|
|
||||||
|
browserWindow.webContents.send(Channels.GOOGLE_AUTH_TOKENS, tokens);
|
||||||
|
}
|
||||||
|
|
||||||
let display: Display;
|
let display: Display;
|
||||||
|
|
||||||
@@ -41,7 +49,7 @@ const createWindow = (): void => {
|
|||||||
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
|
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
|
||||||
sandbox: true,
|
sandbox: true,
|
||||||
},
|
},
|
||||||
icon: "./assets/1024x1024.icns",
|
icon: './assets/1024x1024.icns',
|
||||||
|
|
||||||
// transparent: true,
|
// transparent: true,
|
||||||
|
|
||||||
@@ -60,7 +68,7 @@ const createWindow = (): void => {
|
|||||||
browserWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
|
browserWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
|
||||||
|
|
||||||
// Open the DevTools.
|
// Open the DevTools.
|
||||||
browserWindow.webContents.openDevTools({ mode: "detach" });
|
browserWindow.webContents.openDevTools({ mode: 'detach' });
|
||||||
|
|
||||||
display = screen.getPrimaryDisplay();
|
display = screen.getPrimaryDisplay();
|
||||||
};
|
};
|
||||||
@@ -74,15 +82,15 @@ app
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
// activate login
|
// activate login
|
||||||
ipcMain.on(Channels.ACTIVATE_LOG_IN, async (event, arg) => {
|
ipcMain.on(Channels.ACTIVATE_LOG_IN, async (event, arg) => {
|
||||||
console.log("initiating log in");
|
console.log('initiating log in');
|
||||||
await handleGoogleLogin();
|
await handleGoogleLogin();
|
||||||
});
|
});
|
||||||
|
|
||||||
// access storage/cookies
|
// access storage/cookies
|
||||||
ipcMain.on("electron-store-set", async (event, key, val) => {
|
ipcMain.on('electron-store-set', async (event, key, val) => {
|
||||||
store.set(key, val);
|
store.set(key, val);
|
||||||
});
|
});
|
||||||
ipcMain.handle("electron-store-get", async (event, val) => {
|
ipcMain.handle('electron-store-get', async (event, val) => {
|
||||||
const result = await store.get(val);
|
const result = await store.get(val);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
@@ -90,7 +98,7 @@ app
|
|||||||
// dynamically changing the window bounds
|
// dynamically changing the window bounds
|
||||||
ipcMain.on(Channels.RESIZE_WINDOW, (event, req: DimensionChangeRequest) => {
|
ipcMain.on(Channels.RESIZE_WINDOW, (event, req: DimensionChangeRequest) => {
|
||||||
if (req.setAlwaysOnTop) {
|
if (req.setAlwaysOnTop) {
|
||||||
browserWindow.setAlwaysOnTop(true, "floating");
|
browserWindow.setAlwaysOnTop(true, 'floating');
|
||||||
} else {
|
} else {
|
||||||
browserWindow.setAlwaysOnTop(false);
|
browserWindow.setAlwaysOnTop(false);
|
||||||
}
|
}
|
||||||
@@ -100,26 +108,19 @@ app
|
|||||||
browserWindow.setSize(
|
browserWindow.setSize(
|
||||||
currentDimensions[0] + req.dimensions.width,
|
currentDimensions[0] + req.dimensions.width,
|
||||||
currentDimensions[1] + req.dimensions.height,
|
currentDimensions[1] + req.dimensions.height,
|
||||||
false
|
false,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
browserWindow.setSize(
|
browserWindow.setSize(req.dimensions.width, req.dimensions.height, false);
|
||||||
req.dimensions.width,
|
|
||||||
req.dimensions.height,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.setPosition) {
|
if (req.setPosition) {
|
||||||
if (req.setPosition === "center") {
|
if (req.setPosition === 'center') {
|
||||||
browserWindow.center();
|
browserWindow.center();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.setPosition === "topRight") {
|
if (req.setPosition === 'topRight') {
|
||||||
browserWindow.setPosition(
|
browserWindow.setPosition(display.bounds.width - req.dimensions.width, 0);
|
||||||
display.bounds.width - req.dimensions.width,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -130,7 +131,7 @@ app
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
// on blur, show overlay, and tell app to trigger overlay mode
|
// on blur, show overlay, and tell app to trigger overlay mode
|
||||||
browserWindow.on("blur", () => {
|
browserWindow.on('blur', () => {
|
||||||
browserWindow.webContents.send(Channels.ON_WINDOW_BLUR);
|
browserWindow.webContents.send(Channels.ON_WINDOW_BLUR);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -138,13 +139,13 @@ app
|
|||||||
// Quit when all windows are closed, except on macOS. There, it's common
|
// Quit when all windows are closed, except on macOS. There, it's common
|
||||||
// for applications and their menu bar to stay active until the user quits
|
// for applications and their menu bar to stay active until the user quits
|
||||||
// explicitly with Cmd + Q.
|
// explicitly with Cmd + Q.
|
||||||
app.on("window-all-closed", () => {
|
app.on('window-all-closed', () => {
|
||||||
if (process.platform !== "darwin") {
|
if (process.platform !== 'darwin') {
|
||||||
app.quit();
|
app.quit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on("activate", () => {
|
app.on('activate', () => {
|
||||||
// On OS X it's common to re-create a window in the app when the
|
// On OS X it's common to re-create a window in the app when the
|
||||||
// dock icon is clicked and there are no other windows open.
|
// dock icon is clicked and there are no other windows open.
|
||||||
if (BrowserWindow.getAllWindows().length === 0) {
|
if (BrowserWindow.getAllWindows().length === 0) {
|
||||||
@@ -158,17 +159,17 @@ app.on("activate", () => {
|
|||||||
// open deep links from nirvana web app
|
// open deep links from nirvana web app
|
||||||
if (process.defaultApp) {
|
if (process.defaultApp) {
|
||||||
if (process.argv.length >= 2) {
|
if (process.argv.length >= 2) {
|
||||||
app.setAsDefaultProtocolClient("nirvana-desktop", process.execPath, [
|
app.setAsDefaultProtocolClient('nirvana-desktop', process.execPath, [
|
||||||
path.resolve(process.argv[1]),
|
path.resolve(process.argv[1]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
app.setAsDefaultProtocolClient("nirvana-desktop");
|
app.setAsDefaultProtocolClient('nirvana-desktop');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the protocol. In this case, we choose to show an Error Box.
|
// Handle the protocol. In this case, we choose to show an Error Box.
|
||||||
app.on("open-url", (event, url) => {
|
app.on('open-url', (event, url) => {
|
||||||
console.log("welcome back, you arrived from: ", url);
|
console.log('welcome back, you arrived from: ', url);
|
||||||
|
|
||||||
browserWindow.focus();
|
browserWindow.focus();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,8 +28,6 @@
|
|||||||
|
|
||||||
// import './index.css';
|
// import './index.css';
|
||||||
|
|
||||||
import "./app";
|
import './electronApp';
|
||||||
|
|
||||||
console.log(
|
console.log('👋 This message is being logged by "renderer.js", included via webpack');
|
||||||
'👋 This message is being logged by "renderer.js", included via webpack'
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"module": "commonjs",
|
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"noImplicitAny": false,
|
"allowSyntheticDefaultImports": true,
|
||||||
"sourceMap": true,
|
"strict": true,
|
||||||
"baseUrl": ".",
|
"forceConsistentCasingInFileNames": true,
|
||||||
"outDir": "dist",
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"paths": {
|
"isolatedModules": true,
|
||||||
"*": ["node_modules/*"]
|
"noEmit": true,
|
||||||
},
|
|
||||||
"jsx": "react-jsx"
|
"jsx": "react-jsx"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"]
|
"include": ["src/"]
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -1,12 +1,12 @@
|
|||||||
import { useAuthCheck, useServerCheck } from "../../controller/index";
|
import { useAuthCheck, useServerCheck } from '../../../src/controller/index';
|
||||||
|
|
||||||
import { $jwtToken } from "../../controller/recoil";
|
import { $jwtToken } from '../../../src/controller/recoil';
|
||||||
import Login from "../../pages/Login";
|
import Login from '../../Login';
|
||||||
import NirvanaApi from "../../controller/nirvanaApi";
|
import NirvanaApi from '../../../src/controller/nirvanaApi';
|
||||||
import { STORE_ITEMS } from "../../electron/constants";
|
import { STORE_ITEMS } from '../../../src/electron/constants';
|
||||||
import SkeletonLoader from "../loading/skeleton";
|
import SkeletonLoader from '../loading/skeleton';
|
||||||
import { useEffect } from "react";
|
import { useEffect } from 'react';
|
||||||
import { useRecoilState } from "recoil";
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
export default function ProtectedRoute({
|
export default function ProtectedRoute({
|
||||||
children,
|
children,
|
||||||
@@ -47,7 +47,7 @@ export default function ProtectedRoute({
|
|||||||
// }, []);
|
// }, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("change in jwt token", jwtToken);
|
console.log('change in jwt token', jwtToken);
|
||||||
|
|
||||||
if (jwtToken) {
|
if (jwtToken) {
|
||||||
window.electronAPI.store.set(STORE_ITEMS.AUTH_SESSION_JWT, jwtToken);
|
window.electronAPI.store.set(STORE_ITEMS.AUTH_SESSION_JWT, jwtToken);
|
||||||
@@ -64,7 +64,7 @@ export default function ProtectedRoute({
|
|||||||
// first time loading
|
// first time loading
|
||||||
if (serverLoading)
|
if (serverLoading)
|
||||||
return (
|
return (
|
||||||
<span className="text-md text-gray-400 flex items-center justify-center flex-1 text-center p-5 h-screen">
|
<span className='text-md text-gray-400 flex items-center justify-center flex-1 text-center p-5 h-screen'>
|
||||||
Sorry...this is our bad. Our servers are loading. We are trying our best
|
Sorry...this is our bad. Our servers are loading. We are trying our best
|
||||||
to back up and running! :) <br /> Please contact me for urgent concerns:
|
to back up and running! :) <br /> Please contact me for urgent concerns:
|
||||||
arjunpatel@berkeley.edu
|
arjunpatel@berkeley.edu
|
||||||
@@ -73,7 +73,7 @@ export default function ProtectedRoute({
|
|||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="container h-screen w-screen flex flex-col justify-center mx-10">
|
<div className='container h-screen w-screen flex flex-col justify-center mx-10'>
|
||||||
<SkeletonLoader />
|
<SkeletonLoader />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
+48
-48
@@ -1,4 +1,4 @@
|
|||||||
import { FiActivity, FiSun } from "react-icons/fi";
|
import { FiActivity, FiSun } from 'react-icons/fi';
|
||||||
import {
|
import {
|
||||||
RtcAnswerRequest,
|
RtcAnswerRequest,
|
||||||
RtcCallRequest,
|
RtcCallRequest,
|
||||||
@@ -6,21 +6,21 @@ import {
|
|||||||
RtcReceiveAnswerResponse,
|
RtcReceiveAnswerResponse,
|
||||||
ServerResponseChannels,
|
ServerResponseChannels,
|
||||||
SomeoneUntunedFromLineResponse,
|
SomeoneUntunedFromLineResponse,
|
||||||
} from "@nirvana/core/sockets/channels";
|
} from '@nirvana/core/sockets/channels';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
|
||||||
import { $selectedLineId } from "../../../controller/recoil";
|
import { $selectedLineId } from '../../../controller/recoil';
|
||||||
import { Avatar } from "antd";
|
import { Avatar } from 'antd';
|
||||||
import LineIcon from "../lineIcon";
|
import LineIcon from '../lineIcon';
|
||||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
import { LineMemberState } from '@nirvana/core/models/line.model';
|
||||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
import MasterLineData from '@nirvana/core/models/masterLineData.model';
|
||||||
import Peer from "simple-peer";
|
import Peer from 'simple-peer';
|
||||||
import { ServerRequestChannels } from "../../../../../core/sockets/channels";
|
import { ServerRequestChannels } from '@nirvana/core/sockets/channels';
|
||||||
import moment from "moment";
|
import moment from 'moment';
|
||||||
import toast from "react-hot-toast";
|
import toast from 'react-hot-toast';
|
||||||
import { useGetUserDetails } from "../../../controller/index";
|
import { useGetUserDetails } from '../../../controller/index';
|
||||||
import { useLineDataProvider } from "../../../controller/lineDataProvider";
|
import { useLineDataProvider } from '../../../controller/lineDataProvider';
|
||||||
import { useRecoilState } from "recoil";
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
// todo: send a much more comprehensive master line object? or just add properties to the
|
// todo: send a much more comprehensive master line object? or just add properties to the
|
||||||
// masterLineData object so that we don't have different models to maintain between client and server
|
// masterLineData object so that we don't have different models to maintain between client and server
|
||||||
@@ -36,9 +36,9 @@ export default function LineRow({
|
|||||||
const { data: userData } = useGetUserDetails();
|
const { data: userData } = useGetUserDetails();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.warn("mounting linerow");
|
console.warn('mounting linerow');
|
||||||
|
|
||||||
return () => console.warn("UNMOUNTING line row");
|
return () => console.warn('UNMOUNTING line row');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// take the source of truth list of memeberIds tuned in, and see if I'm in it
|
// take the source of truth list of memeberIds tuned in, and see if I'm in it
|
||||||
@@ -54,19 +54,19 @@ export default function LineRow({
|
|||||||
const renderActivityIcon = useMemo(() => {
|
const renderActivityIcon = useMemo(() => {
|
||||||
// if there is someone or me broadcasting here
|
// if there is someone or me broadcasting here
|
||||||
if (masterLineData.currentBroadcastersUserIds?.length > 0)
|
if (masterLineData.currentBroadcastersUserIds?.length > 0)
|
||||||
return <FiSun className="text-teal-500 animate-pulse" />;
|
return <FiSun className='text-teal-500 animate-pulse' />;
|
||||||
|
|
||||||
if (isUserTunedIn)
|
if (isUserTunedIn)
|
||||||
return <FiActivity className="text-black animate-pulse" />;
|
return <FiActivity className='text-black animate-pulse' />;
|
||||||
|
|
||||||
// if there is new activity blocks for me
|
// if there is new activity blocks for me
|
||||||
if (masterLineData.currentUserMember.lastVisitDate)
|
if (masterLineData.currentUserMember.lastVisitDate)
|
||||||
return (
|
return (
|
||||||
<span className="h-2 w-2 rounded-full bg-slate-800 animate-pulse"></span>
|
<span className='h-2 w-2 rounded-full bg-slate-800 animate-pulse'></span>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="h-2 w-2 rounded-full bg-white animate-pulse"></span>
|
<span className='h-2 w-2 rounded-full bg-white animate-pulse'></span>
|
||||||
);
|
);
|
||||||
}, [masterLineData, isUserTunedIn]);
|
}, [masterLineData, isUserTunedIn]);
|
||||||
|
|
||||||
@@ -77,22 +77,22 @@ export default function LineRow({
|
|||||||
<Avatar.Group
|
<Avatar.Group
|
||||||
key={`lineRowRightActivityGroup-${masterLineData.lineDetails._id.toString()}`}
|
key={`lineRowRightActivityGroup-${masterLineData.lineDetails._id.toString()}`}
|
||||||
maxCount={2}
|
maxCount={2}
|
||||||
maxPopoverTrigger="click"
|
maxPopoverTrigger='click'
|
||||||
size="small"
|
size='small'
|
||||||
maxStyle={{
|
maxStyle={{
|
||||||
color: "#f56a00",
|
color: '#f56a00',
|
||||||
backgroundColor: "#fde3cf",
|
backgroundColor: '#fde3cf',
|
||||||
cursor: "pointer",
|
cursor: 'pointer',
|
||||||
borderRadius: "0",
|
borderRadius: '0',
|
||||||
}}
|
}}
|
||||||
className="shadow-lg"
|
className='shadow-lg'
|
||||||
>
|
>
|
||||||
{masterLineData.otherUserObjects?.map((otherUser, index) => (
|
{masterLineData.otherUserObjects?.map((otherUser, index) => (
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`lineListActivitySection-${otherUser._id.toString()}-${index}`}
|
key={`lineListActivitySection-${otherUser._id.toString()}-${index}`}
|
||||||
src={otherUser.picture ?? ""}
|
src={otherUser.picture ?? ''}
|
||||||
shape="square"
|
shape='square'
|
||||||
size={"small"}
|
size={'small'}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Avatar.Group>
|
</Avatar.Group>
|
||||||
@@ -137,11 +137,11 @@ export default function LineRow({
|
|||||||
className={`flex flex-row items-center justify-start gap-2 p-2 px-4 h-14 hover:bg-gray-200 cursor-pointer transition-all
|
className={`flex flex-row items-center justify-start gap-2 p-2 px-4 h-14 hover:bg-gray-200 cursor-pointer transition-all
|
||||||
last:border-b-0 border-b border-b-gray-200 relative z-50 rounded ${
|
last:border-b-0 border-b border-b-gray-200 relative z-50 rounded ${
|
||||||
selectedLineId === masterLineData.lineDetails._id.toString() &&
|
selectedLineId === masterLineData.lineDetails._id.toString() &&
|
||||||
"bg-gray-200 scale-110 shadow-2xl translate-x-3"
|
'bg-gray-200 scale-110 shadow-2xl translate-x-3'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{/* status dot */}
|
{/* status dot */}
|
||||||
<div className="flex-shrink-0 h-4 w-4">{renderActivityIcon}</div>
|
<div className='flex-shrink-0 h-4 w-4'>{renderActivityIcon}</div>
|
||||||
|
|
||||||
{profilePictures && (
|
{profilePictures && (
|
||||||
<LineIcon grayscale={!isUserTunedIn} sourceImages={profilePictures} />
|
<LineIcon grayscale={!isUserTunedIn} sourceImages={profilePictures} />
|
||||||
@@ -150,15 +150,15 @@ export default function LineRow({
|
|||||||
<h2
|
<h2
|
||||||
className={`text-inherit text-md max-w-[220px] truncate text-slate-800 ${
|
className={`text-inherit text-md max-w-[220px] truncate text-slate-800 ${
|
||||||
masterLineData.currentUserMember.lastVisitDate
|
masterLineData.currentUserMember.lastVisitDate
|
||||||
? "font-semibold"
|
? 'font-semibold'
|
||||||
: ""
|
: ''
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{masterLineData.lineDetails.name ||
|
{masterLineData.lineDetails.name ||
|
||||||
masterLineData.otherUserObjects[0].givenName}
|
masterLineData.otherUserObjects[0].givenName}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div className="ml-auto flex-shrink-0">{renderRightActivity}</div>
|
<div className='ml-auto flex-shrink-0'>{renderRightActivity}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* mounts and unmounts based on if in the room or now */}
|
{/* mounts and unmounts based on if in the room or now */}
|
||||||
@@ -249,7 +249,7 @@ function StreamRoom({
|
|||||||
localPeerConnections[otherTunedInUserId] = localPeerInitiator;
|
localPeerConnections[otherTunedInUserId] = localPeerInitiator;
|
||||||
|
|
||||||
// notify each one with specific signal
|
// notify each one with specific signal
|
||||||
localPeerInitiator.on("signal", (signal) => {
|
localPeerInitiator.on('signal', (signal) => {
|
||||||
$ws.emit(
|
$ws.emit(
|
||||||
ServerRequestChannels.RTC_CALL_REQUEST,
|
ServerRequestChannels.RTC_CALL_REQUEST,
|
||||||
new RtcCallRequest(lineId, otherTunedInUserId, signal)
|
new RtcCallRequest(lineId, otherTunedInUserId, signal)
|
||||||
@@ -266,7 +266,7 @@ function StreamRoom({
|
|||||||
// create a local peer connection for this new user
|
// create a local peer connection for this new user
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"ooo newbie joined room, I guess I will accept it and send him my signal"
|
'ooo newbie joined room, I guess I will accept it and send him my signal'
|
||||||
);
|
);
|
||||||
console.log(res);
|
console.log(res);
|
||||||
|
|
||||||
@@ -276,9 +276,9 @@ function StreamRoom({
|
|||||||
stream: userStream, // add in my own stream that I got before
|
stream: userStream, // add in my own stream that I got before
|
||||||
});
|
});
|
||||||
|
|
||||||
peerForMeAndNewbie.on("signal", (signal) => {
|
peerForMeAndNewbie.on('signal', (signal) => {
|
||||||
console.log(
|
console.log(
|
||||||
"as the answerer, I am going to send back my signal so that the newbie can update his local peer for me"
|
'as the answerer, I am going to send back my signal so that the newbie can update his local peer for me'
|
||||||
);
|
);
|
||||||
$ws.emit(
|
$ws.emit(
|
||||||
ServerRequestChannels.RTC_ANSWER_REQUEST,
|
ServerRequestChannels.RTC_ANSWER_REQUEST,
|
||||||
@@ -315,7 +315,7 @@ function StreamRoom({
|
|||||||
const newUserPeerMap = { ...previousUserPeersMap };
|
const newUserPeerMap = { ...previousUserPeersMap };
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"here is the current peers map",
|
'here is the current peers map',
|
||||||
previousUserPeersMap
|
previousUserPeersMap
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -325,7 +325,7 @@ function StreamRoom({
|
|||||||
peerForAnswerer.signal(res.simplePeerSignal);
|
peerForAnswerer.signal(res.simplePeerSignal);
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
"could not find the peer we created before for this master"
|
'could not find the peer we created before for this master'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +347,7 @@ function StreamRoom({
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
|
|
||||||
toast.error(
|
toast.error(
|
||||||
"Make sure that you have permissions enabled and microphone connected"
|
'Make sure that you have permissions enabled and microphone connected'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,7 @@ function StreamRoom({
|
|||||||
useEffect(() => {}, [tunedInUsers]);
|
useEffect(() => {}, [tunedInUsers]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("keeping an eye on user peers map");
|
console.log('keeping an eye on user peers map');
|
||||||
console.log(userPeers);
|
console.log(userPeers);
|
||||||
}, [userPeers]);
|
}, [userPeers]);
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ function StreamRoom({
|
|||||||
|
|
||||||
// TODO: p1...when the peer map user count > tunedIn.length, then we get rid of the right person from list cuzz they have officially left or disconnected
|
// TODO: p1...when the peer map user count > tunedIn.length, then we get rid of the right person from list cuzz they have officially left or disconnected
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("change in tuned in users in the streaming room!!!");
|
console.log('change in tuned in users in the streaming room!!!');
|
||||||
|
|
||||||
setUserPeers((prevUserPeersMap) => {
|
setUserPeers((prevUserPeersMap) => {
|
||||||
// go through the userIds here
|
// go through the userIds here
|
||||||
@@ -389,7 +389,7 @@ function StreamRoom({
|
|||||||
otherUserIdsPeers.forEach((otherUserId) => {
|
otherUserIdsPeers.forEach((otherUserId) => {
|
||||||
// problem if we are trying to show stream of someone who is not tuned in
|
// problem if we are trying to show stream of someone who is not tuned in
|
||||||
if (!tunedInUsers.includes(otherUserId)) {
|
if (!tunedInUsers.includes(otherUserId)) {
|
||||||
console.log("user left with id:", otherUserId);
|
console.log('user left with id:', otherUserId);
|
||||||
const disconnectedLocalPeer = newMap[otherUserId];
|
const disconnectedLocalPeer = newMap[otherUserId];
|
||||||
|
|
||||||
if (disconnectedLocalPeer) {
|
if (disconnectedLocalPeer) {
|
||||||
@@ -436,9 +436,9 @@ function PeerStreamRenderer({
|
|||||||
const streamRef = useRef<HTMLVideoElement>(null);
|
const streamRef = useRef<HTMLVideoElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
peer.on("stream", (remotePeerStream: MediaStream) => {
|
peer.on('stream', (remotePeerStream: MediaStream) => {
|
||||||
console.log(
|
console.log(
|
||||||
"stream coming in from remote peer...BUT, only going to show once they broadcast"
|
'stream coming in from remote peer...BUT, only going to show once they broadcast'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (streamRef?.current) streamRef.current.srcObject = remotePeerStream;
|
if (streamRef?.current) streamRef.current.srcObject = remotePeerStream;
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import NirvanaApi, { ApiCalls } from "./nirvanaApi";
|
import NirvanaApi, { ApiCalls } from './nirvanaApi';
|
||||||
import { useMutation, useQuery } from "react-query";
|
import { useMutation, useQuery } from 'react-query';
|
||||||
|
|
||||||
import { $jwtToken } from "./recoil";
|
import { $jwtToken } from './recoil';
|
||||||
import { queryClient } from "../pages/nirvanaApp";
|
import { queryClient } from '../../legacy/nirvanaApp';
|
||||||
import { useRecoilValue } from "recoil";
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
// ====== QUERIES
|
// ====== QUERIES
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ import { useRecoilValue } from "recoil";
|
|||||||
* ensure that the server is up
|
* ensure that the server is up
|
||||||
*/
|
*/
|
||||||
export function useServerCheck() {
|
export function useServerCheck() {
|
||||||
return useQuery("SERVER_CHECK", ApiCalls.serverCheck, {
|
return useQuery('SERVER_CHECK', ApiCalls.serverCheck, {
|
||||||
retry: true,
|
retry: true,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ export function useServerCheck() {
|
|||||||
export function useAuthCheck(enabled: boolean = true) {
|
export function useAuthCheck(enabled: boolean = true) {
|
||||||
const jwtToken = useRecoilValue($jwtToken);
|
const jwtToken = useRecoilValue($jwtToken);
|
||||||
|
|
||||||
return useQuery("AUTH_CHECK", ApiCalls.authCheck, {
|
return useQuery('AUTH_CHECK', ApiCalls.authCheck, {
|
||||||
retry: false,
|
retry: false,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
|
|
||||||
@@ -32,11 +32,11 @@ export function useAuthCheck(enabled: boolean = true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useLogin() {
|
export function useLogin() {
|
||||||
return useMutation("LOGIN", ApiCalls.login, {});
|
return useMutation('LOGIN', ApiCalls.login, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useGetUserDetails() {
|
export function useGetUserDetails() {
|
||||||
return useQuery("USER_DETAILS", ApiCalls.getUserDetails, {
|
return useQuery('USER_DETAILS', ApiCalls.getUserDetails, {
|
||||||
retry: false,
|
retry: false,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
@@ -46,7 +46,7 @@ export function useGetUserDetails() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useUserSearch(searchQuery: string) {
|
export function useUserSearch(searchQuery: string) {
|
||||||
return useQuery("USER_SEARCH", () => ApiCalls.userSearch(searchQuery), {
|
return useQuery('USER_SEARCH', () => ApiCalls.userSearch(searchQuery), {
|
||||||
enabled: searchQuery ? true : false,
|
enabled: searchQuery ? true : false,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
});
|
});
|
||||||
@@ -57,7 +57,7 @@ export function useUserLines() {
|
|||||||
// todo: base/source of truth for getting all of the lines for the user
|
// todo: base/source of truth for getting all of the lines for the user
|
||||||
// merge with sockets + audio clip data + master data + convomember data
|
// merge with sockets + audio clip data + master data + convomember data
|
||||||
|
|
||||||
return useQuery("USER_LINES", ApiCalls.getUserLines, {
|
return useQuery('USER_LINES', ApiCalls.getUserLines, {
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
refetchIntervalInBackground: false,
|
refetchIntervalInBackground: false,
|
||||||
staleTime: Infinity,
|
staleTime: Infinity,
|
||||||
@@ -72,7 +72,7 @@ export function useGetDmByUserId() {
|
|||||||
export function useCreateLine() {
|
export function useCreateLine() {
|
||||||
return useMutation(ApiCalls.createLine, {
|
return useMutation(ApiCalls.createLine, {
|
||||||
onSuccess: (res, req) => {
|
onSuccess: (res, req) => {
|
||||||
queryClient.invalidateQueries(["USER_LINES"]);
|
queryClient.invalidateQueries(['USER_LINES']);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+27
-27
@@ -1,4 +1,4 @@
|
|||||||
import { $desktopMode, $jwtToken, $selectedLineId } from "./recoil";
|
import { $desktopMode, $jwtToken, $selectedLineId } from './recoil';
|
||||||
import {
|
import {
|
||||||
ConnectToLineRequest,
|
ConnectToLineRequest,
|
||||||
ServerRequestChannels,
|
ServerRequestChannels,
|
||||||
@@ -12,18 +12,18 @@ import {
|
|||||||
UntuneFromLineRequest,
|
UntuneFromLineRequest,
|
||||||
UserStartedBroadcastingResponse,
|
UserStartedBroadcastingResponse,
|
||||||
UserStoppedBroadcastingResponse,
|
UserStoppedBroadcastingResponse,
|
||||||
} from "@nirvana/core/sockets/channels";
|
} from '@nirvana/core/sockets/channels';
|
||||||
import React, { useContext, useState } from "react";
|
import React, { useContext, useState } from 'react';
|
||||||
import { Socket, io } from "socket.io-client";
|
import { Socket, io } from 'socket.io-client';
|
||||||
import { useCallback, useEffect } from "react";
|
import { useCallback, useEffect } from 'react';
|
||||||
import { useRecoilValue, useSetRecoilState } from "recoil";
|
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
import { LineMemberState } from '@nirvana/core/models/line.model';
|
||||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
import MasterLineData from '@nirvana/core/models/masterLineData.model';
|
||||||
import { User } from "@nirvana/core/models";
|
import { User } from '@nirvana/core/models';
|
||||||
import { queryClient } from "../pages/nirvanaApp";
|
import { queryClient } from '../../legacy/nirvanaApp';
|
||||||
import toast from "react-hot-toast";
|
import toast from 'react-hot-toast';
|
||||||
import { useUserLines } from "./index";
|
import { useUserLines } from './index';
|
||||||
|
|
||||||
let $ws: Socket;
|
let $ws: Socket;
|
||||||
|
|
||||||
@@ -44,19 +44,19 @@ function useSocketHandler(linesData: MasterLineData[]) {
|
|||||||
// https://socket.io/docs/v4/client-options/#reconnection
|
// https://socket.io/docs/v4/client-options/#reconnection
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
$ws = io("http://localhost:5000", {
|
$ws = io('http://localhost:5000', {
|
||||||
query: { token: jwtToken },
|
query: { token: jwtToken },
|
||||||
transports: ["websocket"],
|
transports: ['websocket'],
|
||||||
upgrade: false,
|
upgrade: false,
|
||||||
forceNew: true,
|
forceNew: true,
|
||||||
reconnection: false, // ! TESTING THE PROBLEM WITH RECONNECTION CLIENT LISTENERS NOT ACTIVATING
|
reconnection: false, // ! TESTING THE PROBLEM WITH RECONNECTION CLIENT LISTENERS NOT ACTIVATING
|
||||||
});
|
});
|
||||||
|
|
||||||
$ws.on("connect", () => {
|
$ws.on('connect', () => {
|
||||||
console.log(
|
console.log(
|
||||||
"SOCKETS | CLIENT CONNECTED in socket handler, setting up client side listeners for requests"
|
'SOCKETS | CLIENT CONNECTED in socket handler, setting up client side listeners for requests'
|
||||||
);
|
);
|
||||||
toast.success("you are connected");
|
toast.success('you are connected');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initiate listeners
|
* initiate listeners
|
||||||
@@ -160,7 +160,7 @@ function useSocketHandler(linesData: MasterLineData[]) {
|
|||||||
$ws.on(
|
$ws.on(
|
||||||
ServerResponseChannels.SOMEONE_STARTED_BROADCASTING,
|
ServerResponseChannels.SOMEONE_STARTED_BROADCASTING,
|
||||||
(res: UserStartedBroadcastingResponse) => {
|
(res: UserStartedBroadcastingResponse) => {
|
||||||
console.log("someone is starting to broadcast");
|
console.log('someone is starting to broadcast');
|
||||||
|
|
||||||
setLinesMap((prevLinesMap) => {
|
setLinesMap((prevLinesMap) => {
|
||||||
const newMap = { ...prevLinesMap };
|
const newMap = { ...prevLinesMap };
|
||||||
@@ -198,28 +198,28 @@ function useSocketHandler(linesData: MasterLineData[]) {
|
|||||||
|
|
||||||
// on disconnections, just switch it to flow state?
|
// on disconnections, just switch it to flow state?
|
||||||
// what if there was another problem?
|
// what if there was another problem?
|
||||||
$ws.io.on("close", () => {
|
$ws.io.on('close', () => {
|
||||||
console.error(
|
console.error(
|
||||||
"SOCKET | there was a problem with your app...connection closed likely due to idling or manual disconnect"
|
'SOCKET | there was a problem with your app...connection closed likely due to idling or manual disconnect'
|
||||||
);
|
);
|
||||||
// todo: figure out the right thing based on the situation whether it's a problem or user unplugs
|
// todo: figure out the right thing based on the situation whether it's a problem or user unplugs
|
||||||
// toast(
|
// toast(
|
||||||
// "Disconnected due to idling or some other issue. Please reconnect or refresh to fix the problem."
|
// "Disconnected due to idling or some other issue. Please reconnect or refresh to fix the problem."
|
||||||
// );
|
// );
|
||||||
|
|
||||||
toast("unplugging");
|
toast('unplugging');
|
||||||
setDesktopMode("flowState");
|
setDesktopMode('flowState');
|
||||||
});
|
});
|
||||||
|
|
||||||
// client-side errors
|
// client-side errors
|
||||||
$ws.on("connect_error", (err) => {
|
$ws.on('connect_error', (err) => {
|
||||||
console.error(`SOCKETS | ${err.message}`); // prints the message associated with the error
|
console.error(`SOCKETS | ${err.message}`); // prints the message associated with the error
|
||||||
toast.error("sorry...this is our bad...please refresh with cmd + r");
|
toast.error('sorry...this is our bad...please refresh with cmd + r');
|
||||||
|
|
||||||
// force refetch of server status as well as these generally go hand in hand
|
// force refetch of server status as well as these generally go hand in hand
|
||||||
|
|
||||||
// this should overall remount this component currently which is what we want for new data
|
// this should overall remount this component currently which is what we want for new data
|
||||||
queryClient.invalidateQueries("SERVER_CHECK");
|
queryClient.invalidateQueries('SERVER_CHECK');
|
||||||
});
|
});
|
||||||
|
|
||||||
// on unmounting this component, we want to disconnect
|
// on unmounting this component, we want to disconnect
|
||||||
@@ -412,9 +412,9 @@ export function LineDataProvider({ children }) {
|
|||||||
// and then disconnect
|
// and then disconnect
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
if (desktopMode === "flowState" && $ws) {
|
if (desktopMode === 'flowState' && $ws) {
|
||||||
console.log(
|
console.log(
|
||||||
"SOCKETS | telling all of my connected rooms that I am unplugging"
|
'SOCKETS | telling all of my connected rooms that I am unplugging'
|
||||||
);
|
);
|
||||||
|
|
||||||
$ws.emit(ServerRequestChannels.GOING_INTO_FLOW_STATE);
|
$ws.emit(ServerRequestChannels.GOING_INTO_FLOW_STATE);
|
||||||
+15
-15
@@ -1,58 +1,58 @@
|
|||||||
import { atom } from "recoil";
|
import { atom } from 'recoil';
|
||||||
|
|
||||||
export const $searchQuery = atom<string>({
|
export const $searchQuery = atom<string>({
|
||||||
key: "SEARCH_QUERY",
|
key: 'SEARCH_QUERY',
|
||||||
default: "",
|
default: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const $jwtToken = atom<string>({
|
export const $jwtToken = atom<string>({
|
||||||
key: "JWT_TOKEN",
|
key: 'JWT_TOKEN',
|
||||||
default: null,
|
default: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
// conversation id
|
// conversation id
|
||||||
export const $selectedConversation = atom<string>({
|
export const $selectedConversation = atom<string>({
|
||||||
key: "SELECTED_CONVERSATION",
|
key: 'SELECTED_CONVERSATION',
|
||||||
default: null,
|
default: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
// new convo page trigger
|
// new convo page trigger
|
||||||
export const $newConvoPage = atom<boolean>({
|
export const $newConvoPage = atom<boolean>({
|
||||||
key: "NEW_CONVO_PAGE",
|
key: 'NEW_CONVO_PAGE',
|
||||||
default: false,
|
default: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// number of active lines
|
// number of active lines
|
||||||
export const $numberActiveLines = atom<number>({
|
export const $numberActiveLines = atom<number>({
|
||||||
key: "NUMBER_ACTIVE_LINES",
|
key: 'NUMBER_ACTIVE_LINES',
|
||||||
default: 0,
|
default: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
// max number of active streams
|
// max number of active streams
|
||||||
export const $maxNumberActiveStreams = atom<number>({
|
export const $maxNumberActiveStreams = atom<number>({
|
||||||
key: "MAX_NUMBER_ACTIVE_STREAMS",
|
key: 'MAX_NUMBER_ACTIVE_STREAMS',
|
||||||
default: 0,
|
default: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
|
|
||||||
type DesktopMode = "flowState" | "overlayOnly" | "terminal";
|
type DesktopMode = 'flowState' | 'overlayOnly' | 'terminal';
|
||||||
|
|
||||||
export const $desktopMode = atom<DesktopMode>({
|
export const $desktopMode = atom<DesktopMode>({
|
||||||
key: "DESKTOP_MODE",
|
key: 'DESKTOP_MODE',
|
||||||
default: "terminal",
|
default: 'terminal',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const $selectedLineId = atom<string>({
|
export const $selectedLineId = atom<string>({
|
||||||
key: "SELECTED_LINE_ID",
|
key: 'SELECTED_LINE_ID',
|
||||||
default: null,
|
default: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
interface MediaSettings {
|
interface MediaSettings {
|
||||||
mode: "audio" | "video" | "screen";
|
mode: 'audio' | 'video' | 'screen';
|
||||||
isMuted: boolean;
|
isMuted: boolean;
|
||||||
}
|
}
|
||||||
export const $mediaSettings = atom<MediaSettings>({
|
export const $mediaSettings = atom<MediaSettings>({
|
||||||
key: "MEDIA_SETTINGS",
|
key: 'MEDIA_SETTINGS',
|
||||||
default: { isMuted: false, mode: "audio" },
|
default: { isMuted: false, mode: 'audio' },
|
||||||
});
|
});
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
import { LogoType } from '@nirvana/components/logo/full';
|
||||||
import {
|
import {
|
||||||
$desktopMode,
|
$desktopMode,
|
||||||
$maxNumberActiveStreams,
|
$maxNumberActiveStreams,
|
||||||
$numberActiveLines,
|
$numberActiveLines,
|
||||||
$selectedLineId,
|
$selectedLineId,
|
||||||
} from "../../controller/recoil";
|
} from '../../src/controller/recoil';
|
||||||
import Channels, {
|
import Channels, {
|
||||||
DEFAULT_APP_PRESET,
|
DEFAULT_APP_PRESET,
|
||||||
Dimensions,
|
Dimensions,
|
||||||
} from "../../electron/constants";
|
} from '../../src/electron/constants';
|
||||||
import { useCallback, useEffect, useState } from "react";
|
|
||||||
import { useRecoilState, useRecoilValue } from "recoil";
|
|
||||||
|
|
||||||
import FullMottoLogo from "../../../../components/logo/fullMotto";
|
import FullMottoLogo from '@nirvana/components/logo/fullMotto';
|
||||||
import { LineDataProvider } from "../../controller/lineDataProvider";
|
import { LineDataProvider } from '../../src/controller/lineDataProvider';
|
||||||
import { LogoType } from "@nirvana/components/logo/full";
|
import NirvanaHeader from '../components/header/index';
|
||||||
import NirvanaHeader from "../../components/header/index";
|
import NirvanaTerminal from '../terminal';
|
||||||
import NirvanaTerminal from "../terminal";
|
|
||||||
|
|
||||||
export default function NirvanaRouter() {
|
export default function NirvanaRouter() {
|
||||||
const [selectedLineId, setSelectedLineId] = useRecoilState($selectedLineId);
|
const [selectedLineId, setSelectedLineId] = useRecoilState($selectedLineId);
|
||||||
@@ -27,16 +27,16 @@ export default function NirvanaRouter() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// add dimensions if it's not overlay only mode
|
// add dimensions if it's not overlay only mode
|
||||||
let finalDimensions: Dimensions = { height: 0, width: 0 };
|
let finalDimensions: Dimensions = { height: 0, width: 0 };
|
||||||
let finalPosition: "center" | "topRight";
|
let finalPosition: 'center' | 'topRight';
|
||||||
|
|
||||||
const setAlwaysOnTop = desktopMode === "overlayOnly";
|
const setAlwaysOnTop = desktopMode === 'overlayOnly';
|
||||||
|
|
||||||
// go hunting for which dimensions to have
|
// go hunting for which dimensions to have
|
||||||
if (desktopMode === "terminal" || desktopMode == "flowState") {
|
if (desktopMode === 'terminal' || desktopMode == 'flowState') {
|
||||||
finalDimensions = DEFAULT_APP_PRESET;
|
finalDimensions = DEFAULT_APP_PRESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desktopMode === "overlayOnly") {
|
if (desktopMode === 'overlayOnly') {
|
||||||
finalDimensions = {
|
finalDimensions = {
|
||||||
height: 68 + numberOfOverlayRows * 200,
|
height: 68 + numberOfOverlayRows * 200,
|
||||||
width: 360 + 360 * numberOfOverlayColumns,
|
width: 360 + 360 * numberOfOverlayColumns,
|
||||||
@@ -44,7 +44,7 @@ export default function NirvanaRouter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"setting new dimensions",
|
'setting new dimensions',
|
||||||
desktopMode,
|
desktopMode,
|
||||||
numberOfOverlayColumns,
|
numberOfOverlayColumns,
|
||||||
numberOfOverlayRows,
|
numberOfOverlayRows,
|
||||||
@@ -70,7 +70,7 @@ export default function NirvanaRouter() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.electronAPI.on(Channels.ON_WINDOW_BLUR, () => {
|
window.electronAPI.on(Channels.ON_WINDOW_BLUR, () => {
|
||||||
console.log(
|
console.log(
|
||||||
"window blurring now, should be always on top and then ill tell main process to change dimensions"
|
'window blurring now, should be always on top and then ill tell main process to change dimensions'
|
||||||
);
|
);
|
||||||
// TODO: testing mode... uncomment both instructions below
|
// TODO: testing mode... uncomment both instructions below
|
||||||
// setDesktopMode("overlayOnly");
|
// setDesktopMode("overlayOnly");
|
||||||
@@ -82,15 +82,15 @@ export default function NirvanaRouter() {
|
|||||||
}, [setDesktopMode, setSelectedLineId]);
|
}, [setDesktopMode, setSelectedLineId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col flex-1">
|
<div className='flex flex-col flex-1'>
|
||||||
<NirvanaHeader onHeaderFocus={() => setDesktopMode("terminal")} />
|
<NirvanaHeader onHeaderFocus={() => setDesktopMode('terminal')} />
|
||||||
|
|
||||||
{desktopMode === "flowState" && <FlowState />}
|
{desktopMode === 'flowState' && <FlowState />}
|
||||||
|
|
||||||
{/* remount nirvana terminal */}
|
{/* remount nirvana terminal */}
|
||||||
{(desktopMode === "terminal" || desktopMode === "overlayOnly") && (
|
{(desktopMode === 'terminal' || desktopMode === 'overlayOnly') && (
|
||||||
<LineDataProvider>
|
<LineDataProvider>
|
||||||
<NirvanaTerminal overlayOnly={desktopMode === "overlayOnly"} />
|
<NirvanaTerminal overlayOnly={desktopMode === 'overlayOnly'} />
|
||||||
</LineDataProvider>
|
</LineDataProvider>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -109,7 +109,7 @@ function FlowState() {
|
|||||||
const [quote, setQuote] = useState<Quote>(null);
|
const [quote, setQuote] = useState<Quote>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch("https://api.quotable.io/random")
|
fetch('https://api.quotable.io/random')
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((data: Quote) => {
|
.then((data: Quote) => {
|
||||||
console.warn(data);
|
console.warn(data);
|
||||||
@@ -123,19 +123,19 @@ function FlowState() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col flex-1 justify-center items-center relative">
|
<div className='flex flex-col flex-1 justify-center items-center relative'>
|
||||||
{/* <img src="https://source.unsplash.com/random/?nature" /> */}
|
{/* <img src="https://source.unsplash.com/random/?nature" /> */}
|
||||||
<FullMottoLogo
|
<FullMottoLogo
|
||||||
type={LogoType.small}
|
type={LogoType.small}
|
||||||
className={"absolute bottom-2 mx-auto"}
|
className='absolute bottom-2 mx-auto'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{quote && (
|
{quote && (
|
||||||
<span className="flex flex-col justify-center items-center max-w-screen-sm">
|
<span className='flex flex-col justify-center items-center max-w-screen-sm'>
|
||||||
<span className="text-xl text-gray-800 font-semibold text-center">
|
<span className='text-xl text-gray-800 font-semibold text-center'>
|
||||||
"{quote.content}"
|
"{quote.content}"
|
||||||
</span>
|
</span>
|
||||||
<span className="tex-md italic text-gray-400">{quote.author}</span>
|
<span className='tex-md italic text-gray-400'>{quote.author}</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
+100
-100
@@ -1,19 +1,19 @@
|
|||||||
import { $desktopMode, $selectedLineId } from "../../controller/recoil";
|
import { $desktopMode, $selectedLineId } from '../../src/controller/recoil';
|
||||||
import { Avatar, Skeleton, Tooltip } from "antd";
|
import { Avatar, Skeleton, Tooltip } from 'antd';
|
||||||
import { FiActivity, FiHeadphones, FiSettings, FiSun } from "react-icons/fi";
|
import { FiActivity, FiHeadphones, FiSettings, FiSun } from 'react-icons/fi';
|
||||||
import { GlobalHotKeys, KeyMap } from "react-hotkeys";
|
import { GlobalHotKeys, KeyMap } from 'react-hotkeys';
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useGetUserDetails, useUserLines } from "../../controller/index";
|
import { useGetUserDetails, useUserLines } from '../../src/controller/index';
|
||||||
import { useRecoilState, useSetRecoilState } from "recoil";
|
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { FaPlus } from "react-icons/fa";
|
import { FaPlus } from 'react-icons/fa';
|
||||||
import LineIcon from "../../components/lines/lineIcon/index";
|
import LineIcon from '../components/lines/lineIcon/index';
|
||||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
import { LineMemberState } from '@nirvana/core/models/line.model';
|
||||||
import LineRow from "../../components/lines/lineRow.tsx/index";
|
import LineRow from '../components/lines/lineRow.tsx/index';
|
||||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
import MasterLineData from '@nirvana/core/models/masterLineData.model';
|
||||||
import NewLineModal from "./newLine";
|
import NewLineModal from './newLine';
|
||||||
import toast from "react-hot-toast";
|
import toast from 'react-hot-toast';
|
||||||
import { useLineDataProvider } from "../../controller/lineDataProvider";
|
import { useLineDataProvider } from '../../src/controller/lineDataProvider';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket Provider
|
* Socket Provider
|
||||||
@@ -93,7 +93,7 @@ export default function NirvanaTerminal({
|
|||||||
// todo: sort/order based on activity and activity date and currently broadcasting/live
|
// todo: sort/order based on activity and activity date and currently broadcasting/live
|
||||||
|
|
||||||
const handleEscape = useCallback(() => {
|
const handleEscape = useCallback(() => {
|
||||||
console.log("deselecting line");
|
console.log('deselecting line');
|
||||||
|
|
||||||
setSelectedLineId((prevSelectedLineId) => {
|
setSelectedLineId((prevSelectedLineId) => {
|
||||||
// ! only want to untune if it's a temporarily tuned line
|
// ! only want to untune if it's a temporarily tuned line
|
||||||
@@ -128,7 +128,7 @@ export default function NirvanaTerminal({
|
|||||||
(lineId: string, turnToggleOn: boolean) => {
|
(lineId: string, turnToggleOn: boolean) => {
|
||||||
// inhibit if they are trying to turn on and already have 3 toggle tuned
|
// inhibit if they are trying to turn on and already have 3 toggle tuned
|
||||||
if (toggleTunedLines?.length >= 3 && turnToggleOn) {
|
if (toggleTunedLines?.length >= 3 && turnToggleOn) {
|
||||||
toast.error("You cannot toggle more than 3 lines!");
|
toast.error('You cannot toggle more than 3 lines!');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -162,14 +162,14 @@ export default function NirvanaTerminal({
|
|||||||
|
|
||||||
const keyMap: KeyMap = useMemo(
|
const keyMap: KeyMap = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
DESELECT_LINE: "esc",
|
DESELECT_LINE: 'esc',
|
||||||
START_BROADCAST: {
|
START_BROADCAST: {
|
||||||
sequence: "`",
|
sequence: '`',
|
||||||
action: "keydown",
|
action: 'keydown',
|
||||||
},
|
},
|
||||||
STOP_BROADCAST: {
|
STOP_BROADCAST: {
|
||||||
sequence: "`",
|
sequence: '`',
|
||||||
action: "keyup",
|
action: 'keyup',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
@@ -188,8 +188,8 @@ export default function NirvanaTerminal({
|
|||||||
<>
|
<>
|
||||||
<GlobalHotKeys handlers={handlers} keyMap={keyMap} allowChanges />
|
<GlobalHotKeys handlers={handlers} keyMap={keyMap} allowChanges />
|
||||||
|
|
||||||
<div className="flex flex-row flex-1">
|
<div className='flex flex-row flex-1'>
|
||||||
<div className="flex flex-col bg-white w-[400px] relative group">
|
<div className='flex flex-col bg-white w-[400px] relative group'>
|
||||||
{/* modal for creating new line */}
|
{/* modal for creating new line */}
|
||||||
<NewLineModal
|
<NewLineModal
|
||||||
open={isModalVisible}
|
open={isModalVisible}
|
||||||
@@ -197,17 +197,17 @@ export default function NirvanaTerminal({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{/* tuned in lines block */}
|
{/* tuned in lines block */}
|
||||||
<div className="bg-gray-100 flex flex-col shadow-lg">
|
<div className='bg-gray-100 flex flex-col shadow-lg'>
|
||||||
{/* tuned in header + general controls */}
|
{/* tuned in header + general controls */}
|
||||||
|
|
||||||
<Tooltip placement="right" title={"These are your active rooms..."}>
|
<Tooltip placement='right' title={'These are your active rooms...'}>
|
||||||
<div className="flex flex-row items-center py-3 px-4 pb-0">
|
<div className='flex flex-row items-center py-3 px-4 pb-0'>
|
||||||
<span className="flex flex-row gap-2 items-center justify-start text-gray-400 animate-pulse">
|
<span className='flex flex-row gap-2 items-center justify-start text-gray-400 animate-pulse'>
|
||||||
<FiActivity className="text-sm" />
|
<FiActivity className='text-sm' />
|
||||||
|
|
||||||
<h2 className="text-inherit text-sm">Rooms</h2>
|
<h2 className='text-inherit text-sm'>Rooms</h2>
|
||||||
|
|
||||||
<p className="text-slate-300 text-xs">{`${
|
<p className='text-slate-300 text-xs'>{`${
|
||||||
toggleTunedLines?.length || 0
|
toggleTunedLines?.length || 0
|
||||||
}/3`}</p>
|
}/3`}</p>
|
||||||
</span>
|
</span>
|
||||||
@@ -215,7 +215,7 @@ export default function NirvanaTerminal({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
{/* list of toggle tuned lines */}
|
{/* list of toggle tuned lines */}
|
||||||
<div className="flex flex-col mt-2">
|
<div className='flex flex-col mt-2'>
|
||||||
{toggleTunedLines.map((masterLineData) => (
|
{toggleTunedLines.map((masterLineData) => (
|
||||||
<LineRow
|
<LineRow
|
||||||
key={`terminalListLines-${masterLineData.lineDetails._id.toString()}`}
|
key={`terminalListLines-${masterLineData.lineDetails._id.toString()}`}
|
||||||
@@ -227,14 +227,14 @@ export default function NirvanaTerminal({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!(allLines.length > 0) && !(toggleTunedLines.length > 0) && (
|
{!(allLines.length > 0) && !(toggleTunedLines.length > 0) && (
|
||||||
<span className="text-gray-300 text-sm my-5 text-center">
|
<span className='text-gray-300 text-sm my-5 text-center'>
|
||||||
You have no lines! <br /> Create one to connect to your team
|
You have no lines! <br /> Create one to connect to your team
|
||||||
instantly.
|
instantly.
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* rest of the lines */}
|
{/* rest of the lines */}
|
||||||
<div className={"flex flex-col"}>
|
<div className={'flex flex-col'}>
|
||||||
{isLoadingInitialLines ? (
|
{isLoadingInitialLines ? (
|
||||||
<Skeleton />
|
<Skeleton />
|
||||||
) : (
|
) : (
|
||||||
@@ -250,12 +250,12 @@ export default function NirvanaTerminal({
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
onClick={() => setIsModalVisible(true)}
|
onClick={() => setIsModalVisible(true)}
|
||||||
className="absolute bottom-3 right-3 z-10 scale-0
|
className='absolute bottom-3 right-3 z-10 scale-0
|
||||||
group-hover:scale-100 ease-in-out hover:transition group-hover:transition delay-100 duration-200"
|
group-hover:scale-100 ease-in-out hover:transition group-hover:transition delay-100 duration-200'
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className="flex flex-row gap-2 items-center justify-evenly
|
className='flex flex-row gap-2 items-center justify-evenly
|
||||||
shadow-xl bg-gray-800 p-2 text-white text-xs"
|
shadow-xl bg-gray-800 p-2 text-white text-xs'
|
||||||
>
|
>
|
||||||
<FaPlus />
|
<FaPlus />
|
||||||
<span>New line</span>
|
<span>New line</span>
|
||||||
@@ -270,13 +270,13 @@ export default function NirvanaTerminal({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col flex-1 justify-center items-center bg-gray-100
|
className='flex flex-col flex-1 justify-center items-center bg-gray-100
|
||||||
border-l border-l-gray-200"
|
border-l border-l-gray-200'
|
||||||
>
|
>
|
||||||
<span className="text-xl text-gray-800">
|
<span className='text-xl text-gray-800'>
|
||||||
{`Hi ${userDetails?.user?.givenName}!`}
|
{`Hi ${userDetails?.user?.givenName}!`}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-md text-gray-400">You're all set!</span>
|
<span className='text-md text-gray-400'>You're all set!</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -293,7 +293,7 @@ function LineDetailsTerminal({
|
|||||||
}) {
|
}) {
|
||||||
const { data: userDetails } = useGetUserDetails();
|
const { data: userDetails } = useGetUserDetails();
|
||||||
|
|
||||||
console.log("selected line", selectedLine);
|
console.log('selected line', selectedLine);
|
||||||
|
|
||||||
const isUserToggleTuned = useMemo(
|
const isUserToggleTuned = useMemo(
|
||||||
() => selectedLine?.currentUserMember?.state === LineMemberState.TUNED,
|
() => selectedLine?.currentUserMember?.state === LineMemberState.TUNED,
|
||||||
@@ -357,20 +357,20 @@ function LineDetailsTerminal({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col flex-1 bg-gray-100
|
className='flex flex-col flex-1 bg-gray-100
|
||||||
border-l border-l-gray-200 relative"
|
border-l border-l-gray-200 relative'
|
||||||
>
|
>
|
||||||
{/* line details */}
|
{/* line details */}
|
||||||
<div
|
<div
|
||||||
className="p-4
|
className='p-4
|
||||||
flex flex-row items-center gap-2 justify-end border-b-gray-200 border-b"
|
flex flex-row items-center gap-2 justify-end border-b-gray-200 border-b'
|
||||||
>
|
>
|
||||||
{profilePictures && (
|
{profilePictures && (
|
||||||
<LineIcon grayscale={false} sourceImages={profilePictures} />
|
<LineIcon grayscale={false} sourceImages={profilePictures} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex flex-col items-start mr-auto group">
|
<div className='flex flex-col items-start mr-auto group'>
|
||||||
<span className="flex flex-row gap-2 items-center">
|
<span className='flex flex-row gap-2 items-center'>
|
||||||
<h2 className={`text-lg text-slate-800 font-semibold`}>
|
<h2 className={`text-lg text-slate-800 font-semibold`}>
|
||||||
{selectedLine.lineDetails.name ||
|
{selectedLine.lineDetails.name ||
|
||||||
selectedLine.otherUserObjects[0].givenName}
|
selectedLine.otherUserObjects[0].givenName}
|
||||||
@@ -380,16 +380,16 @@ function LineDetailsTerminal({
|
|||||||
className={`p-1 hidden group-hover:flex justify-center items-center hover:bg-gray-300
|
className={`p-1 hidden group-hover:flex justify-center items-center hover:bg-gray-300
|
||||||
transition-all hover:scale-105`}
|
transition-all hover:scale-105`}
|
||||||
>
|
>
|
||||||
<FiSettings className="text-gray-400 text-xs" />
|
<FiSettings className='text-gray-400 text-xs' />
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span className="flex flex-row gap-2 items-center">
|
<span className='flex flex-row gap-2 items-center'>
|
||||||
<span className="text-gray-300 text-xs">{`${
|
<span className='text-gray-300 text-xs'>{`${
|
||||||
selectedLine.otherMembers?.length + 1 ?? 0
|
selectedLine.otherMembers?.length + 1 ?? 0
|
||||||
} members`}</span>
|
} members`}</span>
|
||||||
<span className="h-1 w-1 bg-gray-800 rounded-full"></span>
|
<span className='h-1 w-1 bg-gray-800 rounded-full'></span>
|
||||||
<span className="text-teal-500 text-xs">{`${
|
<span className='text-teal-500 text-xs'>{`${
|
||||||
selectedLine.tunedInMemberIds?.length ?? 0
|
selectedLine.tunedInMemberIds?.length ?? 0
|
||||||
} in this room`}</span>
|
} in this room`}</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -397,15 +397,15 @@ function LineDetailsTerminal({
|
|||||||
|
|
||||||
{/* TODO: move to on hover of line row */}
|
{/* TODO: move to on hover of line row */}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
placement="left"
|
placement='left'
|
||||||
title={`${
|
title={`${
|
||||||
isUserToggleTuned ? "click to untoggle" : "click to stay tuned in"
|
isUserToggleTuned ? 'click to untoggle' : 'click to stay tuned in'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className={`p-2 flex justify-center items-center shadow-lg
|
className={`p-2 flex justify-center items-center shadow-lg
|
||||||
hover:scale-105 transition-all animate-pulse ${
|
hover:scale-105 transition-all animate-pulse ${
|
||||||
isUserToggleTuned ? "bg-gray-800 text-white" : "text-black"
|
isUserToggleTuned ? 'bg-gray-800 text-white' : 'text-black'
|
||||||
}`}
|
}`}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
isUserToggleTuned
|
isUserToggleTuned
|
||||||
@@ -419,101 +419,101 @@ function LineDetailsTerminal({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<FiActivity className="text-md" />
|
<FiActivity className='text-md' />
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* line timeline */}
|
{/* line timeline */}
|
||||||
<div className="flex flex-col items-center gap-2 my-2 mx-auto max-w-lg w-full">
|
<div className='flex flex-col items-center gap-2 my-2 mx-auto max-w-lg w-full'>
|
||||||
<span
|
<span
|
||||||
className={"text-gray-300 text-sm cursor-pointer hover:underline"}
|
className={'text-gray-300 text-sm cursor-pointer hover:underline'}
|
||||||
>
|
>
|
||||||
load more
|
load more
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span className={"text-gray-300 text-sm"}>yesterday</span>
|
<span className={'text-gray-300 text-sm'}>yesterday</span>
|
||||||
|
|
||||||
<div className={"rounded border border-gray-200 flex flex-col w-full"}>
|
<div className={'rounded border border-gray-200 flex flex-col w-full'}>
|
||||||
{selectedLine.otherUserObjects.map((otherUser) => (
|
{selectedLine.otherUserObjects.map((otherUser) => (
|
||||||
<div
|
<div
|
||||||
className="flex flex-row p-2 gap-2 items-center bg-transparent
|
className='flex flex-row p-2 gap-2 items-center bg-transparent
|
||||||
border-b border-b-gray-200 last:border-b-0"
|
border-b border-b-gray-200 last:border-b-0'
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`linehistory-${1}`}
|
key={`linehistory-${1}`}
|
||||||
src={otherUser.picture}
|
src={otherUser.picture}
|
||||||
shape="square"
|
shape='square'
|
||||||
size={"default"}
|
size={'default'}
|
||||||
// grayscale if not playing?
|
// grayscale if not playing?
|
||||||
className={`${true && "grayscale"}`}
|
className={`${true && 'grayscale'}`}
|
||||||
/>
|
/>
|
||||||
<span className="text-gray-500">{otherUser.givenName}</span>
|
<span className='text-gray-500'>{otherUser.givenName}</span>
|
||||||
|
|
||||||
<span className="ml-auto text-xs text-gray-300">{`${
|
<span className='ml-auto text-xs text-gray-300'>{`${
|
||||||
Math.floor(Math.random() * 10) + 1
|
Math.floor(Math.random() * 10) + 1
|
||||||
}:${Math.floor(Math.random() * 100) + 10}pm |`}</span>
|
}:${Math.floor(Math.random() * 100) + 10}pm |`}</span>
|
||||||
|
|
||||||
<span className="text-gray-400 text-md">{`${
|
<span className='text-gray-400 text-md'>{`${
|
||||||
Math.floor(Math.random() * 60) + 1
|
Math.floor(Math.random() * 60) + 1
|
||||||
} seconds`}</span>
|
} seconds`}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="flex flex-row p-2 gap-2 items-center bg-transparent
|
className='flex flex-row p-2 gap-2 items-center bg-transparent
|
||||||
border-b border-b-gray-200 last:border-b-0"
|
border-b border-b-gray-200 last:border-b-0'
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`linehistory-${1}`}
|
key={`linehistory-${1}`}
|
||||||
src={userDetails.user.picture}
|
src={userDetails.user.picture}
|
||||||
shape="square"
|
shape='square'
|
||||||
size={"default"}
|
size={'default'}
|
||||||
// grayscale if not playing?
|
// grayscale if not playing?
|
||||||
className={`${true && "grayscale"}`}
|
className={`${true && 'grayscale'}`}
|
||||||
/>
|
/>
|
||||||
<span className="text-gray-500">{"Arjun Patel"}</span>
|
<span className='text-gray-500'>{'Arjun Patel'}</span>
|
||||||
|
|
||||||
<span className="ml-auto text-xs text-gray-300">{`${
|
<span className='ml-auto text-xs text-gray-300'>{`${
|
||||||
Math.floor(Math.random() * 10) + 1
|
Math.floor(Math.random() * 10) + 1
|
||||||
}:${Math.floor(Math.random() * 100) + 10}pm |`}</span>
|
}:${Math.floor(Math.random() * 100) + 10}pm |`}</span>
|
||||||
|
|
||||||
<span className="text-gray-400 text-md">{`${
|
<span className='text-gray-400 text-md'>{`${
|
||||||
Math.floor(Math.random() * 60) + 1
|
Math.floor(Math.random() * 60) + 1
|
||||||
} seconds`}</span>
|
} seconds`}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span className={"text-gray-300 text-sm"}>today</span>
|
<span className={'text-gray-300 text-sm'}>today</span>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
"rounded border border-gray-400 flex flex-col w-full shadow-xl"
|
'rounded border border-gray-400 flex flex-col w-full shadow-xl'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{selectedLine.otherUserObjects.map((otherUser) => (
|
{selectedLine.otherUserObjects.map((otherUser) => (
|
||||||
// TODO: show the shadow if it's unheard
|
// TODO: show the shadow if it's unheard
|
||||||
<div
|
<div
|
||||||
className="flex flex-row p-2 gap-2 items-center bg-transparent
|
className='flex flex-row p-2 gap-2 items-center bg-transparent
|
||||||
border-b border-b-gray-400 last:border-b-0"
|
border-b border-b-gray-400 last:border-b-0'
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`linehistory-${1}`}
|
key={`linehistory-${1}`}
|
||||||
src={otherUser.picture}
|
src={otherUser.picture}
|
||||||
shape="square"
|
shape='square'
|
||||||
size={"default"}
|
size={'default'}
|
||||||
// grayscale if not playing?
|
// grayscale if not playing?
|
||||||
className={`${false && "grayscale"}`}
|
className={`${false && 'grayscale'}`}
|
||||||
/>
|
/>
|
||||||
<span className="text-gray-600 font-semibold">
|
<span className='text-gray-600 font-semibold'>
|
||||||
{otherUser.name}
|
{otherUser.name}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span className="ml-auto text-xs text-gray-400">{`${
|
<span className='ml-auto text-xs text-gray-400'>{`${
|
||||||
Math.floor(Math.random() * 10) + 1
|
Math.floor(Math.random() * 10) + 1
|
||||||
}:${Math.floor(Math.random() * 100) + 10}pm |`}</span>
|
}:${Math.floor(Math.random() * 100) + 10}pm |`}</span>
|
||||||
|
|
||||||
<span className="text-gray-500 text-md">{`${
|
<span className='text-gray-500 text-md'>{`${
|
||||||
Math.floor(Math.random() * 60) + 1
|
Math.floor(Math.random() * 60) + 1
|
||||||
} seconds`}</span>
|
} seconds`}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -522,32 +522,32 @@ function LineDetailsTerminal({
|
|||||||
|
|
||||||
{/* live broadcasters */}
|
{/* live broadcasters */}
|
||||||
<span
|
<span
|
||||||
className={"flex flex-row gap-2 items-center text-teal-500 text-sm"}
|
className={'flex flex-row gap-2 items-center text-teal-500 text-sm'}
|
||||||
>
|
>
|
||||||
<FiSun className="animate-ping" />
|
<FiSun className='animate-ping' />
|
||||||
<span>right now</span>
|
<span>right now</span>
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
"rounded border border-teal-500 flex flex-col w-full shadow-2xl"
|
'rounded border border-teal-500 flex flex-col w-full shadow-2xl'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{selectedLine.otherUserObjects.map((otherUser) => (
|
{selectedLine.otherUserObjects.map((otherUser) => (
|
||||||
<div className="flex flex-row p-2 gap-2 items-center bg-transparent">
|
<div className='flex flex-row p-2 gap-2 items-center bg-transparent'>
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`linehistory-${1}`}
|
key={`linehistory-${1}`}
|
||||||
src={otherUser.picture}
|
src={otherUser.picture}
|
||||||
shape="square"
|
shape='square'
|
||||||
size={"large"}
|
size={'large'}
|
||||||
// grayscale if not playing?
|
// grayscale if not playing?
|
||||||
className={`shadow-lg`}
|
className={`shadow-lg`}
|
||||||
/>
|
/>
|
||||||
<span className="text-gray-600 font-semibold">
|
<span className='text-gray-600 font-semibold'>
|
||||||
{otherUser.name}
|
{otherUser.name}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<Tooltip title={"audio only"}>
|
<Tooltip title={'audio only'}>
|
||||||
<FiHeadphones className="text-gray-600 text-md ml-auto" />
|
<FiHeadphones className='text-gray-600 text-md ml-auto' />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -558,11 +558,11 @@ function LineDetailsTerminal({
|
|||||||
className={`p-3 absolute right-3 bottom-3 flex justify-center items-center shadow-2xl
|
className={`p-3 absolute right-3 bottom-3 flex justify-center items-center shadow-2xl
|
||||||
hover:scale-105 transition-all ${
|
hover:scale-105 transition-all ${
|
||||||
isUserBroadcasting
|
isUserBroadcasting
|
||||||
? "bg-teal-800 text-white"
|
? 'bg-teal-800 text-white'
|
||||||
: "text-teal-800 border-teal-800 border"
|
: 'text-teal-800 border-teal-800 border'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<FiSun className="text-lg" />
|
<FiSun className='text-lg' />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
+40
-40
@@ -1,12 +1,12 @@
|
|||||||
import { Avatar, Modal } from "antd";
|
import { Avatar, Modal } from 'antd';
|
||||||
import { HotKeys, KeyMap } from "react-hotkeys";
|
import { HotKeys, KeyMap } from 'react-hotkeys';
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useCreateLine, useUserSearch } from "../../../controller/index";
|
import { useCreateLine, useUserSearch } from '../../../src/controller/index';
|
||||||
|
|
||||||
import BasicUserRow from "../../../components/User/basicUserDetailsRow";
|
import BasicUserRow from '../../components/User/basicUserDetailsRow';
|
||||||
import { FiSearch } from "react-icons/fi";
|
import { FiSearch } from 'react-icons/fi';
|
||||||
import { User } from "@nirvana/core/models";
|
import { User } from '@nirvana/core/models';
|
||||||
import toast from "react-hot-toast";
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
export default function NewLineModal({
|
export default function NewLineModal({
|
||||||
open,
|
open,
|
||||||
@@ -17,25 +17,25 @@ export default function NewLineModal({
|
|||||||
}) {
|
}) {
|
||||||
const [selectedPeople, setSelectedPeople] = useState<User[]>([]);
|
const [selectedPeople, setSelectedPeople] = useState<User[]>([]);
|
||||||
|
|
||||||
const [peopleSearchValue, setPeopleSearchValue] = useState<string>("");
|
const [peopleSearchValue, setPeopleSearchValue] = useState<string>('');
|
||||||
|
|
||||||
// the actual state that goes to query...the debounced one so to speak
|
// the actual state that goes to query...the debounced one so to speak
|
||||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
const [searchQuery, setSearchQuery] = useState<string>('');
|
||||||
const { refetch, data: searchRes } = useUserSearch(searchQuery);
|
const { refetch, data: searchRes } = useUserSearch(searchQuery);
|
||||||
|
|
||||||
const { mutateAsync, isLoading } = useCreateLine();
|
const { mutateAsync, isLoading } = useCreateLine();
|
||||||
|
|
||||||
const [lineName, setLineName] = useState<string>("");
|
const [lineName, setLineName] = useState<string>('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (searchQuery) refetch();
|
if (searchQuery) refetch();
|
||||||
}, [searchQuery]);
|
}, [searchQuery]);
|
||||||
|
|
||||||
const onSearch = useCallback(() => {
|
const onSearch = useCallback(() => {
|
||||||
console.log("enter key pressed");
|
console.log('enter key pressed');
|
||||||
|
|
||||||
if (peopleSearchValue) {
|
if (peopleSearchValue) {
|
||||||
console.log("searching for people in database");
|
console.log('searching for people in database');
|
||||||
setSearchQuery(peopleSearchValue);
|
setSearchQuery(peopleSearchValue);
|
||||||
}
|
}
|
||||||
}, [setSearchQuery, peopleSearchValue]);
|
}, [setSearchQuery, peopleSearchValue]);
|
||||||
@@ -52,7 +52,7 @@ export default function NewLineModal({
|
|||||||
return [...prevSelectedUsers, userToAdd];
|
return [...prevSelectedUsers, userToAdd];
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.error("you already selected this person below!");
|
toast.error('you already selected this person below!');
|
||||||
return prevSelectedUsers;
|
return prevSelectedUsers;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -78,11 +78,11 @@ export default function NewLineModal({
|
|||||||
// make sure that the list of lines updates for this client and others so that it shows this new line
|
// make sure that the list of lines updates for this client and others so that it shows this new line
|
||||||
// select the line so that it shows up in the line details for this client
|
// select the line so that it shows up in the line details for this client
|
||||||
|
|
||||||
console.log("trying to create line now!");
|
console.log('trying to create line now!');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!selectedPeople?.length) {
|
if (!selectedPeople?.length) {
|
||||||
toast.error("you must select at least one person");
|
toast.error('you must select at least one person');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ export default function NewLineModal({
|
|||||||
otherMemberIds: selectedMemberIds,
|
otherMemberIds: selectedMemberIds,
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.success("created line!");
|
toast.success('created line!');
|
||||||
|
|
||||||
// handle close once the new line is created
|
// handle close once the new line is created
|
||||||
handleClose();
|
handleClose();
|
||||||
@@ -103,7 +103,7 @@ export default function NewLineModal({
|
|||||||
toast.error(error);
|
toast.error(error);
|
||||||
console.error(error);
|
console.error(error);
|
||||||
} finally {
|
} finally {
|
||||||
console.log("done");
|
console.log('done');
|
||||||
}
|
}
|
||||||
}, [lineName, selectedPeople]);
|
}, [lineName, selectedPeople]);
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ export default function NewLineModal({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const keyMap: KeyMap = {
|
const keyMap: KeyMap = {
|
||||||
HANDLE_SEARCH: "enter",
|
HANDLE_SEARCH: 'enter',
|
||||||
};
|
};
|
||||||
const handlers = {
|
const handlers = {
|
||||||
HANDLE_SEARCH: onSearch,
|
HANDLE_SEARCH: onSearch,
|
||||||
@@ -123,49 +123,49 @@ export default function NewLineModal({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
title="Create a Line"
|
title='Create a Line'
|
||||||
visible={open}
|
visible={open}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
footer={
|
footer={
|
||||||
<div className="flex flex-row text-white">
|
<div className='flex flex-row text-white'>
|
||||||
<button
|
<button
|
||||||
className="flex-1 bg-gray-500 pb-3 pt-2 text-left pl-2"
|
className='flex-1 bg-gray-500 pb-3 pt-2 text-left pl-2'
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="flex-1 bg-teal-500 pb-3 pt-2 text-left pl-2"
|
className='flex-1 bg-teal-500 pb-3 pt-2 text-left pl-2'
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
>
|
>
|
||||||
Connect
|
Connect
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
className={"flex flex-col gap-5"}
|
className={'flex flex-col gap-5'}
|
||||||
>
|
>
|
||||||
<HotKeys handlers={handlers} keyMap={keyMap} allowChanges={true}>
|
<HotKeys handlers={handlers} keyMap={keyMap} allowChanges={true}>
|
||||||
<div className="flex flex-col items-start gap-2 mb-5">
|
<div className='flex flex-col items-start gap-2 mb-5'>
|
||||||
<p className="text-gray-300 text-sm">People</p>
|
<p className='text-gray-300 text-sm'>People</p>
|
||||||
|
|
||||||
<span className="flex flex-row gap-1 w-full items-center border border-gray-200 p-2 shadow">
|
<span className='flex flex-row gap-1 w-full items-center border border-gray-200 p-2 shadow'>
|
||||||
<FiSearch className="text-gray-300" />
|
<FiSearch className='text-gray-300' />
|
||||||
|
|
||||||
<input
|
<input
|
||||||
className="placeholder:text-gray-300 outline-none placeholder:text-sm border-0 flex-1"
|
className='placeholder:text-gray-300 outline-none placeholder:text-sm border-0 flex-1'
|
||||||
value={peopleSearchValue}
|
value={peopleSearchValue}
|
||||||
onChange={(e) => setPeopleSearchValue(e.target.value)}
|
onChange={(e) => setPeopleSearchValue(e.target.value)}
|
||||||
placeholder="search by name or email"
|
placeholder='search by name or email'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span className="text-xs text-gray-200 ml-auto">
|
<span className='text-xs text-gray-200 ml-auto'>
|
||||||
enter to search
|
enter to search
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{/* search results */}
|
{/* search results */}
|
||||||
{searchRes?.users?.length > 0 && (
|
{searchRes?.users?.length > 0 && (
|
||||||
<div className="flex flex-col border border-gray-200 shadow-md max-h-[500px] w-full overflow-y-auto">
|
<div className='flex flex-col border border-gray-200 shadow-md max-h-[500px] w-full overflow-y-auto'>
|
||||||
{searchRes?.users?.map((searchedUser) => (
|
{searchRes?.users?.map((searchedUser) => (
|
||||||
<BasicUserRow
|
<BasicUserRow
|
||||||
key={`searchResUser-${searchedUser.googleId}`}
|
key={`searchResUser-${searchedUser.googleId}`}
|
||||||
@@ -183,10 +183,10 @@ export default function NewLineModal({
|
|||||||
|
|
||||||
{/* selected people */}
|
{/* selected people */}
|
||||||
{selectedPeople?.length > 0 && (
|
{selectedPeople?.length > 0 && (
|
||||||
<div className="flex flex-col gap-2 mb-5">
|
<div className='flex flex-col gap-2 mb-5'>
|
||||||
<p className="text-gray-300 text-sm">Selected People</p>
|
<p className='text-gray-300 text-sm'>Selected People</p>
|
||||||
|
|
||||||
<div className="flex flex-col w-full">
|
<div className='flex flex-col w-full'>
|
||||||
{selectedPeople.map((selectedUser) => (
|
{selectedPeople.map((selectedUser) => (
|
||||||
<BasicUserRow
|
<BasicUserRow
|
||||||
key={`selectedUser-${selectedUser.googleId}`}
|
key={`selectedUser-${selectedUser.googleId}`}
|
||||||
@@ -206,14 +206,14 @@ export default function NewLineModal({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className='flex flex-col gap-2'>
|
||||||
<p className="text-gray-300 text-sm">Line Name (optional)</p>
|
<p className='text-gray-300 text-sm'>Line Name (optional)</p>
|
||||||
<input
|
<input
|
||||||
value={lineName}
|
value={lineName}
|
||||||
onChange={(e) => setLineName(e.target.value)}
|
onChange={(e) => setLineName(e.target.value)}
|
||||||
className="placeholder:text-gray-300 outline-none placeholder:text-sm flex-1
|
className='placeholder:text-gray-300 outline-none placeholder:text-sm flex-1
|
||||||
border p-2 border-gray-200"
|
border p-2 border-gray-200'
|
||||||
placeholder={"ex. Engineering, Sprint 7, Follow up on present..."}
|
placeholder={'ex. Engineering, Sprint 7, Follow up on present...'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</HotKeys>
|
</HotKeys>
|
||||||
Reference in New Issue
Block a user