Skip to content

Commit

Permalink
Intergrate YorkieIntelligence into ToolBar (#301)
Browse files Browse the repository at this point in the history
* fix(yorkie_intelligence): integrate YorkieIntelligence into FormatBar

* refactor(formatBar) : change naming formatBar -> toolBar

* chore(index.tsx): remove unused code

* chore(ToolBar): rename FormatBar to ToolBar

- change Box to Divider
- set up flex using stack component
- remove TooltipToggleButton style margin and minWidth

* chore(YorkieIntelligence): change setting activated

- remove style pointerEvents and, use disabled attribute
- remove true check (activated)

* chore(Editor): remove true check edtiorStore.cmView

* chore(YorkieIntelligence): remove variable activated

- change type assertion(intelligenceFooterPivot) to if conditional statement

* refactor(YorkieIntelligence): add set up debousing for showToolBar

- change naming showFormatBar -> showToolBar
- add set up Transition (Effect: Fade, delay: 300ms)

* refactor(YorkieIntelligence): remove unnecessary selectionchange event listener

* chore(Editor): adjust position of toolbar in Editor.tsx

* fix(YorkieIntelligence): improve intelligence footer pivot handling

- improve intelligence footer pivot error when changing selection after text formatting

* �Change `TODO` comment

---------

Co-authored-by: devleejb <[email protected]>
  • Loading branch information
2 people authored and minai621 committed Nov 5, 2024
1 parent 899daf0 commit 0515267
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 148 deletions.
3 changes: 0 additions & 3 deletions frontend/src/components/common/TooltipToggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ const style = {
toggleButton: {
width: "25px",
height: "25px",
minWidth: "25px",
padding: "0",
margin: "2px",
border: "none",
fontWeight: "bold",
},
Expand Down
22 changes: 10 additions & 12 deletions frontend/src/components/editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import { useCreateUploadUrlMutation, useUploadFileMutation } from "../../hooks/a
import { selectWorkspace } from "../../store/workspaceSlice";
import { ScrollSyncPane } from "react-scroll-sync";
import { selectSetting } from "../../store/settingSlice";
import { FormatBarState, useFormatUtils, FormatType } from "../../hooks/useFormatUtils";
import { ToolBarState, useFormatUtils, FormatType } from "../../hooks/useFormatUtils";

import FormatBar from "./FormatBar";
import ToolBar from "./ToolBar";

function Editor() {
const dispatch = useDispatch();
Expand All @@ -28,7 +28,7 @@ function Editor() {
const { mutateAsync: createUploadUrl } = useCreateUploadUrlMutation();
const { mutateAsync: uploadFile } = useUploadFileMutation();

const [formatBarState, setFormatBarState] = useState<FormatBarState>({
const [toolBarState, setToolBarState] = useState<ToolBarState>({
show: false,
position: { top: 0, left: 0 },
selectedFormats: new Set<FormatType>(),
Expand Down Expand Up @@ -73,18 +73,19 @@ function Editor() {
checkAndAddFormat("`", FormatType.CODE);
checkAndAddFormat("~~", FormatType.STRIKETHROUGH);

setFormatBarState((prev) => ({
// TODO: Modify the rendering method so that it is not affected by the size of the Toolbar
setToolBarState((prev) => ({
...prev,
show: true,
position: {
top: coords.top - 8,
left: coords.left + 190,
top: coords.top - 5,
left: coords.left,
},
selectedFormats: formats,
}));
}
} else {
setFormatBarState((prev) => ({
setToolBarState((prev) => ({
...prev,
show: false,
selectedFormats: new Set(),
Expand Down Expand Up @@ -185,11 +186,8 @@ function Editor() {
minHeight: "100%",
}}
/>
{Boolean(formatBarState.show && editorStore.cmView) && (
<FormatBar
formatBarState={formatBarState}
onChangeFormatBarState={setFormatBarState}
/>
{Boolean(toolBarState.show) && (
<ToolBar toolBarState={toolBarState} onChangeToolBarState={setToolBarState} />
)}
</div>
</ScrollSyncPane>
Expand Down
75 changes: 0 additions & 75 deletions frontend/src/components/editor/FormatBar.tsx

This file was deleted.

104 changes: 104 additions & 0 deletions frontend/src/components/editor/ToolBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Popover, ToggleButtonGroup, Divider, Stack, Fade } from "@mui/material";
import TooltipToggleButton from "../common/TooltipToggleButton";
import { ToolBarState, useFormatUtils, FormatType } from "../../hooks/useFormatUtils";
import YorkieIntelligence from "./YorkieIntelligence";
import { useDebounce } from "react-use";
import { useState } from "react";

interface ToolBarProps {
toolBarState: ToolBarState;
onChangeToolBarState: React.Dispatch<React.SetStateAction<ToolBarState>>;
}

function ToolBar({
toolBarState: { show: showToolBar, position: formatBarPosition, selectedFormats },
onChangeToolBarState,
}: ToolBarProps) {
const { toggleButtonChangeHandler } = useFormatUtils();
const [debouncedShowToolBar, setDebouncedShowToolBar] = useState<boolean | null>(null);

useDebounce(
() => {
setDebouncedShowToolBar(showToolBar);
},
500,
[showToolBar]
);

if (!debouncedShowToolBar) return;

return (
<Popover
open={debouncedShowToolBar}
anchorReference="anchorPosition"
anchorPosition={{
top: formatBarPosition.top,
left: formatBarPosition.left,
}}
onClose={() => onChangeToolBarState((prev) => ({ ...prev, show: false }))}
anchorOrigin={{
vertical: "top",
horizontal: "left",
}}
transformOrigin={{
vertical: "bottom",
horizontal: "left",
}}
disableAutoFocus
TransitionComponent={Fade}
TransitionProps={{ timeout: 300 }}
>
<Stack direction={"row"} margin={"5px 7px"}>
<YorkieIntelligence />
<Divider
orientation="vertical"
flexItem
sx={{ height: "20px", alignSelf: "center", margin: "0 5px" }}
/>
<ToggleButtonGroup
value={Array.from(selectedFormats)}
onChange={toggleButtonChangeHandler(selectedFormats, onChangeToolBarState)}
exclusive
aria-label="text formatting"
>
<Stack direction={"row"} gap={"5px"} alignItems={"center"}>
<TooltipToggleButton
color={selectedFormats.has(FormatType.ITALIC) ? "primary" : "secondary"}
title={"Cmd+I / Ctrl+I"}
value={FormatType.ITALIC}
>
<i>i</i>
</TooltipToggleButton>
<TooltipToggleButton
color={selectedFormats.has(FormatType.BOLD) ? "primary" : "secondary"}
title={"Cmd+B / Ctrl+B"}
value={FormatType.BOLD}
>
<strong>B</strong>
</TooltipToggleButton>
<TooltipToggleButton
color={
selectedFormats.has(FormatType.STRIKETHROUGH)
? "primary"
: "secondary"
}
title={"Cmd+Shift+X / Ctrl+Shfit+X"}
value={FormatType.STRIKETHROUGH}
>
~
</TooltipToggleButton>
<TooltipToggleButton
color={selectedFormats.has(FormatType.CODE) ? "primary" : "secondary"}
title={"Cmd+E / Ctrl+E"}
value={FormatType.CODE}
>
{"</>"}
</TooltipToggleButton>
</Stack>
</ToggleButtonGroup>
</Stack>
</Popover>
);
}

export default ToolBar;
83 changes: 32 additions & 51 deletions frontend/src/components/editor/YorkieIntelligence.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,59 @@
import { Card, CardActionArea, Fade, Popper, Stack, Typography, useTheme } from "@mui/material";
import { Button, Typography } from "@mui/material";
import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { useDebounce } from "react-use";
import { INTELLIGENCE_FOOTER_ID, INTELLIGENCE_HEADER_ID } from "../../constants/intelligence";
import { INTELLIGENCE_FOOTER_ID } from "../../constants/intelligence";
import YorkieIntelligenceFooter from "./YorkieIntelligenceFooter";
import { useSelector } from "react-redux";
import { selectSetting } from "../../store/settingSlice";

function YorkieIntelligence() {
const theme = useTheme();
const [footerOpen, setFooterOpen] = useState(false);
const [intelligenceHeaderPivot, setIntelligenceHeaderPivot] = useState<Element | null>(null);
const [intelligenceFooterPivot, setIntelligenceFooterPivot] = useState<Element | null>(null);
const [debouncedPivot, setDebouncedPivot] = useState<Element | null>(null);

useDebounce(
() => {
setDebouncedPivot(intelligenceHeaderPivot);
},
500,
[intelligenceHeaderPivot]
);
const { yorkieIntelligence } = useSelector(selectSetting);

useEffect(() => {
// initialize intelligence footer pivot
const intelligenceFooterPivot = document.getElementById(INTELLIGENCE_FOOTER_ID);
setIntelligenceFooterPivot(intelligenceFooterPivot);

document.addEventListener("selectionchange", function () {
const intelligenceHeaderPivot = document.getElementById(INTELLIGENCE_HEADER_ID);
// If changed selection (ex : text formatting), update the intelligence footer pivot
const intelligenceFooterPivot = document.getElementById(INTELLIGENCE_FOOTER_ID);
setIntelligenceHeaderPivot(intelligenceHeaderPivot);
setIntelligenceFooterPivot(intelligenceFooterPivot);

if (!intelligenceHeaderPivot) {
setFooterOpen(false);
setDebouncedPivot(null);
}
});
}, []);

const handleFooterOpen = () => {
setFooterOpen((prev) => !prev);
};

if (!debouncedPivot || !intelligenceFooterPivot) return;
if (!intelligenceFooterPivot) return;

return (
<>
<Popper
open={Boolean(debouncedPivot)}
anchorEl={debouncedPivot}
placement="top-start"
transition
<Button
onClick={handleFooterOpen}
sx={{
padding: "3px 5px",
border: "none",
"&:hover": {
border: "none",
},
}}
disabled={!yorkieIntelligence?.enable}
>
{({ TransitionProps }) => (
<Fade {...TransitionProps}>
<Card
sx={{
boxShadow: theme.shadows[11],
borderRadius: 2,
mb: 1,
}}
>
<CardActionArea
sx={{
paddingX: 1.3,
paddingY: 0.3,
}}
onClick={handleFooterOpen}
>
<Stack direction="row" alignItems="center" gap={1}>
<img src="/yorkie.png" height={20} />
<Typography variant="subtitle1">Yorkie Intelligence</Typography>
</Stack>
</CardActionArea>
</Card>
</Fade>
)}
</Popper>
<img
src="/yorkie.png"
height={20}
alt="yorkie_img"
style={{ filter: yorkieIntelligence?.enable ? "none" : "grayscale(100%)" }}
/>
<Typography variant="subtitle1" fontSize={14}>
Yorkie Intelligence
</Typography>
</Button>

{footerOpen &&
createPortal(
<YorkieIntelligenceFooter onClose={handleFooterOpen} />,
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/hooks/useFormatUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Dispatch, SetStateAction } from "react";
import { useSelector } from "react-redux";
import { selectEditor } from "../store/editorSlice";

export interface FormatBarState {
export interface ToolBarState {
show: boolean;
position: { top: number; left: number };
selectedFormats: Set<FormatType>;
Expand Down Expand Up @@ -122,7 +122,7 @@ export const useFormatUtils = () => {
const toggleButtonChangeHandler = useCallback(
(
selectedFormats: Set<FormatType>,
onChangeFormatBarState: Dispatch<SetStateAction<FormatBarState>>
onChangeToolBarState: Dispatch<SetStateAction<ToolBarState>>
) => {
return (_event: MouseEvent<HTMLElement>, format: FormatType) => {
if (!cmView) return;
Expand All @@ -133,7 +133,7 @@ export const useFormatUtils = () => {
} else {
newSelectedFormats.add(format);
}
onChangeFormatBarState((prev) => ({
onChangeToolBarState((prev) => ({
...prev,
selectedFormats: newSelectedFormats,
}));
Expand Down
Loading

0 comments on commit 0515267

Please sign in to comment.