more top down but not perfect and optimized
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
import { Line, LineMember } from "./line.model";
|
import { Line, LineMember } from './line.model';
|
||||||
|
|
||||||
import AudioClip from "./audioClip.model";
|
import AudioClip from './audioClip.model';
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from 'mongodb';
|
||||||
import { User } from "./user.model";
|
import { User } from './user.model';
|
||||||
|
|
||||||
// why do we have separate full objects being sent?
|
// why do we have separate full objects being sent?
|
||||||
// speed...I'm developing full stack and I just want all of the data and don't want to change this model
|
// speed...I'm developing full stack and I just want all of the data and don't want to change this model
|
||||||
@@ -24,6 +24,18 @@ export default class MasterLineData {
|
|||||||
// -> all connected line members be able to show this in the right activity section of the lineRow
|
// -> all connected line members be able to show this in the right activity section of the lineRow
|
||||||
currentBroadcastersUserIds?: string[];
|
currentBroadcastersUserIds?: string[];
|
||||||
|
|
||||||
|
profilePictures: {
|
||||||
|
allMembers: string[];
|
||||||
|
allMembersWithoutMe: string[];
|
||||||
|
|
||||||
|
untunedMembers: string[];
|
||||||
|
|
||||||
|
tunedMembers: string[];
|
||||||
|
broadcastMembers: string[];
|
||||||
|
};
|
||||||
|
isUserTunedIn: boolean = false;
|
||||||
|
isUserToggleTuned: boolean = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
// full line object
|
// full line object
|
||||||
public lineDetails: Line,
|
public lineDetails: Line,
|
||||||
@@ -34,6 +46,6 @@ export default class MasterLineData {
|
|||||||
// all other members in the convo as well as their user object to see the member details
|
// all other members in the convo as well as their user object to see the member details
|
||||||
public otherMembers?: LineMember[],
|
public otherMembers?: LineMember[],
|
||||||
|
|
||||||
public otherUserObjects?: User[] /**public audioClips: AudioClip[] = [], // public media: Media[] */
|
public otherUserObjects?: User[] /**public audioClips: AudioClip[] = [], // public media: Media[] */,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ type BroadcastersMap = {
|
|||||||
|
|
||||||
interface ITerminalProvider {
|
interface ITerminalProvider {
|
||||||
roomsMap: LineIdToMasterLine;
|
roomsMap: LineIdToMasterLine;
|
||||||
|
|
||||||
allChannels: MasterLineData[];
|
allChannels: MasterLineData[];
|
||||||
|
|
||||||
selectedLineId?: string;
|
selectedLineId?: string;
|
||||||
@@ -363,7 +364,9 @@ export function TerminalProvider({ children }: { children: React.ReactChild }) {
|
|||||||
|
|
||||||
// todo: sort based on content blocks and my last activity date
|
// todo: sort based on content blocks and my last activity date
|
||||||
const allChannels = useMemo(() => {
|
const allChannels = useMemo(() => {
|
||||||
let channels = Object.values(roomMap);
|
let channels: MasterLineData[] = Object.values(roomMap);
|
||||||
|
|
||||||
|
channels = channels.map((currChann) => Object.assign({}, currChann, MasterLineData));
|
||||||
|
|
||||||
if (desktopMode === 'overlayOnly') {
|
if (desktopMode === 'overlayOnly') {
|
||||||
channels = channels.filter((currentChannel) =>
|
channels = channels.filter((currentChannel) =>
|
||||||
@@ -391,6 +394,49 @@ export function TerminalProvider({ children }: { children: React.ReactChild }) {
|
|||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
channels.forEach((currChannel) => {
|
||||||
|
currChannel.isUserTunedIn = currChannel.tunedInMemberIds?.includes(user._id.toString())
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
|
||||||
|
currChannel.isUserToggleTuned = currChannel.currentUserMember.state === LineMemberState.TUNED;
|
||||||
|
|
||||||
|
const allMembers: string[] = [];
|
||||||
|
const allMembersWithoutMe: string[] = [];
|
||||||
|
const tunedMembers: string[] = [];
|
||||||
|
const broadcastMembers: string[] = [];
|
||||||
|
const untunedMembers: string[] = [];
|
||||||
|
|
||||||
|
// ?don't add in my image as that's useless contextually?
|
||||||
|
if (user.picture) allMembers.push(user.picture);
|
||||||
|
|
||||||
|
currChannel.otherUserObjects?.forEach((otherUser) => {
|
||||||
|
if (otherUser.picture) {
|
||||||
|
allMembers.push(otherUser.picture);
|
||||||
|
allMembersWithoutMe.push(otherUser.picture);
|
||||||
|
|
||||||
|
if (currChannel.tunedInMemberIds?.includes(otherUser._id.toString())) {
|
||||||
|
tunedMembers.push(otherUser.picture);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (currChannel.currentBroadcastersUserIds?.includes(otherUser._id.toString())) {
|
||||||
|
broadcastMembers.push(otherUser.picture);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
untunedMembers.push(otherUser.picture);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currChannel.profilePictures = {
|
||||||
|
untunedMembers,
|
||||||
|
allMembers,
|
||||||
|
tunedMembers,
|
||||||
|
broadcastMembers,
|
||||||
|
allMembersWithoutMe,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return channels;
|
return channels;
|
||||||
}, [roomMap, desktopMode, user]);
|
}, [roomMap, desktopMode, user]);
|
||||||
|
|
||||||
@@ -402,6 +448,7 @@ export function TerminalProvider({ children }: { children: React.ReactChild }) {
|
|||||||
[allChannels],
|
[allChannels],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// !Caution: the roommap won't have the additional properties as allChannels does
|
||||||
return (
|
return (
|
||||||
<TerminalContext.Provider
|
<TerminalContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|||||||
@@ -24,9 +24,13 @@ import Peer from 'simple-peer';
|
|||||||
export default function LineDetails() {
|
export default function LineDetails() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
|
||||||
const { selectedLineId, roomsMap, handleUpdateLineMemberState } = useTerminalProvider();
|
const { selectedLineId, allChannels, handleUpdateLineMemberState } = useTerminalProvider();
|
||||||
|
|
||||||
const selectedLine = useMemo(() => roomsMap[selectedLineId], [selectedLineId, roomsMap]);
|
const selectedLine = useMemo(
|
||||||
|
() =>
|
||||||
|
allChannels.find((currChannel) => currChannel.lineDetails._id.toString() === selectedLineId),
|
||||||
|
[selectedLineId, allChannels],
|
||||||
|
);
|
||||||
|
|
||||||
const isUserToggleTuned = useMemo(
|
const isUserToggleTuned = useMemo(
|
||||||
() => selectedLine?.currentUserMember?.state === LineMemberState.TUNED,
|
() => selectedLine?.currentUserMember?.state === LineMemberState.TUNED,
|
||||||
@@ -35,56 +39,11 @@ export default function LineDetails() {
|
|||||||
|
|
||||||
const { peerMap } = useStreams();
|
const { peerMap } = useStreams();
|
||||||
|
|
||||||
// seeing if I am in the list of broadcasters
|
|
||||||
// the source of truth from the socket connections telling me if my clicking actually made a round trip
|
|
||||||
const isUserBroadcasting = useMemo(
|
const isUserBroadcasting = useMemo(
|
||||||
() => selectedLine?.currentBroadcastersUserIds?.includes(user._id.toString()),
|
() => selectedLine?.currentBroadcastersUserIds?.includes(user._id.toString()),
|
||||||
[user, selectedLine],
|
[user, selectedLine],
|
||||||
);
|
);
|
||||||
|
|
||||||
// showing all tuned in members...they may not hear me since they might be doing something else
|
|
||||||
// but feeling of presentness
|
|
||||||
const tunedProfiles = useMemo(() => {
|
|
||||||
const pictureSources: { name: string; pictureSrc: string }[] = [];
|
|
||||||
|
|
||||||
selectedLine.tunedInMemberIds?.forEach((tunedInMemberUserId) => {
|
|
||||||
// don't want to see my own picture
|
|
||||||
// TODO: don't show myself!?
|
|
||||||
if (tunedInMemberUserId === user._id.toString()) {
|
|
||||||
pictureSources.push({
|
|
||||||
name: user.givenName,
|
|
||||||
pictureSrc: user.picture,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const otherUserObject = selectedLine.otherUserObjects?.find(
|
|
||||||
(userObj) => userObj._id.toString() === tunedInMemberUserId,
|
|
||||||
);
|
|
||||||
if (otherUserObject?.picture)
|
|
||||||
pictureSources.push({
|
|
||||||
name: otherUserObject.givenName,
|
|
||||||
pictureSrc: otherUserObject.picture,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return pictureSources;
|
|
||||||
}, [selectedLine, user]);
|
|
||||||
|
|
||||||
// pics for the line icons
|
|
||||||
const profilePictures = useMemo(() => {
|
|
||||||
const pictureSources: string[] = [];
|
|
||||||
|
|
||||||
// ?don't add in my image as that's useless contextually?
|
|
||||||
// if (userData?.user?.picture) pictureSources.push(userData.user.picture);
|
|
||||||
|
|
||||||
selectedLine.otherUserObjects?.forEach((otherUser) => {
|
|
||||||
if (otherUser.picture) pictureSources.push(otherUser.picture);
|
|
||||||
});
|
|
||||||
|
|
||||||
return pictureSources;
|
|
||||||
}, [selectedLine]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col flex-1 bg-white relative overflow-auto">
|
<div className="flex flex-col flex-1 bg-white relative overflow-auto">
|
||||||
{/* line details */}
|
{/* line details */}
|
||||||
@@ -92,7 +51,17 @@ export default function LineDetails() {
|
|||||||
className="p-5 z-30 titlebar
|
className="p-5 z-30 titlebar
|
||||||
flex flex-row items-center justify-end border-b-gray-200 border-b shadow-2xl group"
|
flex flex-row items-center justify-end border-b-gray-200 border-b shadow-2xl group"
|
||||||
>
|
>
|
||||||
{profilePictures && <LineIcon grayscale={false} sourceImages={profilePictures} />}
|
{/* channel picture */}
|
||||||
|
{selectedLine.profilePictures && (
|
||||||
|
<LineIcon
|
||||||
|
grayscale={!selectedLine.isUserTunedIn}
|
||||||
|
sourceImages={
|
||||||
|
selectedLine.profilePictures.tunedMembers.length > 0
|
||||||
|
? selectedLine.profilePictures.tunedMembers
|
||||||
|
: selectedLine.profilePictures.allMembersWithoutMe
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="ml-2 mr-auto flex flex-col items-start ">
|
<div className="ml-2 mr-auto flex flex-col items-start ">
|
||||||
<span className="flex flex-row gap-2 items-center">
|
<span className="flex flex-row gap-2 items-center">
|
||||||
@@ -110,10 +79,10 @@ export default function LineDetails() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Avatar.Group className={'animate-pulse'}>
|
<Avatar.Group className={'animate-pulse'}>
|
||||||
{tunedProfiles.map((otherUser) => (
|
{selectedLine.profilePictures?.tunedMembers?.map((pictureSrc, index) => (
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`lineTunedInUserAvatar-${otherUser.name}`}
|
key={`lineTunedInUserAvatar-${index}`}
|
||||||
src={otherUser.pictureSrc}
|
src={pictureSrc}
|
||||||
shape="square"
|
shape="square"
|
||||||
size={'large'}
|
size={'large'}
|
||||||
className={`shadow-lg`}
|
className={`shadow-lg`}
|
||||||
@@ -124,14 +93,14 @@ export default function LineDetails() {
|
|||||||
<span className="px-10 text-gray-200"> | </span>
|
<span className="px-10 text-gray-200"> | </span>
|
||||||
|
|
||||||
<Avatar.Group>
|
<Avatar.Group>
|
||||||
{selectedLine.otherUserObjects.map((otherUser) => (
|
{selectedLine.profilePictures.untunedMembers.map((pictureSrc, index) => (
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`lineOfflineUserAvatar-${1}`}
|
key={`lineOfflineUserAvatar-${index}`}
|
||||||
src={otherUser.picture}
|
src={pictureSrc}
|
||||||
shape="square"
|
shape="square"
|
||||||
size={'default'}
|
size={'default'}
|
||||||
// grayscale if not playing?
|
// grayscale if not playing?
|
||||||
className={`${true && 'grayscale'}`}
|
className={`grayscale`}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Avatar.Group>
|
</Avatar.Group>
|
||||||
|
|||||||
@@ -25,16 +25,6 @@ export default React.memo(function LineRow({
|
|||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { desktopMode, isWindowFocused } = useElectron();
|
const { desktopMode, isWindowFocused } = useElectron();
|
||||||
|
|
||||||
const isUserTunedIn = useMemo(
|
|
||||||
() => line.tunedInMemberIds?.includes(user._id.toString()),
|
|
||||||
[line.tunedInMemberIds, user],
|
|
||||||
);
|
|
||||||
|
|
||||||
const isUserToggleTuned = useMemo(
|
|
||||||
() => line?.currentUserMember?.state === LineMemberState.TUNED,
|
|
||||||
[line],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleActivateLine = useCallback(() => {
|
const handleActivateLine = useCallback(() => {
|
||||||
handleSelectLine(line.lineDetails._id.toString());
|
handleSelectLine(line.lineDetails._id.toString());
|
||||||
}, [handleSelectLine, line.lineDetails, index]);
|
}, [handleSelectLine, line.lineDetails, index]);
|
||||||
@@ -49,43 +39,6 @@ export default React.memo(function LineRow({
|
|||||||
|
|
||||||
useKeyPressEvent((index + 1).toString(), hotkeyActivateLine);
|
useKeyPressEvent((index + 1).toString(), hotkeyActivateLine);
|
||||||
|
|
||||||
const profilePictures = useMemo(() => {
|
|
||||||
const allMembers: string[] = [];
|
|
||||||
const allMembersWithoutMe: string[] = [];
|
|
||||||
const tunedMembers: string[] = [];
|
|
||||||
const broadcastMembers: string[] = [];
|
|
||||||
const untunedMembers: string[] = [];
|
|
||||||
|
|
||||||
// ?don't add in my image as that's useless contextually?
|
|
||||||
if (user.picture) allMembers.push(user.picture);
|
|
||||||
|
|
||||||
line.otherUserObjects?.forEach((otherUser) => {
|
|
||||||
if (otherUser.picture) {
|
|
||||||
allMembers.push(otherUser.picture);
|
|
||||||
allMembersWithoutMe.push(otherUser.picture);
|
|
||||||
|
|
||||||
if (line.tunedInMemberIds?.includes(otherUser._id.toString())) {
|
|
||||||
tunedMembers.push(otherUser.picture);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (line.currentBroadcastersUserIds?.includes(otherUser._id.toString())) {
|
|
||||||
broadcastMembers.push(otherUser.picture);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
untunedMembers.push(otherUser.picture);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
untunedMembers,
|
|
||||||
allMembers,
|
|
||||||
tunedMembers,
|
|
||||||
broadcastMembers,
|
|
||||||
allMembersWithoutMe,
|
|
||||||
};
|
|
||||||
}, [line, user]);
|
|
||||||
|
|
||||||
const renderRightActivity = useMemo(() => {
|
const renderRightActivity = useMemo(() => {
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
return (
|
return (
|
||||||
@@ -97,7 +50,7 @@ export default React.memo(function LineRow({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profilePictures.broadcastMembers.length > 0)
|
if (line.profilePictures.broadcastMembers.length > 0)
|
||||||
return (
|
return (
|
||||||
<Avatar.Group
|
<Avatar.Group
|
||||||
maxCount={2}
|
maxCount={2}
|
||||||
@@ -111,7 +64,7 @@ export default React.memo(function LineRow({
|
|||||||
}}
|
}}
|
||||||
className="shadow-lg"
|
className="shadow-lg"
|
||||||
>
|
>
|
||||||
{profilePictures.broadcastMembers.map((pictureSrc, index) => (
|
{line.profilePictures.broadcastMembers.map((pictureSrc, index) => (
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`lineRowActiveBroadcasters-${index}`}
|
key={`lineRowActiveBroadcasters-${index}`}
|
||||||
src={pictureSrc}
|
src={pictureSrc}
|
||||||
@@ -122,7 +75,7 @@ export default React.memo(function LineRow({
|
|||||||
</Avatar.Group>
|
</Avatar.Group>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (profilePictures.tunedMembers.length > 0)
|
if (line.profilePictures.tunedMembers.length > 0)
|
||||||
return <FiSun className="text-teal-500 animate-pulse" />;
|
return <FiSun className="text-teal-500 animate-pulse" />;
|
||||||
|
|
||||||
// if there is new activity blocks for me
|
// if there is new activity blocks for me
|
||||||
@@ -142,7 +95,7 @@ export default React.memo(function LineRow({
|
|||||||
{moment(line.currentUserMember.lastVisitDate).fromNow(true)}
|
{moment(line.currentUserMember.lastVisitDate).fromNow(true)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}, [line, isSelected, profilePictures]);
|
}, [line, isSelected]);
|
||||||
|
|
||||||
// TODO: low priority: scale the whole thing and make it pop out nad translate...
|
// TODO: low priority: scale the whole thing and make it pop out nad translate...
|
||||||
// doesn't work right now because no workaround for overflow scroll for y and visible for x
|
// doesn't work right now because no workaround for overflow scroll for y and visible for x
|
||||||
@@ -153,19 +106,19 @@ export default React.memo(function LineRow({
|
|||||||
className={`flex flex-row items-center justify-start gap-2 px-4 py-4 hover:bg-gray-200
|
className={`flex flex-row items-center justify-start gap-2 px-4 py-4 hover:bg-gray-200
|
||||||
cursor-pointer transition-all relative z-50
|
cursor-pointer transition-all relative z-50
|
||||||
|
|
||||||
${isUserToggleTuned && ' bg-gray-100'}
|
${line.isUserToggleTuned && ' bg-gray-100'}
|
||||||
|
|
||||||
${isUserTunedIn && isSelected && ' bg-gray-100 shadow-2xl'}`}
|
${line.isUserTunedIn && isSelected && ' bg-gray-100 shadow-2xl'}`}
|
||||||
>
|
>
|
||||||
{/* channel picture */}
|
{/* channel picture */}
|
||||||
{profilePictures && (
|
{line.profilePictures && (
|
||||||
<span className={`${isSelected && ' scale-125 transition-all'}`}>
|
<span className={`${isSelected && ' scale-125 transition-all'}`}>
|
||||||
<LineIcon
|
<LineIcon
|
||||||
grayscale={!isUserTunedIn}
|
grayscale={!line.isUserTunedIn}
|
||||||
sourceImages={
|
sourceImages={
|
||||||
profilePictures.tunedMembers.length > 0
|
line.profilePictures.tunedMembers.length > 0
|
||||||
? profilePictures.tunedMembers
|
? line.profilePictures.tunedMembers
|
||||||
: profilePictures.allMembersWithoutMe
|
: line.profilePictures.allMembersWithoutMe
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
@@ -180,7 +133,7 @@ export default React.memo(function LineRow({
|
|||||||
{line.lineDetails.name || line.otherUserObjects[0].givenName}
|
{line.lineDetails.name || line.otherUserObjects[0].givenName}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
{isUserToggleTuned && isWindowFocused && (
|
{line.isUserToggleTuned && isWindowFocused && (
|
||||||
<span className="ml-2 text-gray-300 text-xs p-1 px-2 bg-gray-100">{`${index + 1}`}</span>
|
<span className="ml-2 text-gray-300 text-xs p-1 px-2 bg-gray-100">{`${index + 1}`}</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user