import clsx from "clsx"; import * as fs from "@tauri-apps/plugin-fs" import { useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { getPlatformInfo } from "@/lib/platform-utils"; import { CurrentExtension, LatestExtensionResponse, PlatformInfo } from "@/types"; import { ArrowLeft, ChevronsUpDown, CircleHelp, Loader2, RefreshCcw } from "lucide-react"; import { Link } from "react-router-dom"; import { downloadDir, tempDir, join } from "@tauri-apps/api/path"; import { compareVersions } from "@/lib/utils"; import { fetch } from '@tauri-apps/plugin-http'; import { Card } from "@/components/ui/card"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { download } from '@tauri-apps/plugin-upload'; import { Command } from "@tauri-apps/plugin-shell"; import { toast } from "sonner" import chromeLogo from "@/assets/images/chrome.png" import firefoxLogo from "@/assets/images/firefox.png" import edgeLogo from "@/assets/images/edge.png" import operaLogo from "@/assets/images/opera.png" import pytubeppLogo from "@/assets/images/pytubepp.png" export default function ExtensionManagerPage() { const [platformInfo, setPlatformInfo] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isUpdating, setIsUpdating] = useState(false); const [isCollapsibleOpen, setCollapsibleIsOpen] = useState(false) const [isAccordionOpen, setAccordionIsOpen] = useState(false) const [isExtensionInstalled, setIsExtensionInstalled] = useState(false); const [isExtensionUpdateAvailable, setIsExtensionUpdateAvailable] = useState(false); const [extensionUpdate, setExtensionUpdate] = useState(null) const [currentExtension, setCurrentExtension] = useState(null) const [updateStatus, setUpdateStatus] = useState(null) async function checkForUpdates() { setIsLoading(true); try { const downloadDirPath = await downloadDir() const extensionManifestPath = await join(downloadDirPath, "pytubepp-extension-chrome", "manifest.json") const extensionManifestExists = await fs.exists(extensionManifestPath) const response = await fetch('https://github.com/neosubhamoy/pytubepp-extension/releases/latest/download/latest.json', { method: 'GET', }); if (response.ok) { const data: LatestExtensionResponse = await response.json() setExtensionUpdate(data) if (extensionManifestExists) { setIsExtensionInstalled(true) const currentManifest = JSON.parse(await fs.readTextFile(extensionManifestPath)) setCurrentExtension(currentManifest) setIsExtensionUpdateAvailable(compareVersions(data.version, currentManifest.version) === 1) } else { setIsExtensionInstalled(false) setCurrentExtension(null) setIsExtensionUpdateAvailable(false) } } else { setIsExtensionUpdateAvailable(false) setExtensionUpdate(null) if (extensionManifestExists) { setIsExtensionInstalled(true) const currentManifest = JSON.parse(await fs.readTextFile(extensionManifestPath)) setCurrentExtension(currentManifest) } else { setIsExtensionInstalled(false) setCurrentExtension(null) } console.error('Failed to fetch latest extension version'); } } catch (error) { console.error(error); } finally { setIsLoading(false); } } const unpackExtension = async (extension: LatestExtensionResponse, operation: "unpack" | "update") => { setIsUpdating(true) try { setUpdateStatus('Preparing') const downloadDirPath = await downloadDir() const tempDirPath = await tempDir() const extensionDirPath = await join(downloadDirPath, "pytubepp-extension-chrome") const appTempDirPath = await join(tempDirPath, "com.neosubhamoy.pytubepp.helper") const tempExtensionDownloadPath = await join(appTempDirPath, `pytubepp-extension-chrome-v${extension.version}.zip`) const extensionDirExists = await fs.exists(extensionDirPath) const appTempDirExists = await fs.exists(appTempDirPath) if (!extensionDirExists) await fs.mkdir(extensionDirPath, { recursive: true}).then(() => console.log(`Created: ${extensionDirPath}`)) if (!appTempDirExists) await fs.mkdir(appTempDirPath, { recursive: true}).then(() => console.log(`Created: ${appTempDirPath}`)) setUpdateStatus('Downloading') await download( extension.browsers.chrome.url, tempExtensionDownloadPath, ({ progress, total }) => console.log(`Downloading: ${progress} of ${total} bytes`) ); setUpdateStatus('Unpacking') const output = await Command.sidecar('binaries/7zip', ['x', tempExtensionDownloadPath, `-o${extensionDirPath}`, '-aoa']).execute() if (output.code === 0) { console.log(output.stdout) console.log(`Unpacked ${tempExtensionDownloadPath} to ${extensionDirPath}`) } else { console.log(output.stdout, output.stderr) } setUpdateStatus('Cleaning') await fs.remove(tempExtensionDownloadPath) console.log(`Deleted: ${tempExtensionDownloadPath}`) setIsExtensionInstalled(true) setCurrentExtension({version: extension.version}) setIsExtensionUpdateAvailable(false) if (operation === "unpack") toast(`Successfully unpacked v${extension.version} to ${extensionDirPath}`) if (operation === "update") toast(`Successfully updated to v${extension.version}. Please reload the extension to reflect changes`) } catch (error) { if (operation === "unpack") toast(`Failed to unpack v${extension.version}`) if (operation === "update") toast(`Failed to update v${extension.version}`) console.error(error); } finally { setIsUpdating(false); setUpdateStatus(null) } } useEffect(() => { getPlatformInfo().then(setPlatformInfo).catch(console.error); checkForUpdates(); }, []) return (

Extension Manager

refresh

{ isLoading ? (

ckecking...

) : (
chrome pytubepp

PytubePP Extension (Chrome)

Unpacked: { currentExtension ? currentExtension.version : 'none' }   Latest: { extensionUpdate ? extensionUpdate.version : 'unknown' }

How to use unpacked extension

  • 1. Clicking on the 'Unpack' button unpacks latest pytubepp-extension for chrome within '~/Downloads/pytubepp-extension-chrome' folder
  • 2. You need to manually load the unpacked extension folder by visiting 'chrome://extensions' page
  • 3. If an update is available the 'Update' button will show up, Simply click on the button to update and don't forget to reload the extension by visiting 'chrome://extensions' page after updating
setAccordionIsOpen(!isAccordionOpen)}> Official Store Listings (Auto-Updates)
firefox

PytubePP Addon (Firefox)

Add pytubepp-addon to firefox

edge

PytubePP Extension (Edge)

Add pytubepp-extension to edge

opera

PytubePP Extension (Opera)

Add pytubepp-extension to opera

{ !isAccordionOpen && !isCollapsibleOpen && (
  • * Extension Manager helps you manage unpacked pytubepp-extension (installing and updating) as pytubepp-extension is not available on Chrome Web Store under Blue Zinc guidelines. (unpacked chrome extension works for all chromium based browsers)
) }
) }
) }