Skip to content

Commit

Permalink
added the ability to add youtube videos to notes
Browse files Browse the repository at this point in the history
  • Loading branch information
Hartaithan committed Jul 25, 2023
1 parent 52a3e07 commit ce619f3
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 32 deletions.
33 changes: 5 additions & 28 deletions components/AddImageDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { type IModalProps } from "@/models/ModalModel";
import { centeredDialog } from "@/styles/global";
import {
Button,
Text,
Expand All @@ -8,34 +10,9 @@ import {
} from "@mantine/core";
import { type TransformedValues, matches, useForm } from "@mantine/form";
import { useRichTextEditorContext } from "@mantine/tiptap";
import {
type Dispatch,
type SetStateAction,
type FC,
memo,
type CSSProperties,
} from "react";

interface IAddImageDialogProps {
opened: boolean;
setOpened: Dispatch<SetStateAction<boolean>>;
}

interface ICustomPosition {
top?: string | number;
left?: string | number;
bottom?: string | number;
right?: string | number;
transform: CSSProperties["transform"];
}

const position: ICustomPosition = {
top: 20,
left: "50%",
transform: "translateX(-50%)",
};
import { type FC, memo } from "react";

const AddImageDialog: FC<IAddImageDialogProps> = (props) => {
const AddImageDialog: FC<IModalProps> = (props) => {
const { opened, setOpened } = props;
const { editor } = useRichTextEditorContext();

Expand All @@ -58,7 +35,7 @@ const AddImageDialog: FC<IAddImageDialogProps> = (props) => {
<Dialog
opened={opened}
withCloseButton
position={position as DialogProps["position"]}
position={centeredDialog as DialogProps["position"]}
onClose={() => setOpened(false)}
size="lg"
radius="md"
Expand Down
69 changes: 69 additions & 0 deletions components/AddYoutubeLinkDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { type IModalProps } from "@/models/ModalModel";
import { centeredDialog } from "@/styles/global";
import {
Button,
Text,
TextInput,
Dialog,
Group,
type DialogProps,
} from "@mantine/core";
import { type TransformedValues, matches, useForm } from "@mantine/form";
import { useRichTextEditorContext } from "@mantine/tiptap";
import { type FC, memo } from "react";

const AddYoutubeLinkDialog: FC<IModalProps> = (props) => {
const { opened, setOpened } = props;
const { editor } = useRichTextEditorContext();

const form = useForm({
initialValues: { url: "" },
validate: {
url: matches(
// eslint-disable-next-line no-useless-escape
/^(https?\:\/\/)?((www\.)?youtube\.com|youtu\.be)\/.+$/,
"Enter a valid youtube url"
),
},
});

const handleSubmit = (values: TransformedValues<typeof form>): void => {
editor.commands.setYoutubeVideo({
src: values.url,
width: 640,
height: 480,
});
setOpened(false);
};

return (
<Dialog
opened={opened}
withCloseButton
position={centeredDialog as DialogProps["position"]}
onClose={() => setOpened(false)}
size="lg"
radius="md"
zIndex={9999}
>
<Text size="sm" mb="xs" weight={500}>
Add youtube link
</Text>
<Group align="flex-end">
<TextInput
{...form.getInputProps("url")}
placeholder="https://example.com/image.png"
sx={{ flex: 1 }}
/>
<Button
onClick={() => form.onSubmit(handleSubmit)()}
sx={{ alignSelf: "flex-start" }}
>
Add
</Button>
</Group>
</Dialog>
);
};

export default memo(AddYoutubeLinkDialog);
17 changes: 15 additions & 2 deletions components/Controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { type FC } from "react";
import { RichTextEditor, useRichTextEditorContext } from "@mantine/tiptap";
import {
IconArrowBarBoth,
IconBrandYoutube,
IconCheckbox,
IconIndentDecrease,
IconIndentIncrease,
IconPhotoPlus,
} from "@tabler/icons-react";

interface IImageControlProps {
interface IControlProps {
onClick: () => void;
}

Expand Down Expand Up @@ -71,7 +72,7 @@ export const LiftListItemControl: FC = () => {
);
};

export const ImageControl: FC<IImageControlProps> = ({ onClick }) => {
export const ImageControl: FC<IControlProps> = ({ onClick }) => {
return (
<RichTextEditor.Control
onClick={onClick}
Expand All @@ -82,3 +83,15 @@ export const ImageControl: FC<IImageControlProps> = ({ onClick }) => {
</RichTextEditor.Control>
);
};

export const YoutubeControl: FC<IControlProps> = ({ onClick }) => {
return (
<RichTextEditor.Control
onClick={onClick}
aria-label="Add youtube video"
title="Add youtube video"
>
<IconBrandYoutube stroke={1.5} size="1rem" />
</RichTextEditor.Control>
);
};
14 changes: 12 additions & 2 deletions modals/NoteModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
SinkListItemControl,
SplitListItemControl,
ToggleTaskListControl,
YoutubeControl,
} from "@/components/Controls";
import API from "@/helpers/api";
import {
Expand All @@ -49,6 +50,8 @@ import {
} from "@tabler/icons-react";
import { notifications } from "@mantine/notifications";
import AddImageDialog from "@/components/AddImageDialog";
import Youtube from "@tiptap/extension-youtube";
import AddYoutubeLinkDialog from "@/components/AddYoutubeLinkDialog";

interface INoteModalProps {
state: INoteModalState;
Expand Down Expand Up @@ -90,6 +93,7 @@ const NoteModal: FC<INoteModalProps> = (props) => {

const [note, setNote] = useState<INote | null>(null);
const [addImage, setAddImage] = useState<boolean>(false);
const [addYoutube, setAddYoutube] = useState<boolean>(false);

const [status, setStatus] = useState<Status>("loading");
const isLoading = status === "loading";
Expand All @@ -104,7 +108,8 @@ const NoteModal: FC<INoteModalProps> = (props) => {
Link,
Highlight,
TaskList,
Image.configure(),
Image,
Youtube,
TaskItem.configure({ nested: true }),
TextAlign.configure({ types: ["heading", "paragraph"] }),
],
Expand Down Expand Up @@ -215,7 +220,7 @@ const NoteModal: FC<INoteModalProps> = (props) => {
}, [getNote, opened, reset]);

return (
<Modal.Root opened={opened} onClose={onClose} centered size="xl">
<Modal.Root opened={opened} onClose={onClose} centered size={900}>
<Modal.Overlay />
<Modal.Content>
<Modal.Header>
Expand Down Expand Up @@ -269,6 +274,11 @@ const NoteModal: FC<INoteModalProps> = (props) => {
<RichTextEditor.ControlsGroup>
<ImageControl onClick={() => setAddImage(true)} />
<AddImageDialog opened={addImage} setOpened={setAddImage} />
<YoutubeControl onClick={() => setAddYoutube(true)} />
<AddYoutubeLinkDialog
opened={addYoutube}
setOpened={setAddYoutube}
/>
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
Expand Down
9 changes: 9 additions & 0 deletions models/AppModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
type NullablePSNProfile,
type NullableSession,
} from "./AuthModel";
import { type CSSProperties } from "react";

export type IExtendedPageProps = object;

Expand All @@ -35,3 +36,11 @@ export interface IInitialProps {
}

export type IPage<P = object, IP = P> = NextPage<P & IExtendedPageProps, IP>;

export interface ICustomPosition {
top?: string | number;
left?: string | number;
bottom?: string | number;
right?: string | number;
transform: CSSProperties["transform"];
}
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@tiptap/extension-task-list": "^2.0.3",
"@tiptap/extension-text-align": "^2.0.3",
"@tiptap/extension-underline": "^2.0.3",
"@tiptap/extension-youtube": "^2.0.4",
"@tiptap/pm": "^2.0.3",
"@tiptap/react": "^2.0.3",
"@tiptap/starter-kit": "^2.0.3",
Expand Down
7 changes: 7 additions & 0 deletions styles/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,11 @@ export default css.global`
ul[data-type="taskList"] input[type="checkbox"] {
cursor: pointer;
}
div[data-youtube-video] iframe {
border: none;
width: 100%;
height: auto;
aspect-ratio: 16/9;
}
`;
7 changes: 7 additions & 0 deletions styles/global.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { type ICustomPosition } from "@/models/AppModel";
import { type CSSObject, type MantineTheme } from "@mantine/core";

export const globalStyles = (theme: MantineTheme): CSSObject => ({
Expand All @@ -20,3 +21,9 @@ export const globalStyles = (theme: MantineTheme): CSSObject => ({
backgroundColor: theme.colors.primary[8],
},
});

export const centeredDialog: ICustomPosition = {
top: 20,
left: "50%",
transform: "translateX(-50%)",
};

0 comments on commit ce619f3

Please sign in to comment.