diff --git a/src/background.ts b/src/background.ts index 66ad7be4..8d701986 100644 --- a/src/background.ts +++ b/src/background.ts @@ -72,14 +72,6 @@ function reloadSeqtaPages() { result.then(open, onError) } -browser.tabs.onUpdated.addListener((tabId, _, tab) => { - if (tab.url?.includes('share.betterseqta')) { - const id = new URL(tab.url).searchParams.get('id'); - const justCreated = new URL(tab.url).searchParams.get('justCreated'); - browser.tabs.update(tabId, { url: `${browser.runtime.getURL('src/interface/index.html')}?id=${id}&justCreated=${justCreated}#theme` }); - } -}); - // Main message listener browser.runtime.onMessage.addListener((request: any, _sender: any, sendResponse: any) => { switch (request.type) { diff --git a/src/interface/components/ThemeCover.tsx b/src/interface/components/ThemeCover.tsx index 3173dd3c..1c72a9b0 100644 --- a/src/interface/components/ThemeCover.tsx +++ b/src/interface/components/ThemeCover.tsx @@ -46,9 +46,8 @@ export const ThemeCover: React.FC = ({ const handleShareClick = (event: React.MouseEvent) => { event?.preventDefault(); setUploading(true); - browser.runtime.sendMessage({ type: 'currentTab', info: 'ShareTheme', body: { themeID: theme.id } }).then((response) => { + browser.runtime.sendMessage({ type: 'currentTab', info: 'ShareTheme', body: { themeID: theme.id } }).then(() => { setUploading(false); - browser.tabs.create({ url: `https://share.betterseqta/theme?id=${response.id}&justCreated=true` }); }); }; @@ -68,7 +67,7 @@ export const ThemeCover: React.FC = ({ )} - { ( !isEditMode ) && !downloaded && !theme.webURL ? ( + { ( !isEditMode ) && !downloaded && !theme.webURL || true ? ( <>
{ if (DarkMode) document.documentElement.classList.add('dark'); @@ -54,7 +53,6 @@ root.render( } /> } /> } /> - } /> diff --git a/src/interface/pages/Theme.tsx b/src/interface/pages/Theme.tsx deleted file mode 100644 index dc4dc0a3..00000000 --- a/src/interface/pages/Theme.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import { useEffect, useState } from "react"; -import PocketBase from 'pocketbase'; -import { ThemesRecord } from "../types/pocketbase-types"; -import ConfettiExplosion from 'react-confetti-explosion'; -import { LinkIcon } from "@heroicons/react/24/outline"; -import { ToastContainer, toast } from 'react-toastify'; -import browser from 'webextension-polyfill'; -import 'react-toastify/dist/ReactToastify.css'; -import localforage from "localforage"; - -const pb = new PocketBase('https://betterseqta.pockethost.io'); - -const Theme = () => { - const [isLoading, setIsLoading] = useState(true); - const [theme, setTheme] = useState(null); - const [themeID, setThemeID] = useState(''); - const [justCreated, setJustCreated] = useState(false); - const [displayConfetti, setDisplayConfetti] = useState(true); - const [currentThemes, setCurrentThemes] = useState([]); - - useEffect(() => { - const timer = setTimeout(() => { - setDisplayConfetti(false); - }, 5000); - return () => clearTimeout(timer); - }, []); - - useEffect(() => { - const urlParams = new URLSearchParams(window.location.search); - document.title = 'BetterSEQTA+' // Reset the title - const themeID = urlParams.get('id'); - const justCreated = urlParams.get('justCreated'); - if (themeID) setThemeID(themeID); - - const getTheme = async (themeID: string) => { - const theme = await pb.collection('themes').getOne(themeID); - console.debug(theme); - setIsLoading(false); - setTheme(theme); - document.title = theme.name; - - const availableThemes = await localforage.getItem('availableThemes') as string[]; - setCurrentThemes(availableThemes) - } - - if (themeID && themeID !== 'null') { - getTheme(themeID); - setJustCreated(justCreated === 'true'); - } - }, []) - - return ( - <> - { isLoading && ( -
-
-
- )} - { theme && ( -
-
- { justCreated ? ( - <> - { - displayConfetti && ( - - ) - } - <> -

Theme Created Successfully!

-

Share the install link below with your friends to install the theme!

-
- - {`https://share.betterseqta/theme?id=${themeID}`} - - - -
- - - ) : ( - <> -

{theme.name}

-

{theme.description}

- { - currentThemes.includes((theme.theme as { id: string }).id) ? - - : - - } - - )} -
- -
- )} - - ); -}; - -export default Theme; - diff --git a/src/seqta/ui/themes/shareTheme.ts b/src/seqta/ui/themes/shareTheme.ts index da707119..0d7b6454 100644 --- a/src/seqta/ui/themes/shareTheme.ts +++ b/src/seqta/ui/themes/shareTheme.ts @@ -1,7 +1,17 @@ -import PocketBase from 'pocketbase'; import { getTheme } from './getTheme'; -const pb = new PocketBase('https://betterseqta.pockethost.io'); +const saveThemeFile = (data: object, fileName: string) => { + const fileData = JSON.stringify(data, null, 2); + const blob = new Blob([fileData], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${fileName}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +}; const shareTheme = async (themeID: string) => { try { @@ -15,47 +25,43 @@ const shareTheme = async (themeID: string) => { // Extract images and coverImage from themeData, if they exist const { CustomImages = [], coverImage, ...themeWithoutImages } = themeData; - const finalCoverImage = await fetch(coverImage as string).then((res) => res.blob()); - let finalImages: { id: string, data: Blob }[] = []; - - for (const image of CustomImages) { - const finalImage = await fetch(image.url as string).then((res) => res.blob()); + // Helper function to convert Blob to Base64 + const blobToBase64 = (blob: Blob) => new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result as string); + reader.onerror = reject; + reader.readAsDataURL(blob); + }); - finalImages.push({ + // Convert cover image to Base64 + const coverImageBlob = await fetch(coverImage as string).then(res => res.blob()); + const coverImageBase64 = await blobToBase64(coverImageBlob); + + // Convert custom images to Base64 + const finalImages = await Promise.all(CustomImages.map(async (image) => { + const imageBlob = await fetch(image.url as string).then(res => res.blob()); + const imageBase64 = await blobToBase64(imageBlob); + return { id: image.id, - data: finalImage, - }); - } - + variableName: image.variableName, + data: imageBase64, + }; + })); // Prepare the non-file data for uploading const data = { - name: themeData.name || 'Unnamed Theme', - description: themeData.description || 'No description', - downloads: '0', // Assuming initial value as 0 - theme: JSON.stringify({ - ...themeWithoutImages, - images: [ - ...CustomImages.map((image) => ({ - id: image.id, - variableName: image.variableName, - })), - ], - }), // Convert theme data (excluding images) to JSON string - submitted: true, - coverImage: new File([finalCoverImage], 'coverImage.png'), - images: [ ...finalImages.map((image) => new File([image.data], `${image.id}.png`)) ], + ...themeWithoutImages, + images: finalImages.map((image) => ({ + id: image.id, + variableName: image.variableName, + data: image.data, + })), + coverImage: coverImageBase64, }; - const record = await pb.collection('themes').create(data); - - console.debug('record', record); - - return record.id; + saveThemeFile(data, themeData.name || 'Unnamed_Theme'); } catch (error) { console.error('Error sharing theme:', error); - - return null; } };