Skip to content

Commit

Permalink
feat: key file drag-and-drop (#7)
Browse files Browse the repository at this point in the history
This Pull Request implements keyfile drag-and-drop style of uploading
file. Comes with support for uploaded file type checking.

Closes #3 


[screencast-bpconcjcammlapcogcnnelfmaeghhagj-2024.03.08-22_19_41.webm](https://github.com/babblebey/private-key-converter/assets/25631971/2c95f461-8837-4dd0-a3cf-ae14d3396f35)
  • Loading branch information
babblebey authored Mar 8, 2024
1 parent 4a5bd32 commit 4236363
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 10 deletions.
2 changes: 2 additions & 0 deletions app/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Head from "@/components/Head";
import { Inter } from "next/font/google";
import { Header } from "@/components/Header";
import { Footer } from "@/components/Footer";
import { Dropbox } from "@/components/Dropbox";

const inter = Inter({ subsets: ["latin"] });

Expand All @@ -11,6 +12,7 @@ export default function RootLayout({ children }) {
<html lang="en" className={inter.className}>
<Head />
<body className="relative min-h-screen bg-black bg-gradient-to-tr from-zinc-900/50 to-zinc-700/30">
<Dropbox />
<Header />
<main className="min-h-[70vh] pb-5">
{ children }
Expand Down
67 changes: 57 additions & 10 deletions app/page.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useState, Fragment } from "react";
import { useState, Fragment, useEffect } from "react";
import { Title } from "@/components/Title";
import { Error } from "@/components/Error";
import { Success } from "@/components/Success";
Expand All @@ -19,18 +19,28 @@ const keyTypes = {
}
}

const supportedFileTypes = [
"pem",
"txt"
];

const initError = {
status: false,
message: ""
}

export default function Home() {
const [error, setError] = useState(false);
const [copied, setCopied] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(initError);

const [inputKey, setInputKey] = useState("");
const [outputKey, setOutputKey] = useState(null);
const [inputFormat, setInputFormat] = useState("pkcs1");
const [outputFormat, setOutputFormat] = useState("pkcs8");

async function handleSubmit() {
setError(false);
setError(initError);
setLoading(true);

const { key, error } = await convert_PKCS1_to_PKCS8(inputKey);
Expand All @@ -40,14 +50,20 @@ export default function Home() {
document.documentElement.scrollTop = 0;
};
if (error) {
setError(error);
document.querySelector("#error")?.scrollIntoView();
displayError("Conversion type not supported");
};

setLoading(false);
};

function handleFileUpload(file = document.querySelector("#keyfilePicker").files[0]) {
const fileExtension = file.name.split(".")[file.name.split(".").length - 1];
if (!supportedFileTypes.includes(fileExtension)) {
return displayError("File type upload not supported");
}

setError(initError);

const reader = new FileReader();
reader.onload = () => {
const contents = reader.result;
Expand All @@ -56,6 +72,40 @@ export default function Home() {
reader.readAsText(file);
}

function displayError(message) {
setError({status: true, message});
document.querySelector("#error")?.scrollIntoView();
}

function resetProcess() {
setInputKey("");
setOutputKey(null)
}

useEffect(() => {
const dropzone = document.querySelector("body");
const dropbox = dropzone.querySelector("#dropbox");

const stopDefault = (e) => {
e.stopPropagation();
e.preventDefault();
};

dropzone.ondragover = (e) => {
stopDefault(e);
dropbox.style.display = "flex";
};

dropzone.ondragenter = (e) => stopDefault(e);

dropzone.ondrop = (e) => {
stopDefault(e);
dropbox.style.display = "none";
if (inputKey || outputKey) resetProcess();
handleFileUpload(e.dataTransfer.files[0]);
}
}, []);

return (
<div className="container px-8 mx-auto mt-16 lg:mt-32">
{outputKey ? (
Expand Down Expand Up @@ -90,10 +140,7 @@ export default function Home() {
<button
type="button"
className="relative inline-flex items-center px-4 py-2 -ml-px space-x-2 text-sm font-medium duration-150 border rounded text-zinc-300 border-zinc-300/40 hover:border-zinc-300 focus:outline-none hover:text-white"
onClick={() => {
setInputKey("");
setOutputKey(null);
}}
onClick={() => resetProcess()}
>
Convert another
</button>
Expand Down Expand Up @@ -218,7 +265,7 @@ export default function Home() {
)}

<div id="error">
{error && <Error />}
{error.status && <Error message={error.message}/>}
</div>
</div>
)
Expand Down
12 changes: 12 additions & 0 deletions components/Dropbox.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { PlusIcon } from "@heroicons/react/24/outline";

export function Dropbox() {
return (
<div className="hidden items-center justify-center fixed top-0 z-40 w-full h-screen bg-black/70 backdrop-blur" id="dropbox">
<p className="flex items-center text-md md:text-xl text-white space-x-2">
<PlusIcon className="w-10 h-10" aria-hidden="true" />
<span>Drop key file here to upload</span>
</p>
</div>
);
};

0 comments on commit 4236363

Please sign in to comment.