nirvana support really awesome right there!
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -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 | HTMLElement>(null);
|
||||
@@ -34,6 +35,10 @@ export default function FooterControls() {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleQuickDialSupport = useCallback(() => {
|
||||
handleOmniSearch('Nirvana Support');
|
||||
}, [handleOmniSearch]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
@@ -158,36 +163,17 @@ export default function FooterControls() {
|
||||
id="account-menu"
|
||||
open={open}
|
||||
onClose={handleCloseProfileMenu}
|
||||
onClick={handleCloseProfileMenu}
|
||||
PaperProps={{
|
||||
elevation: 0,
|
||||
sx: {
|
||||
overflow: 'visible',
|
||||
filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))',
|
||||
mt: 1.5,
|
||||
'& .MuiAvatar-root': {
|
||||
width: 32,
|
||||
height: 32,
|
||||
ml: -0.5,
|
||||
mr: 1,
|
||||
},
|
||||
'&:before': {
|
||||
content: '""',
|
||||
display: 'block',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 14,
|
||||
width: 10,
|
||||
height: 10,
|
||||
bgcolor: 'background.paper',
|
||||
transform: 'translateY(-50%) rotate(45deg)',
|
||||
zIndex: 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||
transformOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||
>
|
||||
<MenuItem onClick={handleQuickDialSupport}>
|
||||
<ListItemIcon>
|
||||
<FiHelpCircle />
|
||||
</ListItemIcon>
|
||||
<Typography>Help</Typography>
|
||||
</MenuItem>
|
||||
|
||||
<Divider />
|
||||
<MenuItem onClick={logout}>
|
||||
<ListItemIcon>
|
||||
<FiLogOut />
|
||||
|
||||
@@ -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<ITerminalContext>({
|
||||
@@ -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<HTMLInputElement>) => {
|
||||
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<HTMLInputElement>) => {
|
||||
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,
|
||||
}}
|
||||
>
|
||||
<Stack direction={'column'} sx={{ flex: 1 }}>
|
||||
|
||||
@@ -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<User[] | undefin
|
||||
limit(5),
|
||||
);
|
||||
|
||||
const nameManipulatedQuery =
|
||||
searchQuery[0].toUpperCase() + searchQuery.slice(1).toLocaleLowerCase();
|
||||
const nameManipulatedQuery = toTitleCase(searchQuery);
|
||||
const nameSearchQuery = query(
|
||||
db.users,
|
||||
orderBy('displayName'),
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export const toTitleCase = (str: string) => {
|
||||
return str
|
||||
.toLowerCase()
|
||||
.split(' ')
|
||||
.map((s) => s.charAt(0).toUpperCase() + s.substring(1))
|
||||
.join(' ');
|
||||
};
|
||||
Reference in New Issue
Block a user