Skip to content

Commit

Permalink
- introduce the control panel buttons floating below the world view
Browse files Browse the repository at this point in the history
- change right panel & full-screen mode's background to black with 50% or so opacity
- map viewport change to fit circles currently displayed as user clicks on tabs
#73
  • Loading branch information
patrik-u committed Apr 3, 2024
1 parent 99e626e commit f3e65fd
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 71 deletions.
46 changes: 30 additions & 16 deletions circles/functions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1379,15 +1379,12 @@ const setUserSeen = async (userId, circleId, category) => {
);
};

const updateMapViewport = async (circleId) => {
const circle = await getCircle(circleId);
if (!circle) return;

const updateMapViewportForType = async (circle, circleId, type) => {
// get all circles with this parent circle
const circles = await db
.collection("circles")
.where("parent_circle.id", "==", circleId)
.where("type", "==", "circle")
.where("type", "==", type)
.get();

// get all locations
Expand All @@ -1402,7 +1399,7 @@ const updateMapViewport = async (circleId) => {
}
});

if (locations.length <= 0) return;
if (locations.length <= 0) return false;

// calculate map location center
let mapCenter = calculateMapCenter(locations);
Expand All @@ -1419,8 +1416,23 @@ const updateMapViewport = async (circleId) => {
bounds: mapBounds,
};

return calculated_map_viewport;
};

const updateMapViewport = async (circleId) => {
const circle = await getCircle(circleId);
if (!circle) return;

// update viewport for all types
let calculated_map_viewports = {};
calculated_map_viewports["circle"] = await updateMapViewportForType(circle, circleId, "circle");
calculated_map_viewports["post"] = await updateMapViewportForType(circle, circleId, "post");
calculated_map_viewports["event"] = await updateMapViewportForType(circle, circleId, "event");
calculated_map_viewports["project"] = await updateMapViewportForType(circle, circleId, "project");
calculated_map_viewports["user"] = await updateMapViewportForType(circle, circleId, "user");

// update circle
await updateCircle(circleId, { calculated_map_viewport: calculated_map_viewport });
await updateCircle(circleId, { calculated_map_viewports: calculated_map_viewports });
};

//#endregion
Expand Down Expand Up @@ -1766,15 +1778,17 @@ const upsertCircle = async (authCallerId, circleReq) => {
}
}

if (hasNewParent || baseChanged) {
// calculate new map viewport for old and new parent circle
if (oldParentId) {
await updateMapViewport(oldParentId);
}
if (circle.parent_circle?.id) {
await updateMapViewport(circle.parent_circle.id);
}
}
// TODO below logic can be removed as viewport is calculated dynamically on front-end based on displayed circles' locations
// if we want to calculate this on the backend, we can uncomment below
// if (hasNewParent || baseChanged) {
// // calculate new map viewport for old and new parent circle
// if (oldParentId) {
// await updateMapViewport(oldParentId);
// }
// if (circle.parent_circle?.id) {
// await updateMapViewport(circle.parent_circle.id);
// }
// }

// upsert embeddings
upsertCircleEmbedding(circle.id);
Expand Down
80 changes: 72 additions & 8 deletions circles/src/components/Circle.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//#region imports
import React, { useEffect, lazy, useRef, useState, useCallback } from "react";
import React, { useEffect, lazy, useRef, useState, useCallback, useMemo } from "react";
import {
Flex,
Box,
Expand All @@ -9,6 +9,7 @@ import {
DrawerContent,
DrawerCloseButton,
Button,
Text,
useDisclosure,
} from "@chakra-ui/react";
import db from "@/components/Firebase";
Expand Down Expand Up @@ -68,7 +69,7 @@ import WidgetController from "@/components/WidgetController";
import NavigationPanel from "@/components/NavigationPanel";
import config from "@/Config";
import CircleGlobusMap from "@/components/CircleGlobusMap";
import CircleDashboard from "@/components/CircleDashboard";
import { CircleDashboard, tabs } from "@/components/CircleDashboard";
import { CircleChatWidget } from "@/components/CircleChat";
import { UserDashboard } from "@/components/UserDashboard";
import { CircleSearcher } from "@/components/CircleSearch";
Expand Down Expand Up @@ -125,6 +126,18 @@ export const Circle = ({ isGlobal }) => {
const [circleHistory, setCircleHistory] = useAtom(circleHistoryAtom);
const [initialFocusDone, setInitialFocusDone] = useState(false);
const [, setFocusOnMapItem] = useAtom(focusOnMapItemAtom);
const location = useLocationNoUpdates();

const pathSegments = location.pathname.split("/");
const currentTabPath = pathSegments[3]; // assuming the structure is always /{hostId}/{circleId}/{tabPath}/... the relevant segment for tab should be the third one (index 2)
const selectedTab = useMemo(() => {
// get tab with id same as currentTabPath
let tab = tabs.find((x) => x.id === currentTabPath);
if (!tab) {
return tabs.find((x) => x.id === "home"); // default tab
}
return tab;
}, [currentTabPath, tabs, circleId]);

const handlePinClick = () => {
setIsPinned(!isPinned);
Expand Down Expand Up @@ -364,12 +377,12 @@ export const Circle = ({ isGlobal }) => {
}, [signInStatus?.signedIn, user?.id, circleId, inVideoConference]);

// focuses on circle if circle is navigated to directly
useEffect(() => {
if (circleId && circle?.id && !initialFocusDone) {
focusCircle(circle, setFocusOnMapItem);
setInitialFocusDone(true); // Prevent further calls on subsequent renders
}
}, [circleId, circle, initialFocusDone]);
// useEffect(() => {
// if (circleId && circle?.id && !initialFocusDone) {
// focusCircle(circle, setFocusOnMapItem);
// setInitialFocusDone(true); // Prevent further calls on subsequent renders
// }
// }, [circleId, circle, initialFocusDone]);

const circlePictureSize = isMobile ? 120 : 160;

Expand All @@ -378,6 +391,15 @@ export const Circle = ({ isGlobal }) => {
const topMenuHeightPx = topMenuHeight + "px";
const contentHeight = windowHeight;

const onTabClick = (tab) => {
const path = tab?.id ?? "";
navigate(`/${hostId}/${circleId}/${path}`);
};

const isTabSelected = (tab) => {
return tab?.id === selectedTab?.id;
};

return (
<Flex flexDirection="row">
<Box flexGrow="1" position="relative">
Expand All @@ -401,6 +423,48 @@ export const Circle = ({ isGlobal }) => {
background: "linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1))",
}}
></Flex>
{/* Floating control panel */}
{!circleDashboardExpanded && (
<Flex
position="absolute"
bottom="20px"
left="50%"
transform="translateX(-50%)"
borderRadius="10px"
backgroundColor="white"
overflow="hidden"
>
{tabs
.filter((x) => x.showInMap)
.map((tab) => (
<Flex
borderWidth="2px 0px 2px 0px"
borderBottomColor={isTabSelected(tab) ? "#ff2a10" : "white"}
// backgroundColor={isTabSelected(tab) ? "#a1b2c9" : "white"}
height="50px"
// #ff8b68
cursor="pointer"
flexDirection="column"
align="center"
minWidth={"70px"}
flex={1}
onClick={() => onTabClick(tab)}
>
<Flex
flexDirection="column"
align="center"
marginTop="auto"
marginBottom="auto"
>
<tab.icon />
<Text userSelect="none" fontSize="12px">
{tab.name}
</Text>
</Flex>
</Flex>
))}
</Flex>
)}
</Box>

<Flex flexDirection="column" w="full" h="full" pos="absolute" zIndex="2" pointerEvents="none">
Expand Down
3 changes: 2 additions & 1 deletion circles/src/components/CircleAbout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const CircleAbout = ({ onClose, noScrollbars }) => {
// bgGradient="linear(to-r,#d3d1d3,#ffffff)"
// borderRadius="10px"
// margin={isMobile ? "0px" : "0px 10px 10px 0px"}
backgroundColor="white"
padding={noPaddingStyle ? "0px" : "5px"}
flexGrow={noScrollbars ? "0" : "1"}
pointerEvents="auto"
Expand Down Expand Up @@ -127,7 +128,7 @@ const CircleAbout = ({ onClose, noScrollbars }) => {
cursor="pointer"
onClick={() => {
openCircle(navigate, circle.parent_circle);
focusCircle(circle.parent_circle, setFocusOnMapItem);
// focusCircle(circle.parent_circle, setFocusOnMapItem);
setToggleWidgetEvent({ name: "about", value: true });
}}
userSelect="none"
Expand Down
5 changes: 4 additions & 1 deletion circles/src/components/CircleChat.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ import { AboutButton, CircleLink, CircleRichText } from "@/components/CircleElem
import ReactMarkdown from "react-markdown";
import Linkify from "linkify-it";
import { CircleMention } from "@/components/CircleSearch";
import { altBg, expBgColor } from "./Constants";
import { circleDashboardExpandedAtom } from "./Atoms";

const linkify = new Linkify();
linkify.tlds("earth", true);
Expand Down Expand Up @@ -1233,13 +1235,14 @@ export const CircleChat = ({ circle }) => {
};

const circleChatBackgroundColor = "#ededed"; // "#e3e3e3";
const [circleDashboardExpanded, setCircleDashboardExpanded] = useAtom(circleDashboardExpandedAtom);

if (!circle) return null;

return (
<Flex
flexGrow="1"
backgroundColor={circleChatBackgroundColor}
backgroundColor={altBg && circleDashboardExpanded ? "transparent" : circleChatBackgroundColor}
width="100%"
height="100%"
position="relative"
Expand Down
23 changes: 18 additions & 5 deletions circles/src/components/CircleDashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ const CircleSelector = () => {
const handleSelect = (circle) => {
setSelectedCircle(circle);
openCircle(navigate, circle);
focusCircle(circle, setFocusOnMapItem);
// focusCircle(circle, setFocusOnMapItem);
};

if (!selectedCircle?.id) return <Box flexGrow="1" />;
Expand Down Expand Up @@ -196,50 +196,63 @@ const CircleSelector = () => {
);
};

const tabs = [
export const tabs = [
{
id: "home",
name: "Home",
icon: FiHome,
showInMap: true,
type: "circle",
},
{
id: "chat",
name: "Chat",
icon: FiMessageCircle,
type: "circle",
},
{
id: "circles",
name: "Circles",
icon: FiCircle,
showInMap: true,
type: "circle",
},
{
id: "events",
name: "Events",
icon: FiCalendar,
showInMap: true,
type: "event",
},
{
id: "members",
name: "Members",
icon: FiUsers,
showInMap: true,
type: "user",
},
{
id: "projects",
name: "Projects",
icon: FiClipboard,
showInMap: true,
type: "project",
},
{
id: "settings",
name: "Settings",
icon: FiSettings,
type: "circle",
},
{
id: "admin",
name: "Admin",
icon: FiShield,
type: "circle",
},
];

const CircleDashboard = ({ onClose }) => {
export const CircleDashboard = ({ onClose }) => {
log("CircleDashboard.render", -1);

const [user] = useAtom(userAtom);
Expand All @@ -254,6 +267,7 @@ const CircleDashboard = ({ onClose }) => {
const navigate = useNavigateNoUpdates();
const { hostId, circleId } = useParams();
const dropdownRef = useRef(null);
const [, setFocusOnMapItem] = useAtom(focusOnMapItemAtom);

const pathSegments = location.pathname.split("/");
const currentTabPath = pathSegments[3]; // assuming the structure is always /{hostId}/{circleId}/{tabPath}/... the relevant segment for tab should be the third one (index 2)
Expand Down Expand Up @@ -322,7 +336,6 @@ const CircleDashboard = ({ onClose }) => {
)}

<Box
bgGradient="linear(to-r,#d3d1d3,#ffffff)"
borderRadius={isMobile ? "0px" : "10px"}
padding="0px"
flexGrow="1"
Expand Down Expand Up @@ -439,7 +452,7 @@ const CircleDashboard = ({ onClose }) => {
</Box>
)}

<Box flex="1" backgroundColor="white" position="relative">
<Box flex="1" position="relative">
<Suspense fallback={<Box></Box>}>
<Routes>
<Route path="/*" element={<CircleHomeFeed />} />
Expand Down
4 changes: 2 additions & 2 deletions circles/src/components/CircleElements.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ export const MessageButton = ({ circle, inPreview, ...props }) => {

let relationSet = getRelationSet(user, circle);
openCircle(navigate, relationSet);
focusCircle(relationSet, setFocusOnMapItem);
// focusCircle(relationSet, setFocusOnMapItem);
setPreviewCircle(null);
setToggleWidgetEvent({ name: "chat", value: true });
setToggleWidgetEvent({ name: "about", value: true });
Expand Down Expand Up @@ -1695,7 +1695,7 @@ export const OpenButton = ({ circle, ...props }) => {
onClick={(event) => {
event.stopPropagation();
openCircle(navigate, circle);
focusCircle(circle, setFocusOnMapItem);
// focusCircle(circle, setFocusOnMapItem);
}}
position="relative"
align="center"
Expand Down
9 changes: 8 additions & 1 deletion circles/src/components/CircleExtrasAndMain.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import CircleAbout from "@/components/CircleAbout";
import Circles from "@/components/Circles";
import { useParams } from "react-router-dom";
import { BoxIf, ScrollbarsIf } from "./CircleElements";
import { altBg, expBgColor } from "./Constants";
//#endregion

const CircleExtrasAndMain = ({ onClose, extras, main, switchWhenExpanded, hideExtrasWhenCompact }) => {
Expand All @@ -57,7 +58,13 @@ const CircleExtrasAndMain = ({ onClose, extras, main, switchWhenExpanded, hideEx
<BoxIf noBox={!circleDashboardExpanded} order="1" width="375px">
{switchWhenExpanded && circleDashboardExpanded ? getExtras() : main}
</BoxIf>
<BoxIf noBox={!circleDashboardExpanded} order="0" flexGrow="1" align="center" backgroundColor="#ededed">
<BoxIf
noBox={!circleDashboardExpanded}
order="0"
flexGrow="1"
align="center"
backgroundColor={expBgColor}
>
<ScrollbarsIf noScrollbars={!circleDashboardExpanded}>
{switchWhenExpanded && circleDashboardExpanded ? main : getExtras()}
</ScrollbarsIf>
Expand Down
Loading

0 comments on commit f3e65fd

Please sign in to comment.