Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Basic Youtube Embed feature + Word Counter #383

Closed
wants to merge 5 commits into from
Closed

Added Basic Youtube Embed feature + Word Counter #383

wants to merge 5 commits into from

Conversation

MODSetter
Copy link
Contributor

@MODSetter MODSetter commented Apr 26, 2024

Added basic Youtube Embed Feature + Word Counter

Demo:

ytwordcounter.mp4

Copy link

vercel bot commented Apr 26, 2024

@MODSetter is attempting to deploy a commit to the Dub Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

socket-security bot commented Apr 26, 2024

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@radix-ui/react-dropdown-menu@2.0.6 None 0 145 kB benoitgrelard
npm/@tailwindcss/typography@0.5.12 None 0 110 kB adamwathan
npm/use-debounce@9.0.4 None 0 106 kB xnimorz

🚮 Removed packages: npm/typescript@5.4.5

View full report↗︎

@MODSetter MODSetter changed the title Added Basic Youtube Embed feature. Added Basic Youtube Embed feature + Word Counter Apr 26, 2024
@lumpinif
Copy link

TypeError: editor.chain(...).focus(...).deleteRange(...).setYoutubeVideo is not a function

@MODSetter
Copy link
Contributor Author

TypeError: editor.chain(...).focus(...).deleteRange(...).setYoutubeVideo is not a function

Do Build of headless package first

@lumpinif
Copy link

lumpinif commented Apr 27, 2024

what if i dont want to wait and include headless package in my project, I have tried to add youtube directly from tiptap, but it failed to run the command.

the command from tiptap for youtube is like "editor.commands.setYoutubeVideo({
src: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
width: 640,
height: 480,
})" which is also not working in slash-command.tsx

@MODSetter
Copy link
Contributor Author

MODSetter commented Apr 27, 2024

what if i dont want to wait and include headless package in my project, I have tried to add youtube directly from tiptap, but it failed to run the command.

the command from tiptap for youtube is like "editor.commands.setYoutubeVideo({ src: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', width: 640, height: 480, })" which is also not working in slash-command.tsx

I tried with direct configuration before to test the impl then made the final changes in package. You must be not configuring it properly. See tiptap docs it helped me. Make sure you are loading youtube extension in editor.

@lumpinif
Copy link

what if i dont want to wait and include headless package in my project, I have tried to add youtube directly from tiptap, but it failed to run the command.
the command from tiptap for youtube is like "editor.commands.setYoutubeVideo({ src: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', width: 640, height: 480, })" which is also not working in slash-command.tsx

I tried with direct configuration before to test the impl then made the final changes in package. You must be not configuring it properly. See tiptap docs it helped me. Make sure you are loading youtube extension in editor.

did you mean you tried with direct implementation and it worked? If so how different you configured it by directly implementing

@MODSetter
Copy link
Contributor Author

MODSetter commented Apr 27, 2024

what if i dont want to wait and include headless package in my project, I have tried to add youtube directly from tiptap, but it failed to run the command.
the command from tiptap for youtube is like "editor.commands.setYoutubeVideo({ src: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', width: 640, height: 480, })" which is also not working in slash-command.tsx

I tried with direct configuration before to test the impl then made the final changes in package. You must be not configuring it properly. See tiptap docs it helped me. Make sure you are loading youtube extension in editor.

did you mean you tried with direct implementation and it worked? If so how different you configured it by directly implementing

On Mobile so I don't remember every file name but I think you load ,configure and export in extension.ts and it should work.

@lumpinif
Copy link

lumpinif commented Apr 27, 2024

image image

I build another selector to add the youtube video , and it words, but I don't know if I can get the slash-command right though. I will try again.

happy to share the youtube-selector here :

`import { useEffect, useRef } from "react"
import { Check, Trash } from "lucide-react"
import { useEditor } from "novel"

import { cn, isValidUrl, isValidYoutubeUrl } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"

interface YoutubeSelectorProps {
open: boolean
onOpenChange: (open: boolean) => void
}

function getYoutubeUrlFromString(str: string) {
if (isValidUrl(str)) {
if (isValidYoutubeUrl(str)) {
return str
}
}
try {
if (str.includes(".") && !str.includes(" ")) {
const url = new URL(https://${str})
if (isValidYoutubeUrl(url.toString())) {
return url.toString()
}
}
} catch (e) {
return null
}
return null
}

export const YoutubeSelector = ({
open,
onOpenChange,
}: YoutubeSelectorProps) => {
const inputRef = useRef(null)
const widthRef = useRef(null)
const heightRef = useRef(null)
const { editor } = useEditor()

// Autofocus on input by default
useEffect(() => {
inputRef.current && inputRef.current?.focus()
})

if (!editor) return null

const addYoutubeVideo = () => {
const url = getYoutubeUrlFromString(inputRef.current?.value || "")

if (url) {
  editor.commands.setYoutubeVideo({
    src: url,
    width: Math.max(320, parseInt(widthRef.current?.value || "640", 10)),
    height: Math.max(180, parseInt(heightRef.current?.value || "480", 10)),
  })
  onOpenChange(false)
} else {
  alert("Please enter a valid YouTube URL")
}

}

return (




<p
className={cn("underline decoration-stone-400 underline-offset-4")}
>
Youtube













Embed Video





)
}
`

Hey thanks man @MODSetter

@MODSetter
Copy link
Contributor Author

MODSetter commented Apr 27, 2024

image image
I build another selector to add the youtube video , and it words, but I don't know if I can get the slash-command right though. I will try again.

happy to share the youtube-selector here :

`import { useEffect, useRef } from "react" import { Check, Trash } from "lucide-react" import { useEditor } from "novel"

import { cn, isValidUrl, isValidYoutubeUrl } from "@/lib/utils" import { Button } from "@/components/ui/button" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"

interface YoutubeSelectorProps { open: boolean onOpenChange: (open: boolean) => void }

function getYoutubeUrlFromString(str: string) { if (isValidUrl(str)) { if (isValidYoutubeUrl(str)) { return str } } try { if (str.includes(".") && !str.includes(" ")) { const url = new URL(https://${str}) if (isValidYoutubeUrl(url.toString())) { return url.toString() } } } catch (e) { return null } return null }

export const YoutubeSelector = ({ open, onOpenChange, }: YoutubeSelectorProps) => { const inputRef = useRef(null) const widthRef = useRef(null) const heightRef = useRef(null) const { editor } = useEditor()

// Autofocus on input by default useEffect(() => { inputRef.current && inputRef.current?.focus() })

if (!editor) return null

const addYoutubeVideo = () => { const url = getYoutubeUrlFromString(inputRef.current?.value || "")

if (url) {
  editor.commands.setYoutubeVideo({
    src: url,
    width: Math.max(320, parseInt(widthRef.current?.value || "640", 10)),
    height: Math.max(180, parseInt(heightRef.current?.value || "480", 10)),
  })
  onOpenChange(false)
} else {
  alert("Please enter a valid YouTube URL")
}

}

return (

Youtube

Embed Video

)
}
`
Hey thanks man @MODSetter

I have same problem with slash-comand can't seem to find a way to render BubbleMenu to call a Embed or Upload(Blob Api) Dialog like Notion. Will probably take a look at the code next week 😬

@lumpinif
Copy link

lumpinif commented Apr 27, 2024

Recording.2024-04-27.211125.mp4

I got both the selector and the slash command working, but I can't fix the position problem of the popover triggered by the slash command lol.

I can manually overwrite the position though but I just want the popover to be where we trigger the slash command of youtube

@MODSetter
Copy link
Contributor Author

Recording.2024-04-27.211125.mp4
I got both the selector and the slash command working, but I can't fix the position problem of the popover triggered by the slash command lol.

I can manually overwrite the position though but I just want the popover to be where we trigger the slash command of youtube

What was the workaround around slash?

@lumpinif
Copy link

Recording.2024-04-27.211125.mp4
I got both the selector and the slash command working, but I can't fix the position problem of the popover triggered by the slash command lol.
I can manually overwrite the position though but I just want the popover to be where we trigger the slash command of youtube

What was the workaround around slash?

basically, the main idea is to trigger the youtube selector by using slash since we have configured the youtube selector to work as expected, I couldn't use editor.chain(...).focus(...).deleteRange(...).setYoutubeVideo in the slash due to the ts errors say it is not a function, and I think we shouldn't directly use slash to setYoutubeVideo, because it seems too complicated to implement all the UI it needed in the slash such as toast or a popover (or modal, I used modal cuz I couldn't configure the popover to be right position of the slash)

@MODSetter
Copy link
Contributor Author

Merge Conflicts with recent merges to main. Will raise PR after resolving them.

@CodeLine6
Copy link
Contributor

The Wordcounter does not work as expected when there are two or more active instances of editor.

@MODSetter
Copy link
Contributor Author

The Wordcounter does not work as expected when there are two or more active instances of editor.

Can't understand.... main webapp(novel.sh) is using 2 instances one in dialog and it works fine.

@CodeLine6
Copy link
Contributor

CodeLine6 commented May 25, 2024

The Wordcounter does not work as expected when there are two or more active instances of editor.

Can't understand.... main webapp(novel.sh) is using 2 instances one in dialog and it works fine.

You are right. I can't understand why its not the case on my app. After debugging I found out that using editor.storage.characterCount.words() for two different instances returns same value which is the actual word count of the most recent instance; Although when I log editor content for both instances using editor.getHTML(), it works completely fine.

Here is test deployment: https://deploy-preview-2--noteeasy.netlify.app/
Repo Link : https://github.com/missingsemicolononline8/noteeasy/tree/ea77f1611f56e23619548b17a6f80a90eaf03adf

The two instances are

  1. Add New Note Editor
    image

  2. Modify Note Editor: Editor which will appear when you edit any note
    image

Note : If you want to use the test app, you should signup using registration form as using login with google will redirect you to production url which we don't want.

@MODSetter
Copy link
Contributor Author

The Wordcounter does not work as expected when there are two or more active instances of editor.

Can't understand.... main webapp(novel.sh) is using 2 instances one in dialog and it works fine.

You are right. I can't understand why its not the case on my app. After debugging I found out that using editor.storage.characterCount.words() for two different instances returns same value which is the actual word count of the most recent instance; Although when I log editor content for both instances using editor.getHTML(), it works completely fine.

Here is test deployment: https://deploy-preview-2--noteeasy.netlify.app/
Repo Link : https://github.com/missingsemicolononline8/noteeasy/tree/ea77f1611f56e23619548b17a6f80a90eaf03adf

The two instances are

  1. Add New Note Editor
    image

  2. Modify Note Editor: Editor which will appear when you edit any note
    image

Note : If you want to use the test app, you should signup using registration form as using login with google will redirect you to production url which we don't want.

Use this editor component: https://github.com/steven-tey/novel/tree/main/apps%2Fweb%2Fcomponents%2Ftailwind

It have latest update implementation

@CodeLine6
Copy link
Contributor

The Wordcounter does not work as expected when there are two or more active instances of editor.

Can't understand.... main webapp(novel.sh) is using 2 instances one in dialog and it works fine.

You are right. I can't understand why its not the case on my app. After debugging I found out that using editor.storage.characterCount.words() for two different instances returns same value which is the actual word count of the most recent instance; Although when I log editor content for both instances using editor.getHTML(), it works completely fine.
Here is test deployment: https://deploy-preview-2--noteeasy.netlify.app/
Repo Link : https://github.com/missingsemicolononline8/noteeasy/tree/ea77f1611f56e23619548b17a6f80a90eaf03adf
The two instances are

  1. Add New Note Editor
    image
  2. Modify Note Editor: Editor which will appear when you edit any note
    image

Note : If you want to use the test app, you should signup using registration form as using login with google will redirect you to production url which we don't want.

Use this editor component: https://github.com/steven-tey/novel/tree/main/apps%2Fweb%2Fcomponents%2Ftailwind

It have latest update implementation

Would using this solve the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants