From 522cf40cf7c9a692d948eb088d14604b6121b1bb Mon Sep 17 00:00:00 2001 From: talksik Date: Mon, 30 May 2022 10:45:58 -0500 Subject: [PATCH] nirvana support really awesome right there! --- .../src/components/ConversationDetails.tsx | 34 +++-- .../src/components/ConversationList.tsx | 38 +++--- .../desktop/src/components/FooterControls.tsx | 68 ++++------ packages/desktop/src/components/Terminal.tsx | 128 ++++++------------ packages/desktop/src/firebase/firestore.ts | 58 ++++---- packages/desktop/src/util/text.ts | 7 + 6 files changed, 147 insertions(+), 186 deletions(-) create mode 100644 packages/desktop/src/util/text.ts diff --git a/packages/desktop/src/components/ConversationDetails.tsx b/packages/desktop/src/components/ConversationDetails.tsx index a31a10a..72f477f 100644 --- a/packages/desktop/src/components/ConversationDetails.tsx +++ b/packages/desktop/src/components/ConversationDetails.tsx @@ -1,25 +1,33 @@ -/* eslint-disable jsx-a11y/media-has-caption */ -import { blueGrey } from '@mui/material/colors'; -import React, { useState, useEffect, useMemo } from 'react'; -import { joinConversation, leaveConversation } from '../firebase/firestore'; -import useAuth from '../providers/AuthProvider'; -import { useImmer } from 'use-immer'; -import useTerminal from './Terminal'; -import { User } from '@nirvana/core/src/models/user.model'; import { - Stack, - IconButton, - Typography, - AvatarGroup, Avatar, + AvatarGroup, Box, Container, Fab, + IconButton, Paper, + Stack, + Typography, } from '@mui/material'; -import { FiSun, FiMoreVertical, FiPlay, FiCloudRain } from 'react-icons/fi'; +import { FiCloudRain, FiMoreVertical, FiPlay, FiSun } from 'react-icons/fi'; +import React, { useEffect, useMemo, useState } from 'react'; +import { joinConversation, leaveConversation } from '../firebase/firestore'; + import ConversationLabel from '../subcomponents/ConversationLabel'; +import { User } from '@nirvana/core/src/models/user.model'; +/* eslint-disable jsx-a11y/media-has-caption */ +import { blueGrey } from '@mui/material/colors'; +import useAuth from '../providers/AuthProvider'; +import { useImmer } from 'use-immer'; import { useRendersCount } from 'react-use'; +import useTerminal from './Terminal'; + +/** + * nice convo history + * - chunk has max of 1 minute + * - put current clip in next chunk if previous clip was more than 4 hours ago + * - put current clip in next chunk if it's after my last active date here + */ export default function ConversationDetails() { const { user } = useAuth(); diff --git a/packages/desktop/src/components/ConversationList.tsx b/packages/desktop/src/components/ConversationList.tsx index 98cf19f..22cbc4f 100644 --- a/packages/desktop/src/components/ConversationList.tsx +++ b/packages/desktop/src/components/ConversationList.tsx @@ -1,38 +1,40 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; - import { Avatar, + AvatarGroup, Badge, + Box, + CircularProgress, Divider, + IconButton, + Input, List, ListItem, ListItemAvatar, ListItemButton, + ListItemSecondaryAction, ListItemText, ListSubheader, Stack, - Typography, - Input, - CircularProgress, - IconButton, - Box, Tooltip, - ListItemSecondaryAction, - AvatarGroup, + Typography, } from '@mui/material'; -import { blueGrey } from '@mui/material/colors'; -import { FiActivity, FiInbox, FiSearch, FiUsers, FiCoffee, FiCircle, FiSun } from 'react-icons/fi'; -import NirvanaAvatar from './NirvanaAvatar'; +import { FiActivity, FiCircle, FiCoffee, FiInbox, FiSearch, FiSun, FiUsers } from 'react-icons/fi'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useDebounce, useKey, useRendersCount } from 'react-use'; -import { useSnackbar } from 'notistack'; -import KeyboardShortcutLabel from './KeyboardShortcutLabel'; -import { searchUsers } from '../firebase/firestore'; -import { User } from '@nirvana/core/src/models/user.model'; -import useTerminal from './Terminal'; + import Conversation from '@nirvana/core/src/models/conversation.model'; +import ConversationLabel from '../subcomponents/ConversationLabel'; +import KeyboardShortcutLabel from './KeyboardShortcutLabel'; +import NirvanaAvatar from './NirvanaAvatar'; +import { User } from '@nirvana/core/src/models/user.model'; +import { blueGrey } from '@mui/material/colors'; +import { searchUsers } from '../firebase/firestore'; import useAuth from '../providers/AuthProvider'; import { useImmer } from 'use-immer'; -import ConversationLabel from '../subcomponents/ConversationLabel'; +import { useSnackbar } from 'notistack'; +import useTerminal from './Terminal'; + +// sort conversations based on the different data sources: type, conversations, audio clips, etc. /** * diff --git a/packages/desktop/src/components/FooterControls.tsx b/packages/desktop/src/components/FooterControls.tsx index e515c4e..bf75356 100644 --- a/packages/desktop/src/components/FooterControls.tsx +++ b/packages/desktop/src/components/FooterControls.tsx @@ -1,28 +1,29 @@ import { - Box, - Stack, - IconButton, Avatar, - Tooltip, - Switch, - Button, AvatarGroup, + Box, + Button, + Divider, Fab, + IconButton, ListItemIcon, - Typography, Menu, MenuItem, + Stack, + Switch, + Tooltip, + Typography, } from '@mui/material'; -import { blueGrey } from '@mui/material/colors'; +import { FiHeadphones, FiHelpCircle, FiLogOut, FiSun } from 'react-icons/fi'; +import React, { useCallback } from 'react'; -import React from 'react'; -import { FiHeadphones, FiSun, FiLogOut } from 'react-icons/fi'; import ConversationLabel from '../subcomponents/ConversationLabel'; -import useTerminal from './Terminal'; +import { blueGrey } from '@mui/material/colors'; import useAuth from '../providers/AuthProvider'; +import useTerminal from './Terminal'; export default function FooterControls() { - const { selectedConversation } = useTerminal(); + const { selectedConversation, handleOmniSearch } = useTerminal(); const { user, logout } = useAuth(); const [anchorEl, setAnchorEl] = React.useState(null); @@ -34,6 +35,10 @@ export default function FooterControls() { setAnchorEl(null); }; + const handleQuickDialSupport = useCallback(() => { + handleOmniSearch('Nirvana Support'); + }, [handleOmniSearch]); + return ( + + + + + Help + + + diff --git a/packages/desktop/src/components/Terminal.tsx b/packages/desktop/src/components/Terminal.tsx index a7a1242..b051b63 100644 --- a/packages/desktop/src/components/Terminal.tsx +++ b/packages/desktop/src/components/Terminal.tsx @@ -1,36 +1,32 @@ -import React, { useContext, useState, useCallback, useMemo, useEffect } from 'react'; - import { Avatar, + AvatarGroup, Box, + Button, + Dialog, + Divider, + Fab, Grid, IconButton, - Tooltip, - Stack, - Divider, List, ListItem, ListItemAvatar, - Button, ListItemButton, + ListItemIcon, ListItemSecondaryAction, ListItemText, ListSubheader, - Typography, Menu, MenuItem, - ListItemIcon, - Fab, + Stack, Switch, - Dialog, - AvatarGroup, + Tooltip, + Typography, } from '@mui/material'; -import { blueGrey } from '@mui/material/colors'; -import { FiZap, FiHeadphones, FiLogOut, FiMonitor, FiSun } from 'react-icons/fi'; -import { useSnackbar } from 'notistack'; - -import Conversation from '@nirvana/core/src/models/conversation.model'; -import useAuth from '../providers/AuthProvider'; +import { ContentBlock, ContentType } from '@nirvana/core/src/models/content.model'; +import { FiHeadphones, FiLogOut, FiMonitor, FiSun, FiZap } from 'react-icons/fi'; +import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; +import { Unsubscribe, onSnapshot } from 'firebase/firestore'; import { createOneOnOneConversation, getConversationContentQueryLIVE, @@ -39,21 +35,23 @@ import { searchUsers, sendContentBlockToConversation, } from '../firebase/firestore'; -import { useImmer } from 'use-immer'; -import { User } from '@nirvana/core/src/models/user.model'; -import { onSnapshot, Unsubscribe } from 'firebase/firestore'; - import { useDebounce, useKeyPressEvent, useRendersCount, useUnmount } from 'react-use'; -import { uploadAudioClip } from '../firebase/firebaseStorage'; -import { ContentBlock, ContentType } from '@nirvana/core/src/models/content.model'; -import Navbar from './Navbar'; -import MainPanel from './MainPanel'; -import { ConversationList } from './ConversationList'; -import NewConversationDialog from './NewConversationDialog'; -import { createGroupConversation } from '../firebase/firestore'; +import Conversation from '@nirvana/core/src/models/conversation.model'; import ConversationLabel from '../subcomponents/ConversationLabel'; +import { ConversationList } from './ConversationList'; import FooterControls from './FooterControls'; +import MainPanel from './MainPanel'; +import Navbar from './Navbar'; +import NewConversationDialog from './NewConversationDialog'; +import { User } from '@nirvana/core/src/models/user.model'; +import { blueGrey } from '@mui/material/colors'; +import { createGroupConversation } from '../firebase/firestore'; +import { uploadAudioClip } from '../firebase/firebaseStorage'; +import useAuth from '../providers/AuthProvider'; +import { useImmer } from 'use-immer'; +import { useSnackbar } from 'notistack'; + type ConversationMap = { [conversationId: string]: Conversation; }; @@ -84,6 +82,8 @@ interface ITerminalContext { handleShowCreateConvoForm?: () => void; handleEscape?: () => void; + + handleOmniSearch?: (searchQuery: string) => void; // handle searching for anything globally } const TerminalContext = React.createContext({ @@ -106,60 +106,6 @@ const handleOnStartRecording = (e: BlobEvent) => { audioChunks = []; }; -// TODOS -// fetch all conversations that I am part of - -// create a convo -// 1. search -// 2. click on person -// 3. search database if there is already a convo for this -// - if yes: select this one -// - if no: create one -// 4. show the conversation details page show on right -// 5. connect live if other person there -// 6. send first clip -// 7. display all blocks/clips for convo simple and separate - -// if no conversations, show stale state + create one with nirvana - -// 1. create group conversation page -// you know what to do...simple row of selected users...dropdown options should show searched user list -// use material selects for this dropdown to avoid all the work...and hide select-like things -// 2. auto select that conversation and have it show up -// 3. allow adding name when creating convo -// 4. -// 5. convo settings: add people (simple add method with firestore), change name | max 8 people - -/** - * Streaming stuff: - * - join a stream room if 2 or more in the list - * - leave on unmount - * - timer to unselect a conversation after 30 minutes...no fancy checking if user is there/active - * - show little control to see if - */ - -/** - * - * media stuff: - * - paste image + view in history + with modal nice and big - * - paste a link + see in a content block - * - paste link of image and have it save as image - */ - -/** - * - * tech debt: now go back and make convo line and side panel name and icons and all legit - */ - -/** - * nice convo history - * - chunk has max of 1 minute - * - put current clip in next chunk if previous clip was more than 4 hours ago - * - put current clip in next chunk if it's after my last active date here - */ - -// sort based on the different data sources: conversations, audio clips, etc. - // todo: extract each use effect to custom hook and will be clean export function TerminalProvider({ children }: { children?: React.ReactNode }) { const { enqueueSnackbar } = useSnackbar(); @@ -493,14 +439,25 @@ export function TerminalProvider({ children }: { children?: React.ReactNode }) { [searchVal, enqueueSnackbar, setSearchUsersResults, user], ); - const handleChangeSearchInput = useCallback( - (e: React.ChangeEvent) => { + const handleOmniSearch = useCallback( + (searchQuery: string) => { + if (!searchQuery) { + return; + } + setSearching(true); - setSearchVal(e.target.value.replace('/', '')); + setSearchVal(searchQuery.replace('/', '')); }, [setSearching, setSearchVal], ); + const handleChangeSearchInput = useCallback( + (e: React.ChangeEvent) => { + handleOmniSearch(e.target.value); + }, + [handleOmniSearch], + ); + const selectConversation = useCallback( (conversationId: string) => setSelectedConversationId(conversationId), [setSelectedConversationId], @@ -571,6 +528,7 @@ export function TerminalProvider({ children }: { children?: React.ReactNode }) { createConversationMode, handleShowCreateConvoForm, handleEscape, + handleOmniSearch, }} > diff --git a/packages/desktop/src/firebase/firestore.ts b/packages/desktop/src/firebase/firestore.ts index 3f416df..dd6c462 100644 --- a/packages/desktop/src/firebase/firestore.ts +++ b/packages/desktop/src/firebase/firestore.ts @@ -1,39 +1,40 @@ //TODO: move all of this to core or common and separate out files -import { - setDoc, - getFirestore, - doc, - collection, - QueryDocumentSnapshot, - Timestamp, - FieldValue, - getDoc, - query, - where, - getDocs, - orderBy, - limit, - startAt, - endAt, - addDoc, - arrayUnion, - updateDoc, - arrayRemove, - serverTimestamp, -} from 'firebase/firestore'; - -import { User as FirebaseUser } from 'firebase/auth'; -import { firestoreDb } from './connect'; -import { User } from '@nirvana/core/src/models/user.model'; import Conversation, { ConversationMember, MemberMap, MemberRole, MemberState, } from '@nirvana/core/src/models/conversation.model'; -import useAuth from '../providers/AuthProvider'; +import { + FieldValue, + QueryDocumentSnapshot, + Timestamp, + addDoc, + arrayRemove, + arrayUnion, + collection, + doc, + endAt, + getDoc, + getDocs, + getFirestore, + limit, + orderBy, + query, + serverTimestamp, + setDoc, + startAt, + updateDoc, + where, +} from 'firebase/firestore'; + import { ContentBlock } from '@nirvana/core/src/models/content.model'; +import { User as FirebaseUser } from 'firebase/auth'; +import { User } from '@nirvana/core/src/models/user.model'; +import { firestoreDb } from './connect'; +import { toTitleCase } from '../util/text'; +import useAuth from '../providers/AuthProvider'; interface Document { id: string; @@ -108,8 +109,7 @@ export const searchUsers = async (searchQuery: string): Promise { + return str + .toLowerCase() + .split(' ') + .map((s) => s.charAt(0).toUpperCase() + s.substring(1)) + .join(' '); +};