2
0

Add more video supports (#1023)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
	- Introduced a new layout option for the TextInput component.
- Added support for GUMLET and TIKTOK video content types in
VideoBubbleContent.
- Enhanced VideoUploadContent to handle new properties like aspectRatio
and maxWidth.
- Updated VideoBubble to include aspect-ratio and max-width styles based
on content properties.
- **Refactor**
- Changed the extension used for internationalization (i18n) in the VS
Code environment.
	- Modified how environment variables are accessed in tolgee.tsx.
- Updated parseVideoUrl function to include a new property
videoSizeSuggestion.
- **Chores**
- Updated the tolgeeEnv object in env.ts and added a new optional
parameter to the getRuntimeVariable function.
- Expanded video handling capabilities by introducing new video content
types and associated regular expressions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Closes #978 #936 #926
This commit is contained in:
Baptiste Arnaud
2023-11-10 11:17:14 +01:00
committed by GitHub
parent df578417aa
commit dd4de582a9
20 changed files with 306 additions and 143 deletions

View File

@ -4,7 +4,7 @@
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"bradlc.vscode-tailwindcss", "bradlc.vscode-tailwindcss",
"unifiedjs.vscode-mdx", "unifiedjs.vscode-mdx",
"baptistearno.baptistearno-i18n-ally", "lokalise.i18n-ally",
"ms-playwright.playwright", "ms-playwright.playwright",
"Prisma.prisma" "Prisma.prisma"
] ]

View File

@ -20,8 +20,8 @@ usageMatchRegex:
# The "$1" will be replaced by the keypath specified. # The "$1" will be replaced by the keypath specified.
# Optional: uncomment the following two lines to use # Optional: uncomment the following two lines to use
# refactorTemplates: refactorTemplates:
# - i18n.get("$1") - t("$1")
# If set to true, only enables this custom framework (will disable all built-in frameworks) # If set to true, only enables this custom framework (will disable all built-in frameworks)
monopoly: true monopoly: true

View File

@ -110,41 +110,35 @@
"billing.usage.chats.heading": "Chats", "billing.usage.chats.heading": "Chats",
"billing.usage.heading": "Nutzung", "billing.usage.heading": "Nutzung",
"billing.usage.unlimited": "Unbegrenzt", "billing.usage.unlimited": "Unbegrenzt",
"blocks.bubbles.embed.blockCard.tooltip": "Ein PDF, ein iframe, eine Website einbetten...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Dateien hochladen",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Tabellen",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"clickToEdit": "Zum Bearbeiten klicken...",
"confirmModal.defaultTitle": "Bist du sicher?", "confirmModal.defaultTitle": "Bist du sicher?",
"dashboard.header.settingsButton.label": "Einstellungen & Mitglieder", "dashboard.header.settingsButton.label": "Einstellungen & Mitglieder",
"dashboard.redirectionMessage": "Du wirst weitergeleitet...", "dashboard.redirectionMessage": "Du wirst weitergeleitet...",
"dashboard.title": "Meine Typebots", "dashboard.title": "Meine Typebots",
"delete": "Löschen", "delete": "Löschen",
"downgrade": "Downgrade", "downgrade": "Downgrade",
"blocks.bubbles.embed.blockCard.tooltip": "Ein PDF, ein iframe, eine Website einbetten...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Dateien hochladen",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Tabellen",
"editor.blockCard.logicBlock.tooltip.code.label": "JavaScript-Code ausführen", "editor.blockCard.logicBlock.tooltip.code.label": "JavaScript-Code ausführen",
"editor.blockCard.logicBlock.tooltip.jump.label": "Ablauf zu einer anderen Gruppe beschleunigen", "editor.blockCard.logicBlock.tooltip.jump.label": "Ablauf zu einer anderen Gruppe beschleunigen",
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Verlinkung zu einem anderen Typebot", "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Verlinkung zu einem anderen Typebot",
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Zum Bearbeiten klicken...",
"editor.blocks.bubbles.audio.settings.autoplay.label": "Autoplay aktivieren", "editor.blocks.bubbles.audio.settings.autoplay.label": "Autoplay aktivieren",
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Datei auswählen", "editor.blocks.bubbles.audio.settings.chooseFile.label": "Datei auswählen",
"editor.blocks.bubbles.audio.settings.embedLink.label": "Link einbetten", "editor.blocks.bubbles.audio.settings.embedLink.label": "Link einbetten",
"editor.blocks.bubbles.audio.settings.upload.label": "Hochladen", "editor.blocks.bubbles.audio.settings.upload.label": "Hochladen",
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Füge den Audio-Dateilink ein...", "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Füge den Audio-Dateilink ein...",
"editor.blocks.bubbles.audio.settings.worksWith.text": "Funktioniert mit .MP3- und .WAV-Dateien", "editor.blocks.bubbles.audio.settings.worksWith.text": "Funktioniert mit .MP3- und .WAV-Dateien",
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Zum Bearbeiten klicken...",
"editor.blocks.bubbles.embed.node.show.text": "Einbetten anzeigen", "editor.blocks.bubbles.embed.node.show.text": "Einbetten anzeigen",
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px", "editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Füge den Link oder Code ein...", "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Füge den Link oder Code ein...",
"editor.blocks.bubbles.embed.settings.worksWith.text": "Funktioniert mit PDFs, iframes, Websites...", "editor.blocks.bubbles.embed.settings.worksWith.text": "Funktioniert mit PDFs, iframes, Websites...",
"editor.blocks.bubbles.image.node.clickToEdit.text": "Zum Bearbeiten klicken...",
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Beim Klicken Link", "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Beim Klicken Link",
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link Alternativtext (Beschreibung)", "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link Alternativtext (Beschreibung)",
"editor.blocks.bubbles.textEditor.plate.label": "Texteditor", "editor.blocks.bubbles.textEditor.plate.label": "Texteditor",
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Nach einer Variable suchen", "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Nach einer Variable suchen",
"editor.blocks.bubbles.video.node.clickToEdit.text": "Zum Bearbeiten klicken...",
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Füge den Videolink ein...",
"editor.blocks.bubbles.video.settings.worksWith.text": "Funktioniert mit YouTube, Vimeo und anderen",
"editor.blocks.start.text": "Start", "editor.blocks.start.text": "Start",
"editor.editableTypebotName.tooltip.rename.label": "Umbenennen", "editor.editableTypebotName.tooltip.rename.label": "Umbenennen",
"editor.gettingStartedModal.editorBasics.heading": "Grundlagen des Editors", "editor.gettingStartedModal.editorBasics.heading": "Grundlagen des Editors",
@ -231,6 +225,8 @@
"templates.modal.menuHeading.product": "Produkt", "templates.modal.menuHeading.product": "Produkt",
"templates.modal.useTemplateButton.label": "Diese Vorlage verwenden", "templates.modal.useTemplateButton.label": "Diese Vorlage verwenden",
"upgrade": "Upgrade", "upgrade": "Upgrade",
"video.urlInput.helperText": "Funktioniert mit YouTube, Vimeo, Gumlet, TikTok und anderen",
"video.urlInput.placeholder": "Füge den Videolink ein...",
"workspace.dropdown.logoutButton.label": "Abmelden", "workspace.dropdown.logoutButton.label": "Abmelden",
"workspace.dropdown.newButton.label": "Neuer Workspace", "workspace.dropdown.newButton.label": "Neuer Workspace",
"workspace.membersList.inviteButton.label": "Einladen", "workspace.membersList.inviteButton.label": "Einladen",

View File

@ -29,7 +29,7 @@
"account.preferences.graphNavigation.trackpad.description": "Move the board using 2 fingers and zoom in/out by pinching", "account.preferences.graphNavigation.trackpad.description": "Move the board using 2 fingers and zoom in/out by pinching",
"account.preferences.graphNavigation.trackpad.label": "Trackpad", "account.preferences.graphNavigation.trackpad.label": "Trackpad",
"account.preferences.language.heading": "Language", "account.preferences.language.heading": "Language",
"account.preferences.language.tooltip": "The translations are not complete yet. It is a work in progress. 🤓", "account.preferences.language.tooltip": "The translations are not complete yet. It is a work in progress. \uD83E\uDD13",
"analytics.completionRateLabel": "Completion rate", "analytics.completionRateLabel": "Completion rate",
"analytics.notAvailableLabel": "Not available", "analytics.notAvailableLabel": "Not available",
"analytics.startsLabel": "Starts", "analytics.startsLabel": "Starts",
@ -40,7 +40,7 @@
"auth.error.oauthNotLinked": "To confirm your identity, sign in with the same account you used originally.", "auth.error.oauthNotLinked": "To confirm your identity, sign in with the same account you used originally.",
"auth.error.unknown": "An error occurred. Please try again.", "auth.error.unknown": "An error occurred. Please try again.",
"auth.magicLink.description": "Make sure to check your spam folder.", "auth.magicLink.description": "Make sure to check your spam folder.",
"auth.magicLink.title": "A magic link email was sent. 🪄", "auth.magicLink.title": "A magic link email was sent. \uD83E\uDE84",
"auth.noProvider.link": "configure at least one auth provider (Email, Google, GitHub, Facebook or Azure AD).", "auth.noProvider.link": "configure at least one auth provider (Email, Google, GitHub, Facebook or Azure AD).",
"auth.noProvider.preLink": "You need to", "auth.noProvider.preLink": "You need to",
"auth.orEmailLabel": "Or with your email", "auth.orEmailLabel": "Or with your email",
@ -102,54 +102,49 @@
"billing.pricingCard.starter.fileUploadBlock": "File upload input block", "billing.pricingCard.starter.fileUploadBlock": "File upload input block",
"billing.pricingCard.starter.includedSeats": "2 seats included", "billing.pricingCard.starter.includedSeats": "2 seats included",
"billing.pricingCard.upgradeButton.current": "Your current plan", "billing.pricingCard.upgradeButton.current": "Your current plan",
"billing.updateSuccessToast.description": "Workspace {plan} plan successfully updated 🎉", "billing.tiersModal.heading": "Chats pricing table",
"billing.updateSuccessToast.description": "Workspace {plan} plan successfully updated \uD83C\uDF89",
"billing.upgradeAlert.buttonDefaultLabel": "More info", "billing.upgradeAlert.buttonDefaultLabel": "More info",
"billing.upgradeLimitLabel": "You need to upgrade your plan in order to {type}", "billing.upgradeLimitLabel": "You need to upgrade your plan in order to {type}",
"billing.usage.chats.alert.soonReach": "Your typebots are popular! You will soon reach your plan's chats limit. 🚀", "billing.usage.chats.alert.soonReach": "Your typebots are popular! You will soon reach your plan's chats limit. \uD83D\uDE80",
"billing.usage.chats.alert.updatePlan": "Make sure to update your plan to increase this limit and continue chatting with your users.", "billing.usage.chats.alert.updatePlan": "Make sure to update your plan to increase this limit and continue chatting with your users.",
"billing.usage.chats.heading": "Chats", "billing.usage.chats.heading": "Chats",
"billing.usage.heading": "Usage", "billing.usage.heading": "Usage",
"billing.usage.unlimited": "Unlimited", "billing.usage.unlimited": "Unlimited",
"blocks.bubbles.embed.blockCard.tooltip": "Embed a pdf, an iframe, a website...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Upload Files",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"cancel": "Cancel", "cancel": "Cancel",
"clickToEdit": "Click to edit...",
"confirmModal.defaultTitle": "Are you sure?", "confirmModal.defaultTitle": "Are you sure?",
"dashboard.header.settingsButton.label": "Settings & Members", "dashboard.header.settingsButton.label": "Settings & Members",
"dashboard.redirectionMessage": "You are being redirected...", "dashboard.redirectionMessage": "You are being redirected...",
"dashboard.title": "My typebots", "dashboard.title": "My typebots",
"delete": "Delete", "delete": "Delete",
"downgrade": "Downgrade", "downgrade": "Downgrade",
"blocks.bubbles.embed.blockCard.tooltip": "Embed a pdf, an iframe, a website...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Upload Files",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"editor.blockCard.logicBlock.tooltip.code.label": "Execute Javascript code", "editor.blockCard.logicBlock.tooltip.code.label": "Execute Javascript code",
"editor.blockCard.logicBlock.tooltip.jump.label": "Fast forward the flow to another group", "editor.blockCard.logicBlock.tooltip.jump.label": "Fast forward the flow to another group",
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link and jump to another typebot", "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link and jump to another typebot",
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Click to edit...",
"editor.blocks.bubbles.audio.settings.autoplay.label": "Enable autoplay", "editor.blocks.bubbles.audio.settings.autoplay.label": "Enable autoplay",
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Choose a file", "editor.blocks.bubbles.audio.settings.chooseFile.label": "Choose a file",
"editor.blocks.bubbles.audio.settings.embedLink.label": "Embed link", "editor.blocks.bubbles.audio.settings.embedLink.label": "Embed link",
"editor.blocks.bubbles.audio.settings.upload.label": "Upload", "editor.blocks.bubbles.audio.settings.upload.label": "Upload",
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Paste the audio file link...", "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Paste the audio file link...",
"editor.blocks.bubbles.audio.settings.worksWith.text": "Works with .MP3s and .WAVs", "editor.blocks.bubbles.audio.settings.worksWith.text": "Works with .MP3s and .WAVs",
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Click to edit...",
"editor.blocks.bubbles.embed.node.show.text": "Show embed", "editor.blocks.bubbles.embed.node.show.text": "Show embed",
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px", "editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Paste the link or code...", "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Paste the link or code...",
"editor.blocks.bubbles.embed.settings.worksWith.text": "Works with PDFs, iframes, websites...", "editor.blocks.bubbles.embed.settings.worksWith.text": "Works with PDFs, iframes, websites...",
"editor.blocks.bubbles.image.node.clickToEdit.text": "Click to edit...",
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "On click link", "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "On click link",
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link alt text (description)", "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link alt text (description)",
"editor.blocks.bubbles.textEditor.plate.label": "Text editor", "editor.blocks.bubbles.textEditor.plate.label": "Text editor",
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Search for a variable", "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Search for a variable",
"editor.blocks.bubbles.video.node.clickToEdit.text": "Click to edit...",
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Paste the video link...",
"editor.blocks.bubbles.video.settings.worksWith.text": "Works with Youtube, Vimeo and others",
"editor.blocks.start.text": "Start", "editor.blocks.start.text": "Start",
"editor.editableTypebotName.tooltip.rename.label": "Rename", "editor.editableTypebotName.tooltip.rename.label": "Rename",
"editor.gettingStartedModal.editorBasics.heading": "Editor Basics", "editor.gettingStartedModal.editorBasics.heading": "Editor Basics",
"editor.gettingStartedModal.editorBasics.list.four.label": "Preview your bot by clicking the preview button on the top right", "editor.gettingStartedModal.editorBasics.list.four.label": "Preview your bot by clicking the preview button on the top right",
"editor.gettingStartedModal.editorBasics.list.label": "Feel free to use the bottom-right bubble to reach out if you have any question. I usually answer within the next 24 hours. 😃", "editor.gettingStartedModal.editorBasics.list.label": "Feel free to use the bottom-right bubble to reach out if you have any question. I usually answer within the next 24 hours. \uD83D\uDE03",
"editor.gettingStartedModal.editorBasics.list.one.label": "The left side bar contains blocks that you can drag and drop to the board.", "editor.gettingStartedModal.editorBasics.list.one.label": "The left side bar contains blocks that you can drag and drop to the board.",
"editor.gettingStartedModal.editorBasics.list.three.label": "Connect the groups together", "editor.gettingStartedModal.editorBasics.list.three.label": "Connect the groups together",
"editor.gettingStartedModal.editorBasics.list.two.label": "You can group blocks together by dropping them below or above each other", "editor.gettingStartedModal.editorBasics.list.two.label": "You can group blocks together by dropping them below or above each other",
@ -231,12 +226,18 @@
"templates.modal.menuHeading.product": "Product", "templates.modal.menuHeading.product": "Product",
"templates.modal.useTemplateButton.label": "Use this template", "templates.modal.useTemplateButton.label": "Use this template",
"upgrade": "Upgrade", "upgrade": "Upgrade",
"video.aspectRatioInput.label": "Aspect ratio",
"video.aspectRatioInput.moreInfoTooltip": "Example: \"16/9\" or \"9/16",
"video.maxWidthInput.label": "Max width",
"video.maxWidthInput.moreInfoTooltip": "Example: \"300px\" or \"100%",
"video.urlInput.helperText": "Works with Youtube, Vimeo, Gumlet, TikTok and others",
"video.urlInput.placeholder": "Paste the video link...",
"workspace.dropdown.logoutButton.label": "Log out", "workspace.dropdown.logoutButton.label": "Log out",
"workspace.dropdown.newButton.label": "New workspace", "workspace.dropdown.newButton.label": "New workspace",
"workspace.membersList.inviteButton.label": "Invite", "workspace.membersList.inviteButton.label": "Invite",
"workspace.membersList.inviteInput.placeholder": "colleague@company.com", "workspace.membersList.inviteInput.placeholder": "colleague@company.com",
"workspace.membersList.title": "Members", "workspace.membersList.title": "Members",
"workspace.membersList.unlockBanner.label": "Upgrade your plan to work with more team members, and unlock awesome power features 🚀", "workspace.membersList.unlockBanner.label": "Upgrade your plan to work with more team members, and unlock awesome power features \uD83D\uDE80",
"workspace.settings.deleteButton.confirmMessage": "Are you sure you want to delete {workspaceName} workspace? All its folders, typebots and results will be deleted forever.", "workspace.settings.deleteButton.confirmMessage": "Are you sure you want to delete {workspaceName} workspace? All its folders, typebots and results will be deleted forever.",
"workspace.settings.deleteButton.label": "Delete workspace", "workspace.settings.deleteButton.label": "Delete workspace",
"workspace.settings.icon.title": "Icon", "workspace.settings.icon.title": "Icon",
@ -247,6 +248,5 @@
"workspace.settings.modal.menu.settings.label": "Settings", "workspace.settings.modal.menu.settings.label": "Settings",
"workspace.settings.modal.menu.version.label": "Version: {version}", "workspace.settings.modal.menu.version.label": "Version: {version}",
"workspace.settings.modal.menu.workspace.label": "Workspace", "workspace.settings.modal.menu.workspace.label": "Workspace",
"workspace.settings.name.label": "Name:", "workspace.settings.name.label": "Name:"
"billing.tiersModal.heading": "Chats pricing table"
} }

View File

@ -102,6 +102,7 @@
"billing.pricingCard.starter.fileUploadBlock": "Bloc d'upload de fichier", "billing.pricingCard.starter.fileUploadBlock": "Bloc d'upload de fichier",
"billing.pricingCard.starter.includedSeats": "2 collègues inclus", "billing.pricingCard.starter.includedSeats": "2 collègues inclus",
"billing.pricingCard.upgradeButton.current": "Abonnement actuel", "billing.pricingCard.upgradeButton.current": "Abonnement actuel",
"billing.tiersModal.heading": "Table des prix des chats",
"billing.updateSuccessToast.description": "Ton abonnement {plan} a été mis à jour avec succès \uD83C\uDF89", "billing.updateSuccessToast.description": "Ton abonnement {plan} a été mis à jour avec succès \uD83C\uDF89",
"billing.upgradeAlert.buttonDefaultLabel": "Plus d'informations", "billing.upgradeAlert.buttonDefaultLabel": "Plus d'informations",
"billing.upgradeLimitLabel": "Tu dois mettre à niveau ton abonnement pour {type}", "billing.upgradeLimitLabel": "Tu dois mettre à niveau ton abonnement pour {type}",
@ -110,41 +111,35 @@
"billing.usage.chats.heading": "Chats", "billing.usage.chats.heading": "Chats",
"billing.usage.heading": "Utilisation", "billing.usage.heading": "Utilisation",
"billing.usage.unlimited": "Illimité", "billing.usage.unlimited": "Illimité",
"blocks.bubbles.embed.blockCard.tooltip": "Intégrer un pdf, un iframe, un site web...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Télécharger des fichiers",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"cancel": "Annuler", "cancel": "Annuler",
"clickToEdit": "Clique pour modifier...",
"confirmModal.defaultTitle": "Es-tu sûr ?", "confirmModal.defaultTitle": "Es-tu sûr ?",
"dashboard.header.settingsButton.label": "Paramètres & Membres", "dashboard.header.settingsButton.label": "Paramètres & Membres",
"dashboard.redirectionMessage": "Redirection en cours...", "dashboard.redirectionMessage": "Redirection en cours...",
"dashboard.title": "Mes typebots", "dashboard.title": "Mes typebots",
"delete": "Supprimer", "delete": "Supprimer",
"downgrade": "Downgrade", "downgrade": "Downgrade",
"blocks.bubbles.embed.blockCard.tooltip": "Intégrer un pdf, un iframe, un site web...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Télécharger des fichiers",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"editor.blockCard.logicBlock.tooltip.code.label": "Exécuter du code Javascript", "editor.blockCard.logicBlock.tooltip.code.label": "Exécuter du code Javascript",
"editor.blockCard.logicBlock.tooltip.jump.label": "Passer rapidement au groupe suivant", "editor.blockCard.logicBlock.tooltip.jump.label": "Passer rapidement au groupe suivant",
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Lier et exécuter un autre typebot", "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Lier et exécuter un autre typebot",
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Cliquez pour modifier...",
"editor.blocks.bubbles.audio.settings.autoplay.label": "Activer la lecture automatique", "editor.blocks.bubbles.audio.settings.autoplay.label": "Activer la lecture automatique",
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Choisir un fichier", "editor.blocks.bubbles.audio.settings.chooseFile.label": "Choisir un fichier",
"editor.blocks.bubbles.audio.settings.embedLink.label": "Lien intégré", "editor.blocks.bubbles.audio.settings.embedLink.label": "Lien intégré",
"editor.blocks.bubbles.audio.settings.upload.label": "Uploader", "editor.blocks.bubbles.audio.settings.upload.label": "Uploader",
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Collez le lien du fichier audio...", "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Collez le lien du fichier audio...",
"editor.blocks.bubbles.audio.settings.worksWith.text": "Fonctionne avec les fichiers .MP3 et .WAV", "editor.blocks.bubbles.audio.settings.worksWith.text": "Fonctionne avec les fichiers .MP3 et .WAV",
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Cliquez pour modifier...",
"editor.blocks.bubbles.embed.node.show.text": "Afficher l'intégration", "editor.blocks.bubbles.embed.node.show.text": "Afficher l'intégration",
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px", "editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Collez le lien ou le code...", "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Collez le lien ou le code...",
"editor.blocks.bubbles.embed.settings.worksWith.text": "Fonctionne avec les PDF, les iframes, les sites web...", "editor.blocks.bubbles.embed.settings.worksWith.text": "Fonctionne avec les PDF, les iframes, les sites web...",
"editor.blocks.bubbles.image.node.clickToEdit.text": "Cliquez pour modifier...",
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Redirection au clic", "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Redirection au clic",
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texte alternatif du lien (description)", "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texte alternatif du lien (description)",
"editor.blocks.bubbles.textEditor.plate.label": "Éditeur de texte", "editor.blocks.bubbles.textEditor.plate.label": "Éditeur de texte",
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Rechercher une variable", "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Rechercher une variable",
"editor.blocks.bubbles.video.node.clickToEdit.text": "Cliquez pour modifier...",
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Collez le lien de la vidéo...",
"editor.blocks.bubbles.video.settings.worksWith.text": "Fonctionne avec Youtube, Vimeo et autres",
"editor.blocks.start.text": "Démarrer", "editor.blocks.start.text": "Démarrer",
"editor.editableTypebotName.tooltip.rename.label": "Renommer", "editor.editableTypebotName.tooltip.rename.label": "Renommer",
"editor.gettingStartedModal.editorBasics.heading": "Principes de base de l'éditeur", "editor.gettingStartedModal.editorBasics.heading": "Principes de base de l'éditeur",
@ -231,6 +226,12 @@
"templates.modal.menuHeading.product": "Produit", "templates.modal.menuHeading.product": "Produit",
"templates.modal.useTemplateButton.label": "Utiliser ce modèle", "templates.modal.useTemplateButton.label": "Utiliser ce modèle",
"upgrade": "Upgrade", "upgrade": "Upgrade",
"video.aspectRatioInput.label": "Ratio",
"video.aspectRatioInput.moreInfoTooltip": "Exemple: \"16/9\" ou \"9/16\"",
"video.maxWidthInput.label": "Largeur max",
"video.maxWidthInput.moreInfoTooltip": "Exemple: \"300px\" ou \"100%\"",
"video.urlInput.helperText": "Fonctionne avec Youtube, Vimeo, Gumlet, TikTok et autres",
"video.urlInput.placeholder": "Collez le lien de la vidéo...",
"workspace.dropdown.logoutButton.label": "Déconnexion", "workspace.dropdown.logoutButton.label": "Déconnexion",
"workspace.dropdown.newButton.label": "Nouveau workspace", "workspace.dropdown.newButton.label": "Nouveau workspace",
"workspace.membersList.inviteButton.label": "Inviter", "workspace.membersList.inviteButton.label": "Inviter",

View File

@ -102,6 +102,7 @@
"billing.pricingCard.starter.fileUploadBlock": "Bloco de envio de arquivo", "billing.pricingCard.starter.fileUploadBlock": "Bloco de envio de arquivo",
"billing.pricingCard.starter.includedSeats": "2 assentos incluídos", "billing.pricingCard.starter.includedSeats": "2 assentos incluídos",
"billing.pricingCard.upgradeButton.current": "Sua assinatura atual", "billing.pricingCard.upgradeButton.current": "Sua assinatura atual",
"billing.tiersModal.heading": "Tabela de preço de chats",
"billing.updateSuccessToast.description": "Sua assinatura {plan} foi atualizada com sucesso \uD83C\uDF89", "billing.updateSuccessToast.description": "Sua assinatura {plan} foi atualizada com sucesso \uD83C\uDF89",
"billing.upgradeAlert.buttonDefaultLabel": "Mais informações", "billing.upgradeAlert.buttonDefaultLabel": "Mais informações",
"billing.upgradeLimitLabel": "Você precisa atualizar sua assinatura para {type}", "billing.upgradeLimitLabel": "Você precisa atualizar sua assinatura para {type}",
@ -110,41 +111,35 @@
"billing.usage.chats.heading": "Chats", "billing.usage.chats.heading": "Chats",
"billing.usage.heading": "Uso", "billing.usage.heading": "Uso",
"billing.usage.unlimited": "Ilimitado", "billing.usage.unlimited": "Ilimitado",
"blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Carregar Ficheiros",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"cancel": "Cancelar", "cancel": "Cancelar",
"clickToEdit": "Clique para editar...",
"confirmModal.defaultTitle": "Tem certeza?", "confirmModal.defaultTitle": "Tem certeza?",
"dashboard.header.settingsButton.label": "Configurações & Membros", "dashboard.header.settingsButton.label": "Configurações & Membros",
"dashboard.redirectionMessage": "Você está sendo redirecionado...", "dashboard.redirectionMessage": "Você está sendo redirecionado...",
"dashboard.title": "Meus typebots", "dashboard.title": "Meus typebots",
"delete": "Apagar", "delete": "Apagar",
"downgrade": "Downgrade", "downgrade": "Downgrade",
"blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Carregar Ficheiros",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript", "editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript",
"editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo", "editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo",
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot", "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot",
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Clique para editar...",
"editor.blocks.bubbles.audio.settings.autoplay.label": "Ativar reprodução automática", "editor.blocks.bubbles.audio.settings.autoplay.label": "Ativar reprodução automática",
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Escolher um arquivo", "editor.blocks.bubbles.audio.settings.chooseFile.label": "Escolher um arquivo",
"editor.blocks.bubbles.audio.settings.embedLink.label": "Incorporar link", "editor.blocks.bubbles.audio.settings.embedLink.label": "Incorporar link",
"editor.blocks.bubbles.audio.settings.upload.label": "Carregar", "editor.blocks.bubbles.audio.settings.upload.label": "Carregar",
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Colar o link do arquivo de áudio...", "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Colar o link do arquivo de áudio...",
"editor.blocks.bubbles.audio.settings.worksWith.text": "Compatível com .MP3s e .WAVs", "editor.blocks.bubbles.audio.settings.worksWith.text": "Compatível com .MP3s e .WAVs",
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Clique para editar...",
"editor.blocks.bubbles.embed.node.show.text": "Mostrar incorporação", "editor.blocks.bubbles.embed.node.show.text": "Mostrar incorporação",
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px", "editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Colar o link ou código...", "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Colar o link ou código...",
"editor.blocks.bubbles.embed.settings.worksWith.text": "Compatível com PDFs, iframes, websites...", "editor.blocks.bubbles.embed.settings.worksWith.text": "Compatível com PDFs, iframes, websites...",
"editor.blocks.bubbles.image.node.clickToEdit.text": "Clique para editar...",
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Link ao clicar", "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Link ao clicar",
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)", "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)",
"editor.blocks.bubbles.textEditor.plate.label": "Editor de texto", "editor.blocks.bubbles.textEditor.plate.label": "Editor de texto",
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável", "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável",
"editor.blocks.bubbles.video.node.clickToEdit.text": "Clique para editar...",
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Colar o link do vídeo...",
"editor.blocks.bubbles.video.settings.worksWith.text": "Compatível com Youtube, Vimeo e outros",
"editor.blocks.start.text": "Início", "editor.blocks.start.text": "Início",
"editor.editableTypebotName.tooltip.rename.label": "Renomear", "editor.editableTypebotName.tooltip.rename.label": "Renomear",
"editor.gettingStartedModal.editorBasics.heading": "Fundamentos do Editor", "editor.gettingStartedModal.editorBasics.heading": "Fundamentos do Editor",
@ -231,6 +226,8 @@
"templates.modal.menuHeading.product": "Produto", "templates.modal.menuHeading.product": "Produto",
"templates.modal.useTemplateButton.label": "Usar esse modelo", "templates.modal.useTemplateButton.label": "Usar esse modelo",
"upgrade": "Upgrade", "upgrade": "Upgrade",
"video.urlInput.helperText": "Compatível com Youtube, Vimeo, Gumlet, TikTok e outros",
"video.urlInput.placeholder": "Colar o link do vídeo...",
"workspace.dropdown.logoutButton.label": "Sair", "workspace.dropdown.logoutButton.label": "Sair",
"workspace.dropdown.newButton.label": "Novo espaço de trabalho", "workspace.dropdown.newButton.label": "Novo espaço de trabalho",
"workspace.membersList.inviteButton.label": "Convidar", "workspace.membersList.inviteButton.label": "Convidar",

View File

@ -110,41 +110,35 @@
"billing.usage.chats.heading": "Chats", "billing.usage.chats.heading": "Chats",
"billing.usage.heading": "Uso", "billing.usage.heading": "Uso",
"billing.usage.unlimited": "Ilimitado", "billing.usage.unlimited": "Ilimitado",
"blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Carregar Ficheiros",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"cancel": "Cancelar", "cancel": "Cancelar",
"clickToEdit": "Clique para editar...",
"confirmModal.defaultTitle": "Tem a certeza?", "confirmModal.defaultTitle": "Tem a certeza?",
"dashboard.header.settingsButton.label": "Configurações & Membros", "dashboard.header.settingsButton.label": "Configurações & Membros",
"dashboard.redirectionMessage": "Está a ser redirecionado...", "dashboard.redirectionMessage": "Está a ser redirecionado...",
"dashboard.title": "Os meus typebots", "dashboard.title": "Os meus typebots",
"delete": "Apagar", "delete": "Apagar",
"downgrade": "Downgrade", "downgrade": "Downgrade",
"blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...",
"blocks.inputs.fileUpload.blockCard.tooltip": "Carregar Ficheiros",
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
"editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript", "editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript",
"editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo", "editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo",
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot", "editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot",
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Clique para editar...",
"editor.blocks.bubbles.audio.settings.autoplay.label": "Ativar reprodução automática", "editor.blocks.bubbles.audio.settings.autoplay.label": "Ativar reprodução automática",
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Escolher um ficheiro", "editor.blocks.bubbles.audio.settings.chooseFile.label": "Escolher um ficheiro",
"editor.blocks.bubbles.audio.settings.embedLink.label": "Incorporar link", "editor.blocks.bubbles.audio.settings.embedLink.label": "Incorporar link",
"editor.blocks.bubbles.audio.settings.upload.label": "Carregar", "editor.blocks.bubbles.audio.settings.upload.label": "Carregar",
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Colar o link do ficheiro de áudio...", "editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Colar o link do ficheiro de áudio...",
"editor.blocks.bubbles.audio.settings.worksWith.text": "Compatível com .MP3s e .WAVs", "editor.blocks.bubbles.audio.settings.worksWith.text": "Compatível com .MP3s e .WAVs",
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Clique para editar...",
"editor.blocks.bubbles.embed.node.show.text": "Mostrar incorporação", "editor.blocks.bubbles.embed.node.show.text": "Mostrar incorporação",
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px", "editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Colar o link ou código...", "editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Colar o link ou código...",
"editor.blocks.bubbles.embed.settings.worksWith.text": "Compatível com PDFs, iframes, websites...", "editor.blocks.bubbles.embed.settings.worksWith.text": "Compatível com PDFs, iframes, websites...",
"editor.blocks.bubbles.image.node.clickToEdit.text": "Clique para editar...",
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Link ao clicar", "editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Link ao clicar",
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)", "editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)",
"editor.blocks.bubbles.textEditor.plate.label": "Editor de texto", "editor.blocks.bubbles.textEditor.plate.label": "Editor de texto",
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável", "editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável",
"editor.blocks.bubbles.video.node.clickToEdit.text": "Clique para editar...",
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Colar o link do vídeo...",
"editor.blocks.bubbles.video.settings.worksWith.text": "Compatível com Youtube, Vimeo e outros",
"editor.blocks.start.text": "Começar", "editor.blocks.start.text": "Começar",
"editor.editableTypebotName.tooltip.rename.label": "Renomear", "editor.editableTypebotName.tooltip.rename.label": "Renomear",
"editor.gettingStartedModal.editorBasics.heading": "Noções básicas de editor", "editor.gettingStartedModal.editorBasics.heading": "Noções básicas de editor",
@ -231,6 +225,8 @@
"templates.modal.menuHeading.product": "Produto", "templates.modal.menuHeading.product": "Produto",
"templates.modal.useTemplateButton.label": "Usar este modelo", "templates.modal.useTemplateButton.label": "Usar este modelo",
"upgrade": "Upgrade", "upgrade": "Upgrade",
"video.urlInput.helperText": "Compatível com Youtube, Vimeo, Gumlet, TikTok e outros",
"video.urlInput.placeholder": "Colar o link do vídeo...",
"workspace.dropdown.logoutButton.label": "Sair", "workspace.dropdown.logoutButton.label": "Sair",
"workspace.dropdown.newButton.label": "Novo espaço de trabalho", "workspace.dropdown.newButton.label": "Novo espaço de trabalho",
"workspace.membersList.inviteButton.label": "Convidar", "workspace.membersList.inviteButton.label": "Convidar",

View File

@ -8,6 +8,7 @@ import {
HStack, HStack,
Input as ChakraInput, Input as ChakraInput,
InputProps, InputProps,
Stack,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { Variable } from '@typebot.io/schemas' import { Variable } from '@typebot.io/schemas'
import React, { import React, {
@ -33,6 +34,7 @@ export type TextInputProps = {
isRequired?: boolean isRequired?: boolean
placeholder?: string placeholder?: string
isDisabled?: boolean isDisabled?: boolean
direction?: 'row' | 'column'
} & Pick< } & Pick<
InputProps, InputProps,
| 'autoComplete' | 'autoComplete'
@ -63,6 +65,7 @@ export const TextInput = forwardRef(function TextInput(
onKeyUp, onKeyUp,
size, size,
maxWidth, maxWidth,
direction = 'column',
}: TextInputProps, }: TextInputProps,
ref ref
) { ) {
@ -134,9 +137,15 @@ export const TextInput = forwardRef(function TextInput(
) )
return ( return (
<FormControl isRequired={isRequired}> <FormControl
isRequired={isRequired}
as={direction === 'column' ? Stack : HStack}
justifyContent="space-between"
width={label ? 'full' : 'auto'}
spacing={direction === 'column' ? 2 : 3}
>
{label && ( {label && (
<FormLabel> <FormLabel display="flex" flexShrink={0} gap="1" mb="0" mr="0">
{label}{' '} {label}{' '}
{moreInfoTooltip && ( {moreInfoTooltip && (
<MoreInfoTooltip>{moreInfoTooltip}</MoreInfoTooltip> <MoreInfoTooltip>{moreInfoTooltip}</MoreInfoTooltip>

View File

@ -1,7 +1,10 @@
import { useTranslate } from '@tolgee/react' import { useTranslate } from '@tolgee/react'
import { Box, Text, Image } from '@chakra-ui/react' import { Box, Text, Image } from '@chakra-ui/react'
import { VideoBubbleBlock } from '@typebot.io/schemas' import { VideoBubbleBlock } from '@typebot.io/schemas'
import { VideoBubbleContentType } from '@typebot.io/schemas/features/blocks/bubbles/video/constants' import {
VideoBubbleContentType,
embedBaseUrls,
} from '@typebot.io/schemas/features/blocks/bubbles/video/constants'
type Props = { type Props = {
block: VideoBubbleBlock block: VideoBubbleBlock
@ -45,17 +48,32 @@ export const VideoBubbleContent = ({ block }: Props) => {
)} )}
</Box> </Box>
) )
case VideoBubbleContentType.GUMLET:
case VideoBubbleContentType.VIMEO: case VideoBubbleContentType.VIMEO:
case VideoBubbleContentType.YOUTUBE: { case VideoBubbleContentType.YOUTUBE: {
const baseUrl = const baseUrl = embedBaseUrls[block.content.type]
block.content.type === VideoBubbleContentType.VIMEO
? 'https://player.vimeo.com/video'
: 'https://www.youtube.com/embed'
return ( return (
<Box w="full" h="120px" pos="relative"> <Box w="full" h="120px" pos="relative">
<iframe <iframe
src={`${baseUrl}/${block.content.id}`} src={`${baseUrl}/${block.content.id}`}
allowFullScreen style={{
width: '100%',
height: '100%',
position: 'absolute',
left: '0',
top: '0',
borderRadius: '10px',
pointerEvents: 'none',
}}
/>
</Box>
)
}
case VideoBubbleContentType.TIKTOK: {
return (
<Box w="full" h="300px" pos="relative">
<iframe
src={`https://www.tiktok.com/embed/v2/${block.content.id}`}
style={{ style={{
width: '100%', width: '100%',
height: '100%', height: '100%',

View File

@ -1,12 +1,9 @@
import { Stack, Text } from '@chakra-ui/react' import { Stack, Text } from '@chakra-ui/react'
import { VariableString, VideoBubbleBlock } from '@typebot.io/schemas' import { VideoBubbleBlock } from '@typebot.io/schemas'
import { NumberInput, TextInput } from '@/components/inputs' import { TextInput } from '@/components/inputs'
import { useTranslate } from '@tolgee/react' import { useTranslate } from '@tolgee/react'
import { parseVideoUrl } from '@typebot.io/lib/parseVideoUrl' import { parseVideoUrl } from '@typebot.io/lib/parseVideoUrl'
import { import { defaultVideoBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/video/constants'
VideoBubbleContentType,
defaultVideoBubbleContent,
} from '@typebot.io/schemas/features/blocks/bubbles/video/constants'
type Props = { type Props = {
content?: VideoBubbleBlock['content'] content?: VideoBubbleBlock['content']
@ -16,42 +13,69 @@ type Props = {
export const VideoUploadContent = ({ content, onSubmit }: Props) => { export const VideoUploadContent = ({ content, onSubmit }: Props) => {
const { t } = useTranslate() const { t } = useTranslate()
const updateUrl = (url: string) => { const updateUrl = (url: string) => {
const info = parseVideoUrl(url) const {
return onSubmit({ type,
type: info.type, url: matchedUrl,
url, id,
id: info.id, videoSizeSuggestion,
}) } = parseVideoUrl(url)
}
const updateHeight = (height?: number | VariableString) => {
return onSubmit({ return onSubmit({
...content, ...content,
height, type,
url: matchedUrl,
id,
...(!content?.aspectRatio && !content?.maxWidth
? videoSizeSuggestion
: {}),
}) })
} }
const updateAspectRatio = (aspectRatio?: string) => {
return onSubmit({
...content,
aspectRatio,
})
}
const updateMaxWidth = (maxWidth?: string) => {
return onSubmit({
...content,
maxWidth,
})
}
return ( return (
<Stack p="2" spacing={4}> <Stack p="2" spacing={4}>
<Stack> <Stack>
<TextInput <TextInput
placeholder={t( placeholder={t('video.urlInput.placeholder')}
'editor.blocks.bubbles.video.settings.worksWith.placeholder'
)}
defaultValue={content?.url ?? ''} defaultValue={content?.url ?? ''}
onChange={updateUrl} onChange={updateUrl}
/> />
<Text fontSize="sm" color="gray.400" textAlign="center"> <Text fontSize="xs" color="gray.400" textAlign="center">
{t('editor.blocks.bubbles.video.settings.worksWith.text')} {t('video.urlInput.helperText')}
</Text> </Text>
</Stack> </Stack>
{content?.url && (
{content?.type !== VideoBubbleContentType.URL && ( <Stack>
<NumberInput <TextInput
label="Height:" label={t('video.aspectRatioInput.label')}
defaultValue={content?.height ?? defaultVideoBubbleContent.height} moreInfoTooltip={t('video.aspectRatioInput.moreInfoTooltip')}
onValueChange={updateHeight} defaultValue={
suffix={t('editor.blocks.bubbles.video.settings.numberInput.unit')} content?.aspectRatio ?? defaultVideoBubbleContent.aspectRatio
width="150px" }
onChange={updateAspectRatio}
direction="row"
/> />
<TextInput
label={t('video.maxWidthInput.label')}
moreInfoTooltip={t('video.maxWidthInput.moreInfoTooltip')}
defaultValue={
content?.maxWidth ?? defaultVideoBubbleContent.maxWidth
}
onChange={updateMaxWidth}
direction="row"
/>
</Stack>
)} )}
</Stack> </Stack>
) )

View File

@ -5,13 +5,14 @@ import fr from '../../public/locales/fr.json'
import de from '../../public/locales/de.json' import de from '../../public/locales/de.json'
import pt from '../../public/locales/pt.json' import pt from '../../public/locales/pt.json'
import ptBR from '../../public/locales/pt-BR.json' import ptBR from '../../public/locales/pt-BR.json'
import { env } from '@typebot.io/env'
export const tolgee = Tolgee() export const tolgee = Tolgee()
.use(DevTools()) .use(DevTools())
.use(FormatIcu()) .use(FormatIcu())
.init({ .init({
apiKey: process.env.NEXT_PUBLIC_TOLGEE_API_KEY, apiKey: env.NEXT_PUBLIC_TOLGEE_API_KEY,
apiUrl: process.env.NEXT_PUBLIC_TOLGEE_API_URL, apiUrl: env.NEXT_PUBLIC_TOLGEE_API_URL,
defaultLanguage: 'en', defaultLanguage: 'en',
availableLanguages: ['en', 'fr', 'de', 'pt', 'pt-BR'], availableLanguages: ['en', 'fr', 'de', 'pt', 'pt-BR'],
fallbackLanguage: 'en', fallbackLanguage: 'en',

View File

@ -13,7 +13,9 @@
"build:apps": "turbo run build --filter=builder... --filter=viewer...", "build:apps": "turbo run build --filter=builder... --filter=viewer...",
"db:migrate": "cd packages/prisma && pnpm run db:migrate", "db:migrate": "cd packages/prisma && pnpm run db:migrate",
"generate-change-log": "git fetch --all && pnpx gitmoji-changelog", "generate-change-log": "git fetch --all && pnpx gitmoji-changelog",
"locales:sync": "tolgee sync './apps/builder/src/**/*.ts?(x)' --continue-on-warning --remove-unused" "locales:sync": "tolgee sync './apps/builder/src/**/*.ts?(x)' --continue-on-warning --remove-unused",
"locales:push": "tolgee push ./apps/builder/public/locales",
"locales:pull": "tolgee pull ./apps/builder/public/locales"
}, },
"devDependencies": { "devDependencies": {
"cross-env": "7.0.3", "cross-env": "7.0.3",
@ -21,7 +23,7 @@
"husky": "8.0.3", "husky": "8.0.3",
"prettier": "2.8.8", "prettier": "2.8.8",
"turbo": "1.10.12", "turbo": "1.10.12",
"@tolgee/cli": "1.2.0" "@tolgee/cli": "1.3.2"
}, },
"config": { "config": {
"commitizen": { "commitizen": {

View File

@ -69,9 +69,11 @@ export const parseBubbleBlock = (
const parsedContent = block.content const parsedContent = block.content
? deepParseVariables(variables)(block.content) ? deepParseVariables(variables)(block.content)
: undefined : undefined
return { return {
...block, ...block,
content: { content: {
...parsedContent,
...(parsedContent?.url ? parseVideoUrl(parsedContent.url) : {}), ...(parsedContent?.url ? parseVideoUrl(parsedContent.url) : {}),
height: height:
typeof parsedContent?.height === 'string' typeof parsedContent?.height === 'string'

View File

@ -4,9 +4,14 @@ import { createSignal, Match, onCleanup, onMount, Switch } from 'solid-js'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { import {
defaultVideoBubbleContent, defaultVideoBubbleContent,
embedBaseUrls,
embeddableVideoTypes,
VideoBubbleContentType, VideoBubbleContentType,
} from '@typebot.io/schemas/features/blocks/bubbles/video/constants' } from '@typebot.io/schemas/features/blocks/bubbles/video/constants'
import { VideoBubbleBlock } from '@typebot.io/schemas' import {
EmbeddableVideoBubbleContentType,
VideoBubbleBlock,
} from '@typebot.io/schemas'
type Props = { type Props = {
content: VideoBubbleBlock['content'] content: VideoBubbleBlock['content']
@ -23,8 +28,8 @@ export const VideoBubble = (props: Props) => {
onMount(() => { onMount(() => {
const typingDuration = const typingDuration =
props.content?.type && props.content?.type &&
[VideoBubbleContentType.VIMEO, VideoBubbleContentType.YOUTUBE].includes( embeddableVideoTypes.includes(
props.content?.type props.content?.type as EmbeddableVideoBubbleContentType
) )
? 2000 ? 2000
: 100 : 100
@ -50,6 +55,8 @@ export const VideoBubble = (props: Props) => {
style={{ style={{
width: isTyping() ? '64px' : '100%', width: isTyping() ? '64px' : '100%',
height: isTyping() ? '32px' : '100%', height: isTyping() ? '32px' : '100%',
'max-width':
props.content?.maxWidth ?? defaultVideoBubbleContent.maxWidth,
}} }}
> >
{isTyping() && <TypingBubble />} {isTyping() && <TypingBubble />}
@ -71,16 +78,19 @@ export const VideoBubble = (props: Props) => {
} }
style={{ style={{
height: isTyping() ? (isMobile() ? '32px' : '36px') : 'auto', height: isTyping() ? (isMobile() ? '32px' : '36px') : 'auto',
'aspect-ratio': props.content?.aspectRatio,
'max-width':
props.content?.maxWidth ??
defaultVideoBubbleContent.maxWidth,
}} }}
/> />
</Match> </Match>
<Match <Match
when={ when={
props.content?.type && props.content?.type &&
[ embeddableVideoTypes.includes(
VideoBubbleContentType.VIMEO, props.content.type as EmbeddableVideoBubbleContentType
VideoBubbleContentType.YOUTUBE, )
].includes(props.content.type)
} }
> >
<div <div
@ -93,17 +103,23 @@ export const VideoBubble = (props: Props) => {
? isMobile() ? isMobile()
? '32px' ? '32px'
: '36px' : '36px'
: `${ : !props.content?.aspectRatio
? `${
props.content?.height ?? props.content?.height ??
defaultVideoBubbleContent.height defaultVideoBubbleContent.height
}px`, }px`
: undefined,
'aspect-ratio': props.content?.aspectRatio,
'max-width':
props.content?.maxWidth ??
defaultVideoBubbleContent.maxWidth,
}} }}
> >
<iframe <iframe
src={`${ src={`${
props.content?.type === VideoBubbleContentType.VIMEO embedBaseUrls[
? 'https://player.vimeo.com/video' props.content?.type as EmbeddableVideoBubbleContentType
: 'https://www.youtube.com/embed' ]
}/${props.content?.id}`} }/${props.content?.id}`}
class={'w-full h-full'} class={'w-full h-full'}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"

7
packages/env/env.ts vendored
View File

@ -279,15 +279,16 @@ const tolgeeEnv = {
NEXT_PUBLIC_TOLGEE_API_URL: z NEXT_PUBLIC_TOLGEE_API_URL: z
.string() .string()
.url() .url()
.default('https://tolgee.server.baptistearno.com"') .optional()
.optional(), .default('https://tolgee.server.baptistearno.com"'),
}, },
runtimeEnv: { runtimeEnv: {
NEXT_PUBLIC_TOLGEE_API_KEY: getRuntimeVariable( NEXT_PUBLIC_TOLGEE_API_KEY: getRuntimeVariable(
'NEXT_PUBLIC_TOLGEE_API_KEY' 'NEXT_PUBLIC_TOLGEE_API_KEY'
), ),
NEXT_PUBLIC_TOLGEE_API_URL: getRuntimeVariable( NEXT_PUBLIC_TOLGEE_API_URL: getRuntimeVariable(
'NEXT_PUBLIC_TOLGEE_API_URL' 'NEXT_PUBLIC_TOLGEE_API_URL',
'https://tolgee.server.baptistearno.com'
), ),
}, },
} }

View File

@ -2,9 +2,9 @@ declare const window: {
__ENV?: any __ENV?: any
} }
export const getRuntimeVariable = (key: string) => { export const getRuntimeVariable = (key: string, defaultValue?: string) => {
if (typeof window !== 'undefined') if (typeof window !== 'undefined')
return window.__ENV ? window.__ENV[key] : undefined return window.__ENV ? window.__ENV[key] ?? defaultValue : undefined
if (typeof process === 'undefined') return undefined if (typeof process === 'undefined') return undefined
return process.env[key] return process.env[key] ?? defaultValue
} }

View File

@ -1,21 +1,74 @@
import { VideoBubbleContentType } from '@typebot.io/schemas/features/blocks/bubbles/video/constants' import { VideoBubbleBlock } from '@typebot.io/schemas'
import {
const vimeoRegex = /vimeo\.com\/(\d+)/ VideoBubbleContentType,
const youtubeRegex = gumletRegex,
/youtube\.com\/(watch\?v=|shorts\/)([\w-]+)|youtu\.be\/([\w-]+)/ horizontalVideoSuggestionSize,
tiktokRegex,
verticalVideoSuggestionSize,
vimeoRegex,
youtubeRegex,
} from '@typebot.io/schemas/features/blocks/bubbles/video/constants'
export const parseVideoUrl = ( export const parseVideoUrl = (
url: string url: string
): { type: VideoBubbleContentType; url: string; id?: string } => { ): {
if (vimeoRegex.test(url)) { type: VideoBubbleContentType
const id = url.match(vimeoRegex)?.at(1) url: string
if (!id) return { type: VideoBubbleContentType.URL, url } id?: string
return { type: VideoBubbleContentType.VIMEO, url, id } videoSizeSuggestion?: Pick<
} NonNullable<VideoBubbleBlock['content']>,
'aspectRatio' | 'maxWidth'
>
} => {
if (youtubeRegex.test(url)) { if (youtubeRegex.test(url)) {
const id = url.match(youtubeRegex)?.at(2) ?? url.match(youtubeRegex)?.at(3) const match = url.match(youtubeRegex)
if (!id) return { type: VideoBubbleContentType.URL, url } const id = match?.at(2) ?? match?.at(3)
return { type: VideoBubbleContentType.YOUTUBE, url, id } const parsedUrl = match?.at(0) ?? url
if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl }
return {
type: VideoBubbleContentType.YOUTUBE,
url: parsedUrl,
id,
videoSizeSuggestion: url.includes('shorts')
? verticalVideoSuggestionSize
: horizontalVideoSuggestionSize,
}
}
if (vimeoRegex.test(url)) {
const match = url.match(vimeoRegex)
const id = match?.at(1)
const parsedUrl = match?.at(0) ?? url
if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl }
return {
type: VideoBubbleContentType.VIMEO,
url: parsedUrl,
id,
videoSizeSuggestion: horizontalVideoSuggestionSize,
}
}
if (tiktokRegex.test(url)) {
const match = url.match(tiktokRegex)
const id = url.match(tiktokRegex)?.at(1)
const parsedUrl = match?.at(0) ?? url
if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl }
return {
type: VideoBubbleContentType.TIKTOK,
url: parsedUrl,
id,
videoSizeSuggestion: verticalVideoSuggestionSize,
}
}
if (gumletRegex.test(url)) {
const match = url.match(gumletRegex)
const id = match?.at(1)
const parsedUrl = match?.at(0) ?? url
if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl }
return {
type: VideoBubbleContentType.GUMLET,
url: parsedUrl,
id,
videoSizeSuggestion: horizontalVideoSuggestionSize,
}
} }
return { type: VideoBubbleContentType.URL, url } return { type: VideoBubbleContentType.URL, url }
} }

View File

@ -2,8 +2,49 @@ export enum VideoBubbleContentType {
URL = 'url', URL = 'url',
YOUTUBE = 'youtube', YOUTUBE = 'youtube',
VIMEO = 'vimeo', VIMEO = 'vimeo',
TIKTOK = 'tiktok',
GUMLET = 'gumlet',
} }
export const embeddableVideoTypes = [
VideoBubbleContentType.YOUTUBE,
VideoBubbleContentType.VIMEO,
VideoBubbleContentType.TIKTOK,
VideoBubbleContentType.GUMLET,
] as const
export const defaultVideoBubbleContent = { export const defaultVideoBubbleContent = {
height: 400, height: 400,
aspectRatio: '16/9',
maxWidth: '100%',
} as const
export const horizontalVideoSuggestionSize = {
aspectRatio: '16/9',
maxWidth: '100%',
}
export const verticalVideoSuggestionSize = {
aspectRatio: '9/16',
maxWidth: '400px',
}
const youtubeBaseUrl = 'https://www.youtube.com/embed'
export const youtubeRegex =
/youtube\.com\/(watch\?v=|shorts\/)([\w-]+)|youtu\.be\/([\w-]+)/
const vimeoBaseUrl = 'https://player.vimeo.com/video'
export const vimeoRegex = /vimeo\.com\/(\d+)/
const tiktokBaseUrl = 'https://www.tiktok.com/embed/v2'
export const tiktokRegex = /tiktok\.com\/@[\w-]+\/video\/(\d+)/
const gumletBaseUrl = 'https://play.gumlet.io/embed'
export const gumletRegex = /gumlet\.com\/watch\/(\w+)/
export const embedBaseUrls = {
[VideoBubbleContentType.VIMEO]: vimeoBaseUrl,
[VideoBubbleContentType.YOUTUBE]: youtubeBaseUrl,
[VideoBubbleContentType.TIKTOK]: tiktokBaseUrl,
[VideoBubbleContentType.GUMLET]: gumletBaseUrl,
} as const } as const

View File

@ -9,6 +9,8 @@ export const videoBubbleContentSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
type: z.nativeEnum(VideoBubbleContentType).optional(), type: z.nativeEnum(VideoBubbleContentType).optional(),
height: z.number().or(variableStringSchema).optional(), height: z.number().or(variableStringSchema).optional(),
aspectRatio: z.string().optional(),
maxWidth: z.string().optional(),
}) })
export const videoBubbleBlockSchema = blockBaseSchema.merge( export const videoBubbleBlockSchema = blockBaseSchema.merge(
@ -19,3 +21,7 @@ export const videoBubbleBlockSchema = blockBaseSchema.merge(
) )
export type VideoBubbleBlock = z.infer<typeof videoBubbleBlockSchema> export type VideoBubbleBlock = z.infer<typeof videoBubbleBlockSchema>
export type EmbeddableVideoBubbleContentType = Exclude<
VideoBubbleContentType,
VideoBubbleContentType.URL
>

8
pnpm-lock.yaml generated
View File

@ -9,8 +9,8 @@ importers:
.: .:
devDependencies: devDependencies:
'@tolgee/cli': '@tolgee/cli':
specifier: 1.2.0 specifier: 1.3.2
version: 1.2.0 version: 1.3.2
cross-env: cross-env:
specifier: 7.0.3 specifier: 7.0.3
version: 7.0.3 version: 7.0.3
@ -8645,8 +8645,8 @@ packages:
tippy.js: 6.3.7 tippy.js: 6.3.7
dev: false dev: false
/@tolgee/cli@1.2.0: /@tolgee/cli@1.3.2:
resolution: {integrity: sha512-1DBHdidNR0efuUAMjAtf9MDLC/nIwwYArCHjuscHvd/a3hgsdZYwrj926Ass1npj7RbtBYYTlBNju7qdLKD3Wg==} resolution: {integrity: sha512-7Vf+BFGmQ9jLfDiRrhsgg+h494k0V8BacSdKVZV83PqhibI6/+H9boJvB1oSA+IEwAO9BoBFxy87Y1LN0NI1Cg==}
engines: {node: '>= 18'} engines: {node: '>= 18'}
hasBin: true hasBin: true
dependencies: dependencies: