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 { ObjectId } from "mongodb";
|
||||
import { User } from "./user.model";
|
||||
import AudioClip from './audioClip.model';
|
||||
import { ObjectId } from 'mongodb';
|
||||
import { User } from './user.model';
|
||||
|
||||
// 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
|
||||
@@ -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
|
||||
currentBroadcastersUserIds?: string[];
|
||||
|
||||
profilePictures: {
|
||||
allMembers: string[];
|
||||
allMembersWithoutMe: string[];
|
||||
|
||||
untunedMembers: string[];
|
||||
|
||||
tunedMembers: string[];
|
||||
broadcastMembers: string[];
|
||||
};
|
||||
isUserTunedIn: boolean = false;
|
||||
isUserToggleTuned: boolean = false;
|
||||
|
||||
constructor(
|
||||
// full line object
|
||||
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
|
||||
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 {
|
||||
roomsMap: LineIdToMasterLine;
|
||||
|
||||
allChannels: MasterLineData[];
|
||||
|
||||
selectedLineId?: string;
|
||||
@@ -363,7 +364,9 @@ export function TerminalProvider({ children }: { children: React.ReactChild }) {
|
||||
|
||||
// todo: sort based on content blocks and my last activity date
|
||||
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') {
|
||||
channels = channels.filter((currentChannel) =>
|
||||
@@ -391,6 +394,49 @@ export function TerminalProvider({ children }: { children: React.ReactChild }) {
|
||||
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;
|
||||
}, [roomMap, desktopMode, user]);
|
||||
|
||||
@@ -402,6 +448,7 @@ export function TerminalProvider({ children }: { children: React.ReactChild }) {
|
||||
[allChannels],
|
||||
);
|
||||
|
||||
// !Caution: the roommap won't have the additional properties as allChannels does
|
||||
return (
|
||||
<TerminalContext.Provider
|
||||
value={{
|
||||
|
||||
@@ -24,9 +24,13 @@ import Peer from 'simple-peer';
|
||||
export default function LineDetails() {
|
||||
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(
|
||||
() => selectedLine?.currentUserMember?.state === LineMemberState.TUNED,
|
||||
@@ -35,56 +39,11 @@ export default function LineDetails() {
|
||||
|
||||
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(
|
||||
() => selectedLine?.currentBroadcastersUserIds?.includes(user._id.toString()),
|
||||
[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 (
|
||||
<div className="flex flex-col flex-1 bg-white relative overflow-auto">
|
||||
{/* line details */}
|
||||
@@ -92,7 +51,17 @@ export default function LineDetails() {
|
||||
className="p-5 z-30 titlebar
|
||||
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 ">
|
||||
<span className="flex flex-row gap-2 items-center">
|
||||
@@ -110,10 +79,10 @@ export default function LineDetails() {
|
||||
</div>
|
||||
|
||||
<Avatar.Group className={'animate-pulse'}>
|
||||
{tunedProfiles.map((otherUser) => (
|
||||
{selectedLine.profilePictures?.tunedMembers?.map((pictureSrc, index) => (
|
||||
<Avatar
|
||||
key={`lineTunedInUserAvatar-${otherUser.name}`}
|
||||
src={otherUser.pictureSrc}
|
||||
key={`lineTunedInUserAvatar-${index}`}
|
||||
src={pictureSrc}
|
||||
shape="square"
|
||||
size={'large'}
|
||||
className={`shadow-lg`}
|
||||
@@ -124,14 +93,14 @@ export default function LineDetails() {
|
||||
<span className="px-10 text-gray-200"> | </span>
|
||||
|
||||
<Avatar.Group>
|
||||
{selectedLine.otherUserObjects.map((otherUser) => (
|
||||
{selectedLine.profilePictures.untunedMembers.map((pictureSrc, index) => (
|
||||
<Avatar
|
||||
key={`lineOfflineUserAvatar-${1}`}
|
||||
src={otherUser.picture}
|
||||
key={`lineOfflineUserAvatar-${index}`}
|
||||
src={pictureSrc}
|
||||
shape="square"
|
||||
size={'default'}
|
||||
// grayscale if not playing?
|
||||
className={`${true && 'grayscale'}`}
|
||||
className={`grayscale`}
|
||||
/>
|
||||
))}
|
||||
</Avatar.Group>
|
||||
|
||||
@@ -25,16 +25,6 @@ export default React.memo(function LineRow({
|
||||
const { user } = useAuth();
|
||||
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(() => {
|
||||
handleSelectLine(line.lineDetails._id.toString());
|
||||
}, [handleSelectLine, line.lineDetails, index]);
|
||||
@@ -49,43 +39,6 @@ export default React.memo(function LineRow({
|
||||
|
||||
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(() => {
|
||||
if (isSelected) {
|
||||
return (
|
||||
@@ -97,7 +50,7 @@ export default React.memo(function LineRow({
|
||||
);
|
||||
}
|
||||
|
||||
if (profilePictures.broadcastMembers.length > 0)
|
||||
if (line.profilePictures.broadcastMembers.length > 0)
|
||||
return (
|
||||
<Avatar.Group
|
||||
maxCount={2}
|
||||
@@ -111,7 +64,7 @@ export default React.memo(function LineRow({
|
||||
}}
|
||||
className="shadow-lg"
|
||||
>
|
||||
{profilePictures.broadcastMembers.map((pictureSrc, index) => (
|
||||
{line.profilePictures.broadcastMembers.map((pictureSrc, index) => (
|
||||
<Avatar
|
||||
key={`lineRowActiveBroadcasters-${index}`}
|
||||
src={pictureSrc}
|
||||
@@ -122,7 +75,7 @@ export default React.memo(function LineRow({
|
||||
</Avatar.Group>
|
||||
);
|
||||
|
||||
if (profilePictures.tunedMembers.length > 0)
|
||||
if (line.profilePictures.tunedMembers.length > 0)
|
||||
return <FiSun className="text-teal-500 animate-pulse" />;
|
||||
|
||||
// if there is new activity blocks for me
|
||||
@@ -142,7 +95,7 @@ export default React.memo(function LineRow({
|
||||
{moment(line.currentUserMember.lastVisitDate).fromNow(true)}
|
||||
</span>
|
||||
);
|
||||
}, [line, isSelected, profilePictures]);
|
||||
}, [line, isSelected]);
|
||||
|
||||
// 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
|
||||
@@ -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
|
||||
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 */}
|
||||
{profilePictures && (
|
||||
{line.profilePictures && (
|
||||
<span className={`${isSelected && ' scale-125 transition-all'}`}>
|
||||
<LineIcon
|
||||
grayscale={!isUserTunedIn}
|
||||
grayscale={!line.isUserTunedIn}
|
||||
sourceImages={
|
||||
profilePictures.tunedMembers.length > 0
|
||||
? profilePictures.tunedMembers
|
||||
: profilePictures.allMembersWithoutMe
|
||||
line.profilePictures.tunedMembers.length > 0
|
||||
? line.profilePictures.tunedMembers
|
||||
: line.profilePictures.allMembersWithoutMe
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
@@ -180,7 +133,7 @@ export default React.memo(function LineRow({
|
||||
{line.lineDetails.name || line.otherUserObjects[0].givenName}
|
||||
</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>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user