Skip to content

Commit

Permalink
upload util
Browse files Browse the repository at this point in the history
  • Loading branch information
ankushKun committed Jul 16, 2024
1 parent fab830d commit 6f1b9c8
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 0 deletions.
178 changes: 178 additions & 0 deletions next_app/src/components/menubar/components/upload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { useGlobalState, useProjectManager, useWallet } from "@/hooks";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import Arweave from "arweave";
import { useLocalStorage } from "usehooks-ts";
import { AppVersion, Tag } from "@/lib/ao-vars";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Loader } from "lucide-react";
import { GraphQLClient, gql } from "graphql-request";
import Link from "next/link";

type Transaction = {
id: string;
tags: Tag[];
}

export default function Upload() {
const wallet = useWallet()
const [popupOpen, setPopupOpen] = useState(false);
const [fileDragOver, setFileDragOver] = useState(false);
const [price, setPrice] = useState<string>();
const [file, setFile] = useState<File>();
const [uploading, setUploading] = useState(false);
const [history, setHistory] = useLocalStorage<Transaction[]>("upload-history", [], { initializeWithValue: true });

const ar = new Arweave({
host: 'arweave.net',
port: 443,
protocol: 'https',
});


async function upload() {
setUploading(true)
const txn = await ar.createTransaction({
data: new Uint8Array(await file?.arrayBuffer())
}, "use_wallet")
txn.addTag("Content-Type", file?.type || "application/octet-stream")
txn.addTag("App-Name", "BetterIDEa")
txn.addTag("App-Version", AppVersion)
txn.addTag("BetterIDEa-Function", "Upload-Utility")
txn.addTag("File-Name", file?.name || "unknown")
console.log(txn)
try {
await ar.transactions.sign(txn, "use_wallet")
console.log(txn)
await ar.transactions.post(txn)
} catch (e) {
console.error(e)
toast.error(e, { id: "error" })
} finally {
// setHistory([...history, id])
setUploading(false)
}
}

async function handleFileDrop(e: any) {
e.preventDefault();
setFileDragOver(false)
const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
if (files.length == 0) return toast.error("No files dropped", { id: "error" })
const file = files[0];
const reader = new FileReader();
reader.onload = async (e) => {
const bytes = new Uint8Array(e.target?.result as ArrayBuffer);
console.log(bytes)
const price = ar.ar.winstonToAr(await ar.transactions.getPrice(bytes.byteLength, wallet.address))
setPrice(price)
setFile(file)
}
reader.readAsArrayBuffer(file);
}

function handleFileDragOver(e: any) {
e.preventDefault();
setFileDragOver(true);
// console.log(e)
}

async function getUploadHistory() {
if (!wallet.isConnected) return
if (!wallet.address) return
const query = `
query {
transactions(
owners: ["${wallet.address}"],
tags: [
{
name: "App-Name",
values: ["BetterIDEa"]
},
{
name:"BetterIDEa-Function",
values:["Upload-Utility"]
},
#{
# name:"File-Name",
# values:"*"
#}
]
) {
edges {
node {
id,
tags{
name,
value
}
}
}
}
}
`
const client = new GraphQLClient("https://arweave.net/graphql")
const { transactions: { edges } } = await client.request(query) as any
console.log(edges)
setHistory(edges.map((e: any) => e.node))
}

useEffect(() => {
getUploadHistory()
}, [wallet.isConnected, wallet.address])

return (
<Dialog open={popupOpen} onOpenChange={(e) => { setPopupOpen(e) }}>
<DialogTrigger className="invisible" id="upload-file">
Upload File
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Upload a file to Arweave</DialogTitle>
<DialogDescription>
Uploading a file to Arweave will make it immutable and permanent. Drag and drop the file you want to upload.
</DialogDescription>
</DialogHeader>
<Tabs defaultValue="upload" className="w-full">
<TabsList className="w-full bg-muted/20 text-black">
<TabsTrigger value="upload" className="w-full data-[state=active]:bg-primary data-[state=active]:text-white">Upload</TabsTrigger>
<TabsTrigger value="history" className="w-full data-[state=active]:bg-primary data-[state=active]:text-white">History</TabsTrigger>
</TabsList>
<TabsContent value="upload">
<input id="upload-to-ar" type="file" accept="*" placeholder="Upload File" hidden onChange={handleFileDrop} />
<label htmlFor="upload-to-ar" className="text-center" onDragOver={handleFileDragOver} onDrop={handleFileDrop} onDragLeave={() => setFileDragOver(false)}>
<div data-draggedover={fileDragOver} className="flex flex-col border border-dashed data-[draggedover=true]:border-primary rounded-lg p-4 text-sm">
{file ? file.name : "Drag a file"}
{file && <Button variant="link" className="text-muted-foreground p-0 h-5 mt-1" onClick={(e) => {
e.preventDefault()
// reset input
setFile(null); setPrice(null);
}}>clear</Button>}
</div>
</label>
{price && <div className="text-left text-xs text-muted-foreground mt-1">Estimated cost: {price} AR</div>}
<Button disabled={uploading} onClick={() => upload()} className="mt-4">Upload {uploading && <Loader size={18} className="ml-2 animate-spin" />}</Button>
</TabsContent>
<TabsContent value="history" className="grid grid-cols-3 gap-y-2 items-center justify-center max-h-[300px] overflow-scroll">
{/* {
JSON.stringify(history, null, 2)
} */}
{
history.length > 0 && history.map((txn, _) => {
const fileName = txn.tags?.find((tag: Tag) => tag.name === "File-Name")?.value

return <>
{fileName || <span className="text-muted">unnamed</span>}
<Link href={`https://arweave.net/${txn.id}`} target="_blank" className="text-xs hover:underline col-span-2 truncate">{txn.id}</Link>
</>
})
}
</TabsContent>
</Tabs>
</DialogContent>
</Dialog>
);
}
12 changes: 12 additions & 0 deletions next_app/src/components/menubar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { toast } from "sonner"
import { GitHubLogoIcon, TwitterLogoIcon } from "@radix-ui/react-icons"
import Link from "next/link"
import Sponsor from "./components/sponsor"
import Upload from "./components/upload"

export default function Menubar() {
const globalState = useGlobalState()
Expand Down Expand Up @@ -82,6 +83,14 @@ export default function Menubar() {
<MenubarItem disabled={!project || !globalState.activeFile} onClick={() => globalState.closeOpenedFile(globalState.activeFile)}>Close File</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger className="rounded-none m-0">Utils</MenubarTrigger>
<MenubarContent sideOffset={1} alignOffset={0} className="rounded-b-md rounded-t-none bg-background">
{/* <MenubarLabel className="text-muted-foreground">Utilities</MenubarLabel> */}
{/* <MenubarSeparator /> */}
<MenubarItem onClick={() => document.getElementById("upload-file")?.click()}>Upload to Arweave</MenubarItem>
</MenubarContent>
</MenubarMenu>
<div className="grow"></div>
<MenubarMenu>
<MenubarTrigger className="rounded-none">More from us</MenubarTrigger>
Expand Down Expand Up @@ -128,6 +137,9 @@ export default function Menubar() {
<DeleteFile />
<DownloadFile />
<DuplicateFile />

<Upload/>

<Sponsor/>
</div>
}

0 comments on commit 6f1b9c8

Please sign in to comment.