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": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/electron",
|
||||
"plugin:import/typescript",
|
||||
"plugin:reac/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser"
|
||||
"extends": ["plugin:react/recommended", "airbnb", "airbnb/hooks", "airbnb-typescript"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"plugins": ["react", "@typescript-eslint"],
|
||||
"rules": {
|
||||
"no-shadow": "off",
|
||||
"@typescript-eslint/no-shadow": ["error"],
|
||||
"no-unused-vars": "warn",
|
||||
"@typescript-eslint/no-unused-vars": "warn"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,14 +74,19 @@
|
||||
"@electron-forge/plugin-webpack": "6.0.0-beta.63",
|
||||
"@types/react": "^17.0.40",
|
||||
"@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",
|
||||
"@vercel/webpack-asset-relocator-loader": "1.7.0",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"css-loader": "^6.0.0",
|
||||
"electron": "17.1.2",
|
||||
"eslint": "^8.0.1",
|
||||
"eslint-plugin-import": "^2.25.0",
|
||||
"eslint": "^8.15.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",
|
||||
"mini-css-extract-plugin": "^2.6.0",
|
||||
"node-loader": "^2.0.0",
|
||||
@@ -98,8 +103,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@getstation/electron-google-oauth2": "^2.1.0",
|
||||
"@nirvana/core": "*",
|
||||
"@nirvana/components": "*",
|
||||
"@nirvana/core": "*",
|
||||
"antd": "^4.20.2",
|
||||
"axios": "^0.26.1",
|
||||
"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
|
||||
// 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
|
||||
|
||||
enum Channels {
|
||||
ACTIVATE_LOG_IN = "ACTIVATE_LOG_IN",
|
||||
GOOGLE_AUTH_TOKENS = "GOOGLE_AUTH_TOKENS",
|
||||
RESIZE_WINDOW = "RESIZE_WINDOW",
|
||||
ON_WINDOW_BLUR = "ON_WINDOW_BLUR",
|
||||
export enum Channels {
|
||||
ACTIVATE_LOG_IN = 'ACTIVATE_LOG_IN',
|
||||
GOOGLE_AUTH_TOKENS = 'GOOGLE_AUTH_TOKENS',
|
||||
RESIZE_WINDOW = 'RESIZE_WINDOW',
|
||||
ON_WINDOW_BLUR = 'ON_WINDOW_BLUR',
|
||||
}
|
||||
|
||||
export enum STORE_ITEMS {
|
||||
AUTH_SESSION_JWT = "AUTH_SESSION_JWT",
|
||||
export enum StoreItems {
|
||||
AUTH_SESSION_JWT = 'AUTH_SESSION_JWT',
|
||||
}
|
||||
|
||||
export type Dimensions = { height: number; width: number };
|
||||
|
||||
export interface DimensionChangeRequest {
|
||||
setAlwaysOnTop: boolean;
|
||||
setPosition?: "topRight" | "center";
|
||||
setPosition?: 'topRight' | 'center';
|
||||
dimensions: Dimensions;
|
||||
addDimensions: boolean;
|
||||
}
|
||||
@@ -28,5 +29,3 @@ export const OVERLAY_ONLY_INITIAL_PRESET: Dimensions = {
|
||||
height: 50,
|
||||
width: 325,
|
||||
};
|
||||
|
||||
export default Channels;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { Dimensions, DimensionChangeRequest } from "./constants";
|
||||
import { electronAPI } from "./preload";
|
||||
/* eslint-disable no-unused-vars */
|
||||
import { DimensionChangeRequest, STORE_ITEMS, Channels } from './constants';
|
||||
|
||||
export {};
|
||||
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";
|
||||
import { contextBridge, ipcRenderer } from "electron";
|
||||
|
||||
import { STORE_ITEMS } from "./constants";
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
import { Channels, Dimensions, StoreItems } from './constants';
|
||||
|
||||
const electronAPI = {
|
||||
auth: {
|
||||
@@ -10,11 +9,11 @@ const electronAPI = {
|
||||
},
|
||||
},
|
||||
store: {
|
||||
get(val: STORE_ITEMS) {
|
||||
return ipcRenderer.invoke("electron-store-get", val);
|
||||
get(val: StoreItems) {
|
||||
return ipcRenderer.invoke('electron-store-get', val);
|
||||
},
|
||||
set(property: STORE_ITEMS, val: any) {
|
||||
ipcRenderer.send("electron-store-set", property, val);
|
||||
set(property: StoreItems, val: any) {
|
||||
ipcRenderer.send('electron-store-set', property, val);
|
||||
},
|
||||
// Other method you want to add like has(), reset(), etc.
|
||||
},
|
||||
@@ -26,7 +25,7 @@ const electronAPI = {
|
||||
},
|
||||
|
||||
on(channel: Channels, func: any) {
|
||||
const validChannels = ["ipc-example"];
|
||||
// const validChannels = ['ipc-example'];
|
||||
// if (validChannels.includes(channel)) {
|
||||
// // Deliberately strip event as it includes `sender`
|
||||
// ipcRenderer.on(channel, (event, ...args) => func(...args));
|
||||
@@ -45,6 +44,6 @@ const electronAPI = {
|
||||
},
|
||||
};
|
||||
|
||||
contextBridge.exposeInMainWorld("electronAPI", electronAPI);
|
||||
contextBridge.exposeInMainWorld('electronAPI', 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 {
|
||||
BrowserWindow,
|
||||
Display,
|
||||
Menu,
|
||||
app,
|
||||
dialog,
|
||||
globalShortcut,
|
||||
ipcMain,
|
||||
screen,
|
||||
} from "electron";
|
||||
import Channels, { DEFAULT_APP_PRESET } from "./electron/constants";
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
// eslint-disable-next-line object-curly-newline
|
||||
import { BrowserWindow, Display, app, ipcMain, screen } from 'electron';
|
||||
|
||||
import { DimensionChangeRequest } from "./electron/constants";
|
||||
import { handleGoogleLogin } from "./electron/handleLogin";
|
||||
import path from "path";
|
||||
import store from "./electron/store";
|
||||
import path from 'path';
|
||||
import ElectronGoogleOAuth2 from '@getstation/electron-google-oauth2';
|
||||
import { Channels, DEFAULT_APP_PRESET, DimensionChangeRequest } from './electron/constants';
|
||||
|
||||
import store from './electron/store';
|
||||
|
||||
// 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
|
||||
@@ -22,14 +15,29 @@ declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
|
||||
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
|
||||
|
||||
// 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
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// 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.
|
||||
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;
|
||||
|
||||
@@ -41,7 +49,7 @@ const createWindow = (): void => {
|
||||
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
|
||||
sandbox: true,
|
||||
},
|
||||
icon: "./assets/1024x1024.icns",
|
||||
icon: './assets/1024x1024.icns',
|
||||
|
||||
// transparent: true,
|
||||
|
||||
@@ -60,7 +68,7 @@ const createWindow = (): void => {
|
||||
browserWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
|
||||
|
||||
// Open the DevTools.
|
||||
browserWindow.webContents.openDevTools({ mode: "detach" });
|
||||
browserWindow.webContents.openDevTools({ mode: 'detach' });
|
||||
|
||||
display = screen.getPrimaryDisplay();
|
||||
};
|
||||
@@ -74,15 +82,15 @@ app
|
||||
.then(() => {
|
||||
// activate login
|
||||
ipcMain.on(Channels.ACTIVATE_LOG_IN, async (event, arg) => {
|
||||
console.log("initiating log in");
|
||||
console.log('initiating log in');
|
||||
await handleGoogleLogin();
|
||||
});
|
||||
|
||||
// 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);
|
||||
});
|
||||
ipcMain.handle("electron-store-get", async (event, val) => {
|
||||
ipcMain.handle('electron-store-get', async (event, val) => {
|
||||
const result = await store.get(val);
|
||||
return result;
|
||||
});
|
||||
@@ -90,7 +98,7 @@ app
|
||||
// dynamically changing the window bounds
|
||||
ipcMain.on(Channels.RESIZE_WINDOW, (event, req: DimensionChangeRequest) => {
|
||||
if (req.setAlwaysOnTop) {
|
||||
browserWindow.setAlwaysOnTop(true, "floating");
|
||||
browserWindow.setAlwaysOnTop(true, 'floating');
|
||||
} else {
|
||||
browserWindow.setAlwaysOnTop(false);
|
||||
}
|
||||
@@ -100,26 +108,19 @@ app
|
||||
browserWindow.setSize(
|
||||
currentDimensions[0] + req.dimensions.width,
|
||||
currentDimensions[1] + req.dimensions.height,
|
||||
false
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
browserWindow.setSize(
|
||||
req.dimensions.width,
|
||||
req.dimensions.height,
|
||||
false
|
||||
);
|
||||
browserWindow.setSize(req.dimensions.width, req.dimensions.height, false);
|
||||
}
|
||||
|
||||
if (req.setPosition) {
|
||||
if (req.setPosition === "center") {
|
||||
if (req.setPosition === 'center') {
|
||||
browserWindow.center();
|
||||
}
|
||||
|
||||
if (req.setPosition === "topRight") {
|
||||
browserWindow.setPosition(
|
||||
display.bounds.width - req.dimensions.width,
|
||||
0
|
||||
);
|
||||
if (req.setPosition === 'topRight') {
|
||||
browserWindow.setPosition(display.bounds.width - req.dimensions.width, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -130,7 +131,7 @@ app
|
||||
// });
|
||||
|
||||
// on blur, show overlay, and tell app to trigger overlay mode
|
||||
browserWindow.on("blur", () => {
|
||||
browserWindow.on('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
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") {
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on("activate", () => {
|
||||
app.on('activate', () => {
|
||||
// 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.
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
@@ -158,17 +159,17 @@ app.on("activate", () => {
|
||||
// open deep links from nirvana web app
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient("nirvana-desktop", process.execPath, [
|
||||
app.setAsDefaultProtocolClient('nirvana-desktop', process.execPath, [
|
||||
path.resolve(process.argv[1]),
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient("nirvana-desktop");
|
||||
app.setAsDefaultProtocolClient('nirvana-desktop');
|
||||
}
|
||||
|
||||
// Handle the protocol. In this case, we choose to show an Error Box.
|
||||
app.on("open-url", (event, url) => {
|
||||
console.log("welcome back, you arrived from: ", url);
|
||||
app.on('open-url', (event, url) => {
|
||||
console.log('welcome back, you arrived from: ', url);
|
||||
|
||||
browserWindow.focus();
|
||||
});
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
// import './index.css';
|
||||
|
||||
import "./app";
|
||||
import './electronApp';
|
||||
|
||||
console.log(
|
||||
'👋 This message is being logged by "renderer.js", included via webpack'
|
||||
);
|
||||
console.log('👋 This message is being logged by "renderer.js", included via webpack');
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"module": "commonjs",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"outDir": "dist",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"paths": {
|
||||
"*": ["node_modules/*"]
|
||||
},
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"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 Login from "../../pages/Login";
|
||||
import NirvanaApi from "../../controller/nirvanaApi";
|
||||
import { STORE_ITEMS } from "../../electron/constants";
|
||||
import SkeletonLoader from "../loading/skeleton";
|
||||
import { useEffect } from "react";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { $jwtToken } from '../../../src/controller/recoil';
|
||||
import Login from '../../Login';
|
||||
import NirvanaApi from '../../../src/controller/nirvanaApi';
|
||||
import { STORE_ITEMS } from '../../../src/electron/constants';
|
||||
import SkeletonLoader from '../loading/skeleton';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
export default function ProtectedRoute({
|
||||
children,
|
||||
@@ -47,7 +47,7 @@ export default function ProtectedRoute({
|
||||
// }, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("change in jwt token", jwtToken);
|
||||
console.log('change in jwt token', jwtToken);
|
||||
|
||||
if (jwtToken) {
|
||||
window.electronAPI.store.set(STORE_ITEMS.AUTH_SESSION_JWT, jwtToken);
|
||||
@@ -64,7 +64,7 @@ export default function ProtectedRoute({
|
||||
// first time loading
|
||||
if (serverLoading)
|
||||
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
|
||||
to back up and running! :) <br /> Please contact me for urgent concerns:
|
||||
arjunpatel@berkeley.edu
|
||||
@@ -73,7 +73,7 @@ export default function ProtectedRoute({
|
||||
|
||||
if (isLoading) {
|
||||
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 />
|
||||
</div>
|
||||
);
|
||||
+48
-48
@@ -1,4 +1,4 @@
|
||||
import { FiActivity, FiSun } from "react-icons/fi";
|
||||
import { FiActivity, FiSun } from 'react-icons/fi';
|
||||
import {
|
||||
RtcAnswerRequest,
|
||||
RtcCallRequest,
|
||||
@@ -6,21 +6,21 @@ import {
|
||||
RtcReceiveAnswerResponse,
|
||||
ServerResponseChannels,
|
||||
SomeoneUntunedFromLineResponse,
|
||||
} from "@nirvana/core/sockets/channels";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
} from '@nirvana/core/sockets/channels';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { $selectedLineId } from "../../../controller/recoil";
|
||||
import { Avatar } from "antd";
|
||||
import LineIcon from "../lineIcon";
|
||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
||||
import Peer from "simple-peer";
|
||||
import { ServerRequestChannels } from "../../../../../core/sockets/channels";
|
||||
import moment from "moment";
|
||||
import toast from "react-hot-toast";
|
||||
import { useGetUserDetails } from "../../../controller/index";
|
||||
import { useLineDataProvider } from "../../../controller/lineDataProvider";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { $selectedLineId } from '../../../controller/recoil';
|
||||
import { Avatar } from 'antd';
|
||||
import LineIcon from '../lineIcon';
|
||||
import { LineMemberState } from '@nirvana/core/models/line.model';
|
||||
import MasterLineData from '@nirvana/core/models/masterLineData.model';
|
||||
import Peer from 'simple-peer';
|
||||
import { ServerRequestChannels } from '@nirvana/core/sockets/channels';
|
||||
import moment from 'moment';
|
||||
import toast from 'react-hot-toast';
|
||||
import { useGetUserDetails } from '../../../controller/index';
|
||||
import { useLineDataProvider } from '../../../controller/lineDataProvider';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
// 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
|
||||
@@ -36,9 +36,9 @@ export default function LineRow({
|
||||
const { data: userData } = useGetUserDetails();
|
||||
|
||||
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
|
||||
@@ -54,19 +54,19 @@ export default function LineRow({
|
||||
const renderActivityIcon = useMemo(() => {
|
||||
// if there is someone or me broadcasting here
|
||||
if (masterLineData.currentBroadcastersUserIds?.length > 0)
|
||||
return <FiSun className="text-teal-500 animate-pulse" />;
|
||||
return <FiSun className='text-teal-500 animate-pulse' />;
|
||||
|
||||
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 (masterLineData.currentUserMember.lastVisitDate)
|
||||
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 (
|
||||
<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]);
|
||||
|
||||
@@ -77,22 +77,22 @@ export default function LineRow({
|
||||
<Avatar.Group
|
||||
key={`lineRowRightActivityGroup-${masterLineData.lineDetails._id.toString()}`}
|
||||
maxCount={2}
|
||||
maxPopoverTrigger="click"
|
||||
size="small"
|
||||
maxPopoverTrigger='click'
|
||||
size='small'
|
||||
maxStyle={{
|
||||
color: "#f56a00",
|
||||
backgroundColor: "#fde3cf",
|
||||
cursor: "pointer",
|
||||
borderRadius: "0",
|
||||
color: '#f56a00',
|
||||
backgroundColor: '#fde3cf',
|
||||
cursor: 'pointer',
|
||||
borderRadius: '0',
|
||||
}}
|
||||
className="shadow-lg"
|
||||
className='shadow-lg'
|
||||
>
|
||||
{masterLineData.otherUserObjects?.map((otherUser, index) => (
|
||||
<Avatar
|
||||
key={`lineListActivitySection-${otherUser._id.toString()}-${index}`}
|
||||
src={otherUser.picture ?? ""}
|
||||
shape="square"
|
||||
size={"small"}
|
||||
src={otherUser.picture ?? ''}
|
||||
shape='square'
|
||||
size={'small'}
|
||||
/>
|
||||
))}
|
||||
</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
|
||||
last:border-b-0 border-b border-b-gray-200 relative z-50 rounded ${
|
||||
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 */}
|
||||
<div className="flex-shrink-0 h-4 w-4">{renderActivityIcon}</div>
|
||||
<div className='flex-shrink-0 h-4 w-4'>{renderActivityIcon}</div>
|
||||
|
||||
{profilePictures && (
|
||||
<LineIcon grayscale={!isUserTunedIn} sourceImages={profilePictures} />
|
||||
@@ -150,15 +150,15 @@ export default function LineRow({
|
||||
<h2
|
||||
className={`text-inherit text-md max-w-[220px] truncate text-slate-800 ${
|
||||
masterLineData.currentUserMember.lastVisitDate
|
||||
? "font-semibold"
|
||||
: ""
|
||||
? 'font-semibold'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{masterLineData.lineDetails.name ||
|
||||
masterLineData.otherUserObjects[0].givenName}
|
||||
</h2>
|
||||
|
||||
<div className="ml-auto flex-shrink-0">{renderRightActivity}</div>
|
||||
<div className='ml-auto flex-shrink-0'>{renderRightActivity}</div>
|
||||
</div>
|
||||
|
||||
{/* mounts and unmounts based on if in the room or now */}
|
||||
@@ -249,7 +249,7 @@ function StreamRoom({
|
||||
localPeerConnections[otherTunedInUserId] = localPeerInitiator;
|
||||
|
||||
// notify each one with specific signal
|
||||
localPeerInitiator.on("signal", (signal) => {
|
||||
localPeerInitiator.on('signal', (signal) => {
|
||||
$ws.emit(
|
||||
ServerRequestChannels.RTC_CALL_REQUEST,
|
||||
new RtcCallRequest(lineId, otherTunedInUserId, signal)
|
||||
@@ -266,7 +266,7 @@ function StreamRoom({
|
||||
// create a local peer connection for this new user
|
||||
|
||||
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);
|
||||
|
||||
@@ -276,9 +276,9 @@ function StreamRoom({
|
||||
stream: userStream, // add in my own stream that I got before
|
||||
});
|
||||
|
||||
peerForMeAndNewbie.on("signal", (signal) => {
|
||||
peerForMeAndNewbie.on('signal', (signal) => {
|
||||
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(
|
||||
ServerRequestChannels.RTC_ANSWER_REQUEST,
|
||||
@@ -315,7 +315,7 @@ function StreamRoom({
|
||||
const newUserPeerMap = { ...previousUserPeersMap };
|
||||
|
||||
console.log(
|
||||
"here is the current peers map",
|
||||
'here is the current peers map',
|
||||
previousUserPeersMap
|
||||
);
|
||||
|
||||
@@ -325,7 +325,7 @@ function StreamRoom({
|
||||
peerForAnswerer.signal(res.simplePeerSignal);
|
||||
} else {
|
||||
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);
|
||||
|
||||
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(() => {
|
||||
console.log("keeping an eye on user peers map");
|
||||
console.log('keeping an eye on user peers map');
|
||||
console.log(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
|
||||
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) => {
|
||||
// go through the userIds here
|
||||
@@ -389,7 +389,7 @@ function StreamRoom({
|
||||
otherUserIdsPeers.forEach((otherUserId) => {
|
||||
// problem if we are trying to show stream of someone who is not tuned in
|
||||
if (!tunedInUsers.includes(otherUserId)) {
|
||||
console.log("user left with id:", otherUserId);
|
||||
console.log('user left with id:', otherUserId);
|
||||
const disconnectedLocalPeer = newMap[otherUserId];
|
||||
|
||||
if (disconnectedLocalPeer) {
|
||||
@@ -436,9 +436,9 @@ function PeerStreamRenderer({
|
||||
const streamRef = useRef<HTMLVideoElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
peer.on("stream", (remotePeerStream: MediaStream) => {
|
||||
peer.on('stream', (remotePeerStream: MediaStream) => {
|
||||
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;
|
||||
@@ -1,9 +1,9 @@
|
||||
import NirvanaApi, { ApiCalls } from "./nirvanaApi";
|
||||
import { useMutation, useQuery } from "react-query";
|
||||
import NirvanaApi, { ApiCalls } from './nirvanaApi';
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
import { $jwtToken } from "./recoil";
|
||||
import { queryClient } from "../pages/nirvanaApp";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { $jwtToken } from './recoil';
|
||||
import { queryClient } from '../../legacy/nirvanaApp';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
// ====== QUERIES
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useRecoilValue } from "recoil";
|
||||
* ensure that the server is up
|
||||
*/
|
||||
export function useServerCheck() {
|
||||
return useQuery("SERVER_CHECK", ApiCalls.serverCheck, {
|
||||
return useQuery('SERVER_CHECK', ApiCalls.serverCheck, {
|
||||
retry: true,
|
||||
refetchOnWindowFocus: false,
|
||||
|
||||
@@ -22,7 +22,7 @@ export function useServerCheck() {
|
||||
export function useAuthCheck(enabled: boolean = true) {
|
||||
const jwtToken = useRecoilValue($jwtToken);
|
||||
|
||||
return useQuery("AUTH_CHECK", ApiCalls.authCheck, {
|
||||
return useQuery('AUTH_CHECK', ApiCalls.authCheck, {
|
||||
retry: false,
|
||||
refetchOnWindowFocus: false,
|
||||
|
||||
@@ -32,11 +32,11 @@ export function useAuthCheck(enabled: boolean = true) {
|
||||
}
|
||||
|
||||
export function useLogin() {
|
||||
return useMutation("LOGIN", ApiCalls.login, {});
|
||||
return useMutation('LOGIN', ApiCalls.login, {});
|
||||
}
|
||||
|
||||
export function useGetUserDetails() {
|
||||
return useQuery("USER_DETAILS", ApiCalls.getUserDetails, {
|
||||
return useQuery('USER_DETAILS', ApiCalls.getUserDetails, {
|
||||
retry: false,
|
||||
refetchOnWindowFocus: false,
|
||||
onError: (err) => {
|
||||
@@ -46,7 +46,7 @@ export function useGetUserDetails() {
|
||||
}
|
||||
|
||||
export function useUserSearch(searchQuery: string) {
|
||||
return useQuery("USER_SEARCH", () => ApiCalls.userSearch(searchQuery), {
|
||||
return useQuery('USER_SEARCH', () => ApiCalls.userSearch(searchQuery), {
|
||||
enabled: searchQuery ? true : false,
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
@@ -57,7 +57,7 @@ export function useUserLines() {
|
||||
// todo: base/source of truth for getting all of the lines for the user
|
||||
// merge with sockets + audio clip data + master data + convomember data
|
||||
|
||||
return useQuery("USER_LINES", ApiCalls.getUserLines, {
|
||||
return useQuery('USER_LINES', ApiCalls.getUserLines, {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchIntervalInBackground: false,
|
||||
staleTime: Infinity,
|
||||
@@ -72,7 +72,7 @@ export function useGetDmByUserId() {
|
||||
export function useCreateLine() {
|
||||
return useMutation(ApiCalls.createLine, {
|
||||
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 {
|
||||
ConnectToLineRequest,
|
||||
ServerRequestChannels,
|
||||
@@ -12,18 +12,18 @@ import {
|
||||
UntuneFromLineRequest,
|
||||
UserStartedBroadcastingResponse,
|
||||
UserStoppedBroadcastingResponse,
|
||||
} from "@nirvana/core/sockets/channels";
|
||||
import React, { useContext, useState } from "react";
|
||||
import { Socket, io } from "socket.io-client";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { useRecoilValue, useSetRecoilState } from "recoil";
|
||||
} from '@nirvana/core/sockets/channels';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { Socket, io } from 'socket.io-client';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
||||
import { User } from "@nirvana/core/models";
|
||||
import { queryClient } from "../pages/nirvanaApp";
|
||||
import toast from "react-hot-toast";
|
||||
import { useUserLines } from "./index";
|
||||
import { LineMemberState } from '@nirvana/core/models/line.model';
|
||||
import MasterLineData from '@nirvana/core/models/masterLineData.model';
|
||||
import { User } from '@nirvana/core/models';
|
||||
import { queryClient } from '../../legacy/nirvanaApp';
|
||||
import toast from 'react-hot-toast';
|
||||
import { useUserLines } from './index';
|
||||
|
||||
let $ws: Socket;
|
||||
|
||||
@@ -44,19 +44,19 @@ function useSocketHandler(linesData: MasterLineData[]) {
|
||||
// https://socket.io/docs/v4/client-options/#reconnection
|
||||
|
||||
useEffect(() => {
|
||||
$ws = io("http://localhost:5000", {
|
||||
$ws = io('http://localhost:5000', {
|
||||
query: { token: jwtToken },
|
||||
transports: ["websocket"],
|
||||
transports: ['websocket'],
|
||||
upgrade: false,
|
||||
forceNew: true,
|
||||
reconnection: false, // ! TESTING THE PROBLEM WITH RECONNECTION CLIENT LISTENERS NOT ACTIVATING
|
||||
});
|
||||
|
||||
$ws.on("connect", () => {
|
||||
$ws.on('connect', () => {
|
||||
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
|
||||
@@ -160,7 +160,7 @@ function useSocketHandler(linesData: MasterLineData[]) {
|
||||
$ws.on(
|
||||
ServerResponseChannels.SOMEONE_STARTED_BROADCASTING,
|
||||
(res: UserStartedBroadcastingResponse) => {
|
||||
console.log("someone is starting to broadcast");
|
||||
console.log('someone is starting to broadcast');
|
||||
|
||||
setLinesMap((prevLinesMap) => {
|
||||
const newMap = { ...prevLinesMap };
|
||||
@@ -198,28 +198,28 @@ function useSocketHandler(linesData: MasterLineData[]) {
|
||||
|
||||
// on disconnections, just switch it to flow state?
|
||||
// what if there was another problem?
|
||||
$ws.io.on("close", () => {
|
||||
$ws.io.on('close', () => {
|
||||
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
|
||||
// toast(
|
||||
// "Disconnected due to idling or some other issue. Please reconnect or refresh to fix the problem."
|
||||
// );
|
||||
|
||||
toast("unplugging");
|
||||
setDesktopMode("flowState");
|
||||
toast('unplugging');
|
||||
setDesktopMode('flowState');
|
||||
});
|
||||
|
||||
// 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
|
||||
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
|
||||
|
||||
// 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
|
||||
@@ -412,9 +412,9 @@ export function LineDataProvider({ children }) {
|
||||
// and then disconnect
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (desktopMode === "flowState" && $ws) {
|
||||
if (desktopMode === 'flowState' && $ws) {
|
||||
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);
|
||||
+15
-15
@@ -1,58 +1,58 @@
|
||||
import { atom } from "recoil";
|
||||
import { atom } from 'recoil';
|
||||
|
||||
export const $searchQuery = atom<string>({
|
||||
key: "SEARCH_QUERY",
|
||||
default: "",
|
||||
key: 'SEARCH_QUERY',
|
||||
default: '',
|
||||
});
|
||||
|
||||
export const $jwtToken = atom<string>({
|
||||
key: "JWT_TOKEN",
|
||||
key: 'JWT_TOKEN',
|
||||
default: null,
|
||||
});
|
||||
|
||||
// conversation id
|
||||
export const $selectedConversation = atom<string>({
|
||||
key: "SELECTED_CONVERSATION",
|
||||
key: 'SELECTED_CONVERSATION',
|
||||
default: null,
|
||||
});
|
||||
|
||||
// new convo page trigger
|
||||
export const $newConvoPage = atom<boolean>({
|
||||
key: "NEW_CONVO_PAGE",
|
||||
key: 'NEW_CONVO_PAGE',
|
||||
default: false,
|
||||
});
|
||||
|
||||
// number of active lines
|
||||
export const $numberActiveLines = atom<number>({
|
||||
key: "NUMBER_ACTIVE_LINES",
|
||||
key: 'NUMBER_ACTIVE_LINES',
|
||||
default: 0,
|
||||
});
|
||||
|
||||
// max number of active streams
|
||||
export const $maxNumberActiveStreams = atom<number>({
|
||||
key: "MAX_NUMBER_ACTIVE_STREAMS",
|
||||
key: 'MAX_NUMBER_ACTIVE_STREAMS',
|
||||
default: 0,
|
||||
});
|
||||
|
||||
// ============
|
||||
|
||||
type DesktopMode = "flowState" | "overlayOnly" | "terminal";
|
||||
type DesktopMode = 'flowState' | 'overlayOnly' | 'terminal';
|
||||
|
||||
export const $desktopMode = atom<DesktopMode>({
|
||||
key: "DESKTOP_MODE",
|
||||
default: "terminal",
|
||||
key: 'DESKTOP_MODE',
|
||||
default: 'terminal',
|
||||
});
|
||||
|
||||
export const $selectedLineId = atom<string>({
|
||||
key: "SELECTED_LINE_ID",
|
||||
key: 'SELECTED_LINE_ID',
|
||||
default: null,
|
||||
});
|
||||
|
||||
interface MediaSettings {
|
||||
mode: "audio" | "video" | "screen";
|
||||
mode: 'audio' | 'video' | 'screen';
|
||||
isMuted: boolean;
|
||||
}
|
||||
export const $mediaSettings = atom<MediaSettings>({
|
||||
key: "MEDIA_SETTINGS",
|
||||
default: { isMuted: false, mode: "audio" },
|
||||
key: 'MEDIA_SETTINGS',
|
||||
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 {
|
||||
$desktopMode,
|
||||
$maxNumberActiveStreams,
|
||||
$numberActiveLines,
|
||||
$selectedLineId,
|
||||
} from "../../controller/recoil";
|
||||
} from '../../src/controller/recoil';
|
||||
import Channels, {
|
||||
DEFAULT_APP_PRESET,
|
||||
Dimensions,
|
||||
} from "../../electron/constants";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useRecoilState, useRecoilValue } from "recoil";
|
||||
} from '../../src/electron/constants';
|
||||
|
||||
import FullMottoLogo from "../../../../components/logo/fullMotto";
|
||||
import { LineDataProvider } from "../../controller/lineDataProvider";
|
||||
import { LogoType } from "@nirvana/components/logo/full";
|
||||
import NirvanaHeader from "../../components/header/index";
|
||||
import NirvanaTerminal from "../terminal";
|
||||
import FullMottoLogo from '@nirvana/components/logo/fullMotto';
|
||||
import { LineDataProvider } from '../../src/controller/lineDataProvider';
|
||||
import NirvanaHeader from '../components/header/index';
|
||||
import NirvanaTerminal from '../terminal';
|
||||
|
||||
export default function NirvanaRouter() {
|
||||
const [selectedLineId, setSelectedLineId] = useRecoilState($selectedLineId);
|
||||
@@ -27,16 +27,16 @@ export default function NirvanaRouter() {
|
||||
useEffect(() => {
|
||||
// add dimensions if it's not overlay only mode
|
||||
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
|
||||
if (desktopMode === "terminal" || desktopMode == "flowState") {
|
||||
if (desktopMode === 'terminal' || desktopMode == 'flowState') {
|
||||
finalDimensions = DEFAULT_APP_PRESET;
|
||||
}
|
||||
|
||||
if (desktopMode === "overlayOnly") {
|
||||
if (desktopMode === 'overlayOnly') {
|
||||
finalDimensions = {
|
||||
height: 68 + numberOfOverlayRows * 200,
|
||||
width: 360 + 360 * numberOfOverlayColumns,
|
||||
@@ -44,7 +44,7 @@ export default function NirvanaRouter() {
|
||||
}
|
||||
|
||||
console.log(
|
||||
"setting new dimensions",
|
||||
'setting new dimensions',
|
||||
desktopMode,
|
||||
numberOfOverlayColumns,
|
||||
numberOfOverlayRows,
|
||||
@@ -70,7 +70,7 @@ export default function NirvanaRouter() {
|
||||
useEffect(() => {
|
||||
window.electronAPI.on(Channels.ON_WINDOW_BLUR, () => {
|
||||
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
|
||||
// setDesktopMode("overlayOnly");
|
||||
@@ -82,15 +82,15 @@ export default function NirvanaRouter() {
|
||||
}, [setDesktopMode, setSelectedLineId]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col flex-1">
|
||||
<NirvanaHeader onHeaderFocus={() => setDesktopMode("terminal")} />
|
||||
<div className='flex flex-col flex-1'>
|
||||
<NirvanaHeader onHeaderFocus={() => setDesktopMode('terminal')} />
|
||||
|
||||
{desktopMode === "flowState" && <FlowState />}
|
||||
{desktopMode === 'flowState' && <FlowState />}
|
||||
|
||||
{/* remount nirvana terminal */}
|
||||
{(desktopMode === "terminal" || desktopMode === "overlayOnly") && (
|
||||
{(desktopMode === 'terminal' || desktopMode === 'overlayOnly') && (
|
||||
<LineDataProvider>
|
||||
<NirvanaTerminal overlayOnly={desktopMode === "overlayOnly"} />
|
||||
<NirvanaTerminal overlayOnly={desktopMode === 'overlayOnly'} />
|
||||
</LineDataProvider>
|
||||
)}
|
||||
</div>
|
||||
@@ -109,7 +109,7 @@ function FlowState() {
|
||||
const [quote, setQuote] = useState<Quote>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetch("https://api.quotable.io/random")
|
||||
fetch('https://api.quotable.io/random')
|
||||
.then((res) => res.json())
|
||||
.then((data: Quote) => {
|
||||
console.warn(data);
|
||||
@@ -123,19 +123,19 @@ function FlowState() {
|
||||
}, []);
|
||||
|
||||
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" /> */}
|
||||
<FullMottoLogo
|
||||
type={LogoType.small}
|
||||
className={"absolute bottom-2 mx-auto"}
|
||||
className='absolute bottom-2 mx-auto'
|
||||
/>
|
||||
|
||||
{quote && (
|
||||
<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='flex flex-col justify-center items-center max-w-screen-sm'>
|
||||
<span className='text-xl text-gray-800 font-semibold text-center'>
|
||||
"{quote.content}"
|
||||
</span>
|
||||
<span className="tex-md italic text-gray-400">{quote.author}</span>
|
||||
<span className='tex-md italic text-gray-400'>{quote.author}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
+100
-100
@@ -1,19 +1,19 @@
|
||||
import { $desktopMode, $selectedLineId } from "../../controller/recoil";
|
||||
import { Avatar, Skeleton, Tooltip } from "antd";
|
||||
import { FiActivity, FiHeadphones, FiSettings, FiSun } from "react-icons/fi";
|
||||
import { GlobalHotKeys, KeyMap } from "react-hotkeys";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useGetUserDetails, useUserLines } from "../../controller/index";
|
||||
import { useRecoilState, useSetRecoilState } from "recoil";
|
||||
import { $desktopMode, $selectedLineId } from '../../src/controller/recoil';
|
||||
import { Avatar, Skeleton, Tooltip } from 'antd';
|
||||
import { FiActivity, FiHeadphones, FiSettings, FiSun } from 'react-icons/fi';
|
||||
import { GlobalHotKeys, KeyMap } from 'react-hotkeys';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useGetUserDetails, useUserLines } from '../../src/controller/index';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { FaPlus } from "react-icons/fa";
|
||||
import LineIcon from "../../components/lines/lineIcon/index";
|
||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
||||
import LineRow from "../../components/lines/lineRow.tsx/index";
|
||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
||||
import NewLineModal from "./newLine";
|
||||
import toast from "react-hot-toast";
|
||||
import { useLineDataProvider } from "../../controller/lineDataProvider";
|
||||
import { FaPlus } from 'react-icons/fa';
|
||||
import LineIcon from '../components/lines/lineIcon/index';
|
||||
import { LineMemberState } from '@nirvana/core/models/line.model';
|
||||
import LineRow from '../components/lines/lineRow.tsx/index';
|
||||
import MasterLineData from '@nirvana/core/models/masterLineData.model';
|
||||
import NewLineModal from './newLine';
|
||||
import toast from 'react-hot-toast';
|
||||
import { useLineDataProvider } from '../../src/controller/lineDataProvider';
|
||||
|
||||
/**
|
||||
* Socket Provider
|
||||
@@ -93,7 +93,7 @@ export default function NirvanaTerminal({
|
||||
// todo: sort/order based on activity and activity date and currently broadcasting/live
|
||||
|
||||
const handleEscape = useCallback(() => {
|
||||
console.log("deselecting line");
|
||||
console.log('deselecting line');
|
||||
|
||||
setSelectedLineId((prevSelectedLineId) => {
|
||||
// ! only want to untune if it's a temporarily tuned line
|
||||
@@ -128,7 +128,7 @@ export default function NirvanaTerminal({
|
||||
(lineId: string, turnToggleOn: boolean) => {
|
||||
// inhibit if they are trying to turn on and already have 3 toggle tuned
|
||||
if (toggleTunedLines?.length >= 3 && turnToggleOn) {
|
||||
toast.error("You cannot toggle more than 3 lines!");
|
||||
toast.error('You cannot toggle more than 3 lines!');
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -162,14 +162,14 @@ export default function NirvanaTerminal({
|
||||
|
||||
const keyMap: KeyMap = useMemo(
|
||||
() => ({
|
||||
DESELECT_LINE: "esc",
|
||||
DESELECT_LINE: 'esc',
|
||||
START_BROADCAST: {
|
||||
sequence: "`",
|
||||
action: "keydown",
|
||||
sequence: '`',
|
||||
action: 'keydown',
|
||||
},
|
||||
STOP_BROADCAST: {
|
||||
sequence: "`",
|
||||
action: "keyup",
|
||||
sequence: '`',
|
||||
action: 'keyup',
|
||||
},
|
||||
}),
|
||||
[]
|
||||
@@ -188,8 +188,8 @@ export default function NirvanaTerminal({
|
||||
<>
|
||||
<GlobalHotKeys handlers={handlers} keyMap={keyMap} allowChanges />
|
||||
|
||||
<div className="flex flex-row flex-1">
|
||||
<div className="flex flex-col bg-white w-[400px] relative group">
|
||||
<div className='flex flex-row flex-1'>
|
||||
<div className='flex flex-col bg-white w-[400px] relative group'>
|
||||
{/* modal for creating new line */}
|
||||
<NewLineModal
|
||||
open={isModalVisible}
|
||||
@@ -197,17 +197,17 @@ export default function NirvanaTerminal({
|
||||
/>
|
||||
|
||||
{/* 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 */}
|
||||
|
||||
<Tooltip placement="right" title={"These are your active rooms..."}>
|
||||
<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">
|
||||
<FiActivity className="text-sm" />
|
||||
<Tooltip placement='right' title={'These are your active rooms...'}>
|
||||
<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'>
|
||||
<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
|
||||
}/3`}</p>
|
||||
</span>
|
||||
@@ -215,7 +215,7 @@ export default function NirvanaTerminal({
|
||||
</Tooltip>
|
||||
|
||||
{/* list of toggle tuned lines */}
|
||||
<div className="flex flex-col mt-2">
|
||||
<div className='flex flex-col mt-2'>
|
||||
{toggleTunedLines.map((masterLineData) => (
|
||||
<LineRow
|
||||
key={`terminalListLines-${masterLineData.lineDetails._id.toString()}`}
|
||||
@@ -227,14 +227,14 @@ export default function NirvanaTerminal({
|
||||
</div>
|
||||
|
||||
{!(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
|
||||
instantly.
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* rest of the lines */}
|
||||
<div className={"flex flex-col"}>
|
||||
<div className={'flex flex-col'}>
|
||||
{isLoadingInitialLines ? (
|
||||
<Skeleton />
|
||||
) : (
|
||||
@@ -250,12 +250,12 @@ export default function NirvanaTerminal({
|
||||
|
||||
<div
|
||||
onClick={() => setIsModalVisible(true)}
|
||||
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"
|
||||
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'
|
||||
>
|
||||
<button
|
||||
className="flex flex-row gap-2 items-center justify-evenly
|
||||
shadow-xl bg-gray-800 p-2 text-white text-xs"
|
||||
className='flex flex-row gap-2 items-center justify-evenly
|
||||
shadow-xl bg-gray-800 p-2 text-white text-xs'
|
||||
>
|
||||
<FaPlus />
|
||||
<span>New line</span>
|
||||
@@ -270,13 +270,13 @@ export default function NirvanaTerminal({
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="flex flex-col flex-1 justify-center items-center bg-gray-100
|
||||
border-l border-l-gray-200"
|
||||
className='flex flex-col flex-1 justify-center items-center bg-gray-100
|
||||
border-l border-l-gray-200'
|
||||
>
|
||||
<span className="text-xl text-gray-800">
|
||||
<span className='text-xl text-gray-800'>
|
||||
{`Hi ${userDetails?.user?.givenName}!`}
|
||||
</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>
|
||||
@@ -293,7 +293,7 @@ function LineDetailsTerminal({
|
||||
}) {
|
||||
const { data: userDetails } = useGetUserDetails();
|
||||
|
||||
console.log("selected line", selectedLine);
|
||||
console.log('selected line', selectedLine);
|
||||
|
||||
const isUserToggleTuned = useMemo(
|
||||
() => selectedLine?.currentUserMember?.state === LineMemberState.TUNED,
|
||||
@@ -357,20 +357,20 @@ function LineDetailsTerminal({
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex flex-col flex-1 bg-gray-100
|
||||
border-l border-l-gray-200 relative"
|
||||
className='flex flex-col flex-1 bg-gray-100
|
||||
border-l border-l-gray-200 relative'
|
||||
>
|
||||
{/* line details */}
|
||||
<div
|
||||
className="p-4
|
||||
flex flex-row items-center gap-2 justify-end border-b-gray-200 border-b"
|
||||
className='p-4
|
||||
flex flex-row items-center gap-2 justify-end border-b-gray-200 border-b'
|
||||
>
|
||||
{profilePictures && (
|
||||
<LineIcon grayscale={false} sourceImages={profilePictures} />
|
||||
)}
|
||||
|
||||
<div className="flex flex-col items-start mr-auto group">
|
||||
<span className="flex flex-row gap-2 items-center">
|
||||
<div className='flex flex-col items-start mr-auto group'>
|
||||
<span className='flex flex-row gap-2 items-center'>
|
||||
<h2 className={`text-lg text-slate-800 font-semibold`}>
|
||||
{selectedLine.lineDetails.name ||
|
||||
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
|
||||
transition-all hover:scale-105`}
|
||||
>
|
||||
<FiSettings className="text-gray-400 text-xs" />
|
||||
<FiSettings className='text-gray-400 text-xs' />
|
||||
</button>
|
||||
</span>
|
||||
|
||||
<span className="flex flex-row gap-2 items-center">
|
||||
<span className="text-gray-300 text-xs">{`${
|
||||
<span className='flex flex-row gap-2 items-center'>
|
||||
<span className='text-gray-300 text-xs'>{`${
|
||||
selectedLine.otherMembers?.length + 1 ?? 0
|
||||
} members`}</span>
|
||||
<span className="h-1 w-1 bg-gray-800 rounded-full"></span>
|
||||
<span className="text-teal-500 text-xs">{`${
|
||||
<span className='h-1 w-1 bg-gray-800 rounded-full'></span>
|
||||
<span className='text-teal-500 text-xs'>{`${
|
||||
selectedLine.tunedInMemberIds?.length ?? 0
|
||||
} in this room`}</span>
|
||||
</span>
|
||||
@@ -397,15 +397,15 @@ function LineDetailsTerminal({
|
||||
|
||||
{/* TODO: move to on hover of line row */}
|
||||
<Tooltip
|
||||
placement="left"
|
||||
placement='left'
|
||||
title={`${
|
||||
isUserToggleTuned ? "click to untoggle" : "click to stay tuned in"
|
||||
isUserToggleTuned ? 'click to untoggle' : 'click to stay tuned in'
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
className={`p-2 flex justify-center items-center shadow-lg
|
||||
hover:scale-105 transition-all animate-pulse ${
|
||||
isUserToggleTuned ? "bg-gray-800 text-white" : "text-black"
|
||||
isUserToggleTuned ? 'bg-gray-800 text-white' : 'text-black'
|
||||
}`}
|
||||
onClick={() =>
|
||||
isUserToggleTuned
|
||||
@@ -419,101 +419,101 @@ function LineDetailsTerminal({
|
||||
)
|
||||
}
|
||||
>
|
||||
<FiActivity className="text-md" />
|
||||
<FiActivity className='text-md' />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{/* 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
|
||||
className={"text-gray-300 text-sm cursor-pointer hover:underline"}
|
||||
className={'text-gray-300 text-sm cursor-pointer hover:underline'}
|
||||
>
|
||||
load more
|
||||
</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) => (
|
||||
<div
|
||||
className="flex flex-row p-2 gap-2 items-center bg-transparent
|
||||
border-b border-b-gray-200 last:border-b-0"
|
||||
className='flex flex-row p-2 gap-2 items-center bg-transparent
|
||||
border-b border-b-gray-200 last:border-b-0'
|
||||
>
|
||||
<Avatar
|
||||
key={`linehistory-${1}`}
|
||||
src={otherUser.picture}
|
||||
shape="square"
|
||||
size={"default"}
|
||||
shape='square'
|
||||
size={'default'}
|
||||
// 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() * 100) + 10}pm |`}</span>
|
||||
|
||||
<span className="text-gray-400 text-md">{`${
|
||||
<span className='text-gray-400 text-md'>{`${
|
||||
Math.floor(Math.random() * 60) + 1
|
||||
} seconds`}</span>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div
|
||||
className="flex flex-row p-2 gap-2 items-center bg-transparent
|
||||
border-b border-b-gray-200 last:border-b-0"
|
||||
className='flex flex-row p-2 gap-2 items-center bg-transparent
|
||||
border-b border-b-gray-200 last:border-b-0'
|
||||
>
|
||||
<Avatar
|
||||
key={`linehistory-${1}`}
|
||||
src={userDetails.user.picture}
|
||||
shape="square"
|
||||
size={"default"}
|
||||
shape='square'
|
||||
size={'default'}
|
||||
// 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() * 100) + 10}pm |`}</span>
|
||||
|
||||
<span className="text-gray-400 text-md">{`${
|
||||
<span className='text-gray-400 text-md'>{`${
|
||||
Math.floor(Math.random() * 60) + 1
|
||||
} seconds`}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span className={"text-gray-300 text-sm"}>today</span>
|
||||
<span className={'text-gray-300 text-sm'}>today</span>
|
||||
|
||||
<div
|
||||
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) => (
|
||||
// TODO: show the shadow if it's unheard
|
||||
<div
|
||||
className="flex flex-row p-2 gap-2 items-center bg-transparent
|
||||
border-b border-b-gray-400 last:border-b-0"
|
||||
className='flex flex-row p-2 gap-2 items-center bg-transparent
|
||||
border-b border-b-gray-400 last:border-b-0'
|
||||
>
|
||||
<Avatar
|
||||
key={`linehistory-${1}`}
|
||||
src={otherUser.picture}
|
||||
shape="square"
|
||||
size={"default"}
|
||||
shape='square'
|
||||
size={'default'}
|
||||
// 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}
|
||||
</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() * 100) + 10}pm |`}</span>
|
||||
|
||||
<span className="text-gray-500 text-md">{`${
|
||||
<span className='text-gray-500 text-md'>{`${
|
||||
Math.floor(Math.random() * 60) + 1
|
||||
} seconds`}</span>
|
||||
</div>
|
||||
@@ -522,32 +522,32 @@ function LineDetailsTerminal({
|
||||
|
||||
{/* live broadcasters */}
|
||||
<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>
|
||||
<div
|
||||
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) => (
|
||||
<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
|
||||
key={`linehistory-${1}`}
|
||||
src={otherUser.picture}
|
||||
shape="square"
|
||||
size={"large"}
|
||||
shape='square'
|
||||
size={'large'}
|
||||
// grayscale if not playing?
|
||||
className={`shadow-lg`}
|
||||
/>
|
||||
<span className="text-gray-600 font-semibold">
|
||||
<span className='text-gray-600 font-semibold'>
|
||||
{otherUser.name}
|
||||
</span>
|
||||
|
||||
<Tooltip title={"audio only"}>
|
||||
<FiHeadphones className="text-gray-600 text-md ml-auto" />
|
||||
<Tooltip title={'audio only'}>
|
||||
<FiHeadphones className='text-gray-600 text-md ml-auto' />
|
||||
</Tooltip>
|
||||
</div>
|
||||
))}
|
||||
@@ -558,11 +558,11 @@ function LineDetailsTerminal({
|
||||
className={`p-3 absolute right-3 bottom-3 flex justify-center items-center shadow-2xl
|
||||
hover:scale-105 transition-all ${
|
||||
isUserBroadcasting
|
||||
? "bg-teal-800 text-white"
|
||||
: "text-teal-800 border-teal-800 border"
|
||||
? 'bg-teal-800 text-white'
|
||||
: 'text-teal-800 border-teal-800 border'
|
||||
}`}
|
||||
>
|
||||
<FiSun className="text-lg" />
|
||||
<FiSun className='text-lg' />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
+40
-40
@@ -1,12 +1,12 @@
|
||||
import { Avatar, Modal } from "antd";
|
||||
import { HotKeys, KeyMap } from "react-hotkeys";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCreateLine, useUserSearch } from "../../../controller/index";
|
||||
import { Avatar, Modal } from 'antd';
|
||||
import { HotKeys, KeyMap } from 'react-hotkeys';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useCreateLine, useUserSearch } from '../../../src/controller/index';
|
||||
|
||||
import BasicUserRow from "../../../components/User/basicUserDetailsRow";
|
||||
import { FiSearch } from "react-icons/fi";
|
||||
import { User } from "@nirvana/core/models";
|
||||
import toast from "react-hot-toast";
|
||||
import BasicUserRow from '../../components/User/basicUserDetailsRow';
|
||||
import { FiSearch } from 'react-icons/fi';
|
||||
import { User } from '@nirvana/core/models';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export default function NewLineModal({
|
||||
open,
|
||||
@@ -17,25 +17,25 @@ export default function NewLineModal({
|
||||
}) {
|
||||
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
|
||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||
const [searchQuery, setSearchQuery] = useState<string>('');
|
||||
const { refetch, data: searchRes } = useUserSearch(searchQuery);
|
||||
|
||||
const { mutateAsync, isLoading } = useCreateLine();
|
||||
|
||||
const [lineName, setLineName] = useState<string>("");
|
||||
const [lineName, setLineName] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
if (searchQuery) refetch();
|
||||
}, [searchQuery]);
|
||||
|
||||
const onSearch = useCallback(() => {
|
||||
console.log("enter key pressed");
|
||||
console.log('enter key pressed');
|
||||
|
||||
if (peopleSearchValue) {
|
||||
console.log("searching for people in database");
|
||||
console.log('searching for people in database');
|
||||
setSearchQuery(peopleSearchValue);
|
||||
}
|
||||
}, [setSearchQuery, peopleSearchValue]);
|
||||
@@ -52,7 +52,7 @@ export default function NewLineModal({
|
||||
return [...prevSelectedUsers, userToAdd];
|
||||
}
|
||||
|
||||
toast.error("you already selected this person below!");
|
||||
toast.error('you already selected this person below!');
|
||||
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
|
||||
// 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 {
|
||||
if (!selectedPeople?.length) {
|
||||
toast.error("you must select at least one person");
|
||||
toast.error('you must select at least one person');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ export default function NewLineModal({
|
||||
otherMemberIds: selectedMemberIds,
|
||||
});
|
||||
|
||||
toast.success("created line!");
|
||||
toast.success('created line!');
|
||||
|
||||
// handle close once the new line is created
|
||||
handleClose();
|
||||
@@ -103,7 +103,7 @@ export default function NewLineModal({
|
||||
toast.error(error);
|
||||
console.error(error);
|
||||
} finally {
|
||||
console.log("done");
|
||||
console.log('done');
|
||||
}
|
||||
}, [lineName, selectedPeople]);
|
||||
|
||||
@@ -112,7 +112,7 @@ export default function NewLineModal({
|
||||
};
|
||||
|
||||
const keyMap: KeyMap = {
|
||||
HANDLE_SEARCH: "enter",
|
||||
HANDLE_SEARCH: 'enter',
|
||||
};
|
||||
const handlers = {
|
||||
HANDLE_SEARCH: onSearch,
|
||||
@@ -123,49 +123,49 @@ export default function NewLineModal({
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
title="Create a Line"
|
||||
title='Create a Line'
|
||||
visible={open}
|
||||
onCancel={handleCancel}
|
||||
footer={
|
||||
<div className="flex flex-row text-white">
|
||||
<div className='flex flex-row text-white'>
|
||||
<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}
|
||||
>
|
||||
Cancel
|
||||
</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}
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
className={"flex flex-col gap-5"}
|
||||
className={'flex flex-col gap-5'}
|
||||
>
|
||||
<HotKeys handlers={handlers} keyMap={keyMap} allowChanges={true}>
|
||||
<div className="flex flex-col items-start gap-2 mb-5">
|
||||
<p className="text-gray-300 text-sm">People</p>
|
||||
<div className='flex flex-col items-start gap-2 mb-5'>
|
||||
<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">
|
||||
<FiSearch className="text-gray-300" />
|
||||
<span className='flex flex-row gap-1 w-full items-center border border-gray-200 p-2 shadow'>
|
||||
<FiSearch className='text-gray-300' />
|
||||
|
||||
<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}
|
||||
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
|
||||
</span>
|
||||
</span>
|
||||
|
||||
{/* search results */}
|
||||
{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) => (
|
||||
<BasicUserRow
|
||||
key={`searchResUser-${searchedUser.googleId}`}
|
||||
@@ -183,10 +183,10 @@ export default function NewLineModal({
|
||||
|
||||
{/* selected people */}
|
||||
{selectedPeople?.length > 0 && (
|
||||
<div className="flex flex-col gap-2 mb-5">
|
||||
<p className="text-gray-300 text-sm">Selected People</p>
|
||||
<div className='flex flex-col gap-2 mb-5'>
|
||||
<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) => (
|
||||
<BasicUserRow
|
||||
key={`selectedUser-${selectedUser.googleId}`}
|
||||
@@ -206,14 +206,14 @@ export default function NewLineModal({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-gray-300 text-sm">Line Name (optional)</p>
|
||||
<div className='flex flex-col gap-2'>
|
||||
<p className='text-gray-300 text-sm'>Line Name (optional)</p>
|
||||
<input
|
||||
value={lineName}
|
||||
onChange={(e) => setLineName(e.target.value)}
|
||||
className="placeholder:text-gray-300 outline-none placeholder:text-sm flex-1
|
||||
border p-2 border-gray-200"
|
||||
placeholder={"ex. Engineering, Sprint 7, Follow up on present..."}
|
||||
className='placeholder:text-gray-300 outline-none placeholder:text-sm flex-1
|
||||
border p-2 border-gray-200'
|
||||
placeholder={'ex. Engineering, Sprint 7, Follow up on present...'}
|
||||
/>
|
||||
</div>
|
||||
</HotKeys>
|
||||
Reference in New Issue
Block a user