CipherStreamWeb converted to use Vite

This commit is contained in:
2025-08-13 23:31:29 -04:00
parent 70f9adb930
commit c9bddfa74d
120 changed files with 13931 additions and 3 deletions

View File

@@ -0,0 +1,25 @@
import { TertiaryButton, useToaster } from "mattrixwv-components";
export default function CopyOutputButton({
value
}:{
value: string;
}){
const { addSuccess } = useToaster();
const copyToClipboard = async () => {
await navigator.clipboard.writeText(value);
addSuccess("Output copied to clipboard", 5000);
}
return (
<TertiaryButton
onClick={() => void copyToClipboard()}
>
Copy Output
</TertiaryButton>
);
}

View File

@@ -0,0 +1,19 @@
import { ButtonSwitch } from "mattrixwv-components";
export default function EncodingDecodingButton({
encoding,
setEncoding
}:{
encoding: boolean,
setEncoding: (encoding: boolean) => void
}){
return (
<ButtonSwitch
checked={encoding}
onChange={setEncoding}
onNode={<div className="bg-blue-600 hover:bg-blue-700 active:bg-blue-800 rounded-lg px-4 py-2">Encoding</div>}
offNode={<div className="bg-green-600 hover:bg-green-700 active:bg-green-800 rounded-lg px-4 py-2">Decoding</div>}
/>
);
}

View File

@@ -0,0 +1,45 @@
import type { CipherInfo } from "@/models/CipherInfo";
import type { UseQueryResult } from "@tanstack/react-query";
import { DangerMessageBlock, RubberSpinner } from "mattrixwv-components";
import { CipherWrapper } from "./CipherWrapper";
export default function CipherLoader({
infoQuery,
children
}:{
infoQuery: UseQueryResult<CipherInfo, Error>;
children: React.ReactNode;
}){
return (
<>
{
infoQuery.isError &&
<div>
<DangerMessageBlock>
Error fetching cipher info.
</DangerMessageBlock>
</div>
}
{
infoQuery.isError &&
<div
className="w-32 h-32"
>
<RubberSpinner
className="stroke-blue-600"
trackClassName="fill-white/20"
/>
</div>
}
{
infoQuery.isSuccess &&
<CipherWrapper
cipherInfo={infoQuery.data}
>
{children}
</CipherWrapper>
}
</>
);
}

View File

@@ -0,0 +1,87 @@
import type { CipherInfo } from "@/models/CipherInfo";
export function CipherWrapper({
cipherInfo,
children
}:{
cipherInfo: CipherInfo;
children: React.ReactNode;
}){
return (
<div
className="flex flex-col items-center justify-center gap-y-16"
>
{/* Header */}
<div
className="flex flex-col items-center justify-center"
>
<h1
className="font-bold text-4xl"
>
{cipherInfo.name}
</h1>
<p
className="text-center"
>
{cipherInfo.description}
</p>
</div>
{/* Inputs */}
<div>
{children}
</div>
{/* Explanations */}
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<h3
className="text-2xl"
>
Explanation
</h3>
<div
className="flex flex-col items-center justify-center gap-y-2 w-full"
>
{
cipherInfo.explanation.map((line, index) => (
<p
key={index}
className="w-full text-justify"
>
{line}
</p>
))
}
</div>
<h3
className="text-2xl"
>
Facts
</h3>
<div
className="flex flex-col items-center justify-center gap-y-2 w-full"
>
{
cipherInfo.facts.map((fact, index) => (
<p
key={index}
className="w-full text-justify"
>
{fact}
</p>
))
}
{
cipherInfo.facts.length === 0 &&
<p
className="w-full text-justify"
>
No facts available.
</p>
}
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,142 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeADFGVX, useEncodeADFGVX } from "@/hooks/combination/ADFGVXHooks";
import { TextInput, useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function ADFGVXInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ squareKeyword, setSquareKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeADFGVXMutation = useEncodeADFGVX();
const decodeADFGVXMutation = useDecodeADFGVX();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeADFGVXMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
squareKeyword,
inputString: input
});
}
else{
decodeADFGVXMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
squareKeyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, squareKeyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeADFGVXMutation.isSuccess){
setOutput(decodeADFGVXMutation.data.outputString ?? "");
decodeADFGVXMutation.reset();
}
if(encodeADFGVXMutation.isSuccess){
setOutput(encodeADFGVXMutation.data.outputString ?? "");
encodeADFGVXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeADFGVXMutation.isSuccess, encodeADFGVXMutation.isSuccess, decodeADFGVXMutation.data, encodeADFGVXMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeADFGVXMutation.isError){
addDanger(decodeADFGVXMutation.error.message);
decodeADFGVXMutation.reset();
}
if(encodeADFGVXMutation.isError){
addDanger(encodeADFGVXMutation.error.message);
encodeADFGVXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeADFGVXMutation.isError, encodeADFGVXMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<TextInput
placeholder="Square Keyword"
value={squareKeyword}
onChange={(e) => setSquareKeyword(e.target.value)}
labelClassName="bg-(--bg-color) text-(--text-color)"
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,142 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeADFGX, useEncodeADFGX } from "@/hooks/combination/ADFGXHooks";
import { TextInput, useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function ADFGXInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ squareKeyword, setSquareKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeADFGXMutation = useEncodeADFGX();
const decodeADFGXMutation = useDecodeADFGX();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeADFGXMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
squareKeyword,
inputString: input
});
}
else{
decodeADFGXMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
squareKeyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, squareKeyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeADFGXMutation.isSuccess){
setOutput(decodeADFGXMutation.data.outputString ?? "");
decodeADFGXMutation.reset();
}
if(encodeADFGXMutation.isSuccess){
setOutput(encodeADFGXMutation.data.outputString ?? "");
encodeADFGXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeADFGXMutation.isSuccess, encodeADFGXMutation.isSuccess, decodeADFGXMutation.data, encodeADFGXMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeADFGXMutation.isError){
addDanger(decodeADFGXMutation.error.message);
decodeADFGXMutation.reset();
}
if(encodeADFGXMutation.isError){
addDanger(encodeADFGXMutation.error.message);
encodeADFGXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeADFGXMutation.isError, encodeADFGXMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<TextInput
value={squareKeyword}
onChange={(e) => setSquareKeyword(e.target.value)}
placeholder="Square Keyword"
labelClassName="bg-(--bg-color) text-(--text-color)"
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,150 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import NumberSelector from "@/components/input/NumberSelector";
import NumberSelectorArray from "@/components/input/NumberSelectorArray";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeAffine, useEncodeAffine } from "@/hooks/monosubstitution/AffineHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function AffineInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ key1, setKey1 ] = useState(1);
const [ key2, setKey2 ] = useState(0);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeAffineMutation = useEncodeAffine();
const decodeAffineMutation = useDecodeAffine();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeAffineMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
key1,
key2,
inputString: input
});
}
else{
decodeAffineMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
key1,
key2,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, key1, key2, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeAffineMutation.isSuccess){
setOutput(decodeAffineMutation.data.outputString ?? "");
decodeAffineMutation.reset();
}
if(encodeAffineMutation.isSuccess){
setOutput(encodeAffineMutation.data.outputString ?? "");
encodeAffineMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAffineMutation.isSuccess, encodeAffineMutation.isSuccess, decodeAffineMutation.data, encodeAffineMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeAffineMutation.isError){
addDanger(decodeAffineMutation.error.message);
decodeAffineMutation.reset();
}
if(encodeAffineMutation.isError){
addDanger(encodeAffineMutation.error.message);
encodeAffineMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAffineMutation.isError, encodeAffineMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelectorArray
label="Key 1"
value={key1}
shiftArray={[1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]}
onChange={setKey1}
/>
<NumberSelector
label="Key 2"
value={key2}
minValue={0}
maxValue={25}
onChange={setKey2}
/>
</div>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,125 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeAtbash, useEncodeAtbash } from "@/hooks/monosubstitution/AtbashHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function AtbashInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeAtbashMutation = useEncodeAtbash();
const decodeAtbashMutation = useDecodeAtbash();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeAtbashMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
inputString: input
});
}
else{
decodeAtbashMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeAtbashMutation.isSuccess){
setOutput(decodeAtbashMutation.data.outputString ?? "");
decodeAtbashMutation.reset();
}
if(encodeAtbashMutation.isSuccess){
setOutput(encodeAtbashMutation.data.outputString ?? "");
encodeAtbashMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAtbashMutation.isSuccess, encodeAtbashMutation.isSuccess, decodeAtbashMutation.data, encodeAtbashMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeAtbashMutation.isError){
addDanger(decodeAtbashMutation.error.message);
decodeAtbashMutation.reset();
}
if(encodeAtbashMutation.isError){
addDanger(encodeAtbashMutation.error.message);
encodeAtbashMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAtbashMutation, encodeAtbashMutation ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeAutokey, useEncodeAutokey } from "@/hooks/monosubstitution/AutokeyHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function AutokeyInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeAutokeyMutation = useEncodeAutokey();
const decodeAutokeyMutation = useDecodeAutokey();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeAutokeyMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeAutokeyMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, input, keyword, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeAutokeyMutation.isSuccess){
setOutput(decodeAutokeyMutation.data.outputString ?? "");
decodeAutokeyMutation.reset();
}
if(encodeAutokeyMutation.isSuccess){
setOutput(encodeAutokeyMutation.data.outputString ?? "");
encodeAutokeyMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAutokeyMutation.isSuccess, encodeAutokeyMutation.isSuccess, decodeAutokeyMutation.data, encodeAutokeyMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeAutokeyMutation.isError){
addDanger(decodeAutokeyMutation.error.message);
decodeAutokeyMutation.reset();
}
if(encodeAutokeyMutation.isError){
addDanger(encodeAutokeyMutation.error.message);
encodeAutokeyMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAutokeyMutation.isError, encodeAutokeyMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,115 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeBaconian, useEncodeBaconian } from "@/hooks/monosubstitution/BaconianHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function BaconianInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeBaconianMutation = useEncodeBaconian();
const decodeBaconianMutation = useDecodeBaconian();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeBaconianMutation.mutate({
encoding,
preserveCapitals: capitals,
inputString: input
});
}
else{
decodeBaconianMutation.mutate({
encoding,
preserveCapitals: capitals,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [ capitals, encoding, input, performCoding ]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeBaconianMutation.isSuccess){
setOutput(decodeBaconianMutation.data.outputString ?? "");
decodeBaconianMutation.reset();
}
if(encodeBaconianMutation.isSuccess){
setOutput(encodeBaconianMutation.data.outputString ?? "");
encodeBaconianMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBaconianMutation.isSuccess, encodeBaconianMutation.isSuccess, decodeBaconianMutation.data, encodeBaconianMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeBaconianMutation.isError){
addDanger(decodeBaconianMutation.error.message);
decodeBaconianMutation.reset();
}
if(encodeBaconianMutation.isError){
addDanger(encodeBaconianMutation.error.message);
encodeBaconianMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBaconianMutation.isError, encodeBaconianMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,118 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import NumberSelector from "@/components/input/NumberSelector";
import OutputMessage from "@/components/input/OutputMessage";
import { useDecodeBaseX, useEncodeBaseX } from "@/hooks/monosubstitution/BaseXHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function BaseXInputs(){
const [ encoding, setEncoding ] = useState(true);
const [ base, setBase ] = useState(2);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeBaseXMutation = useEncodeBaseX();
const decodeBaseXMutation = useDecodeBaseX();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeBaseXMutation.mutate({
encoding,
base,
inputString: input
});
}
else{
decodeBaseXMutation.mutate({
encoding,
base,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [base, encoding, input, performCoding]);
//When the mutations is successful set the new output
useEffect(() => {
if(decodeBaseXMutation.isSuccess){
setOutput(decodeBaseXMutation.data.outputString ?? "");
decodeBaseXMutation.reset();
}
if(encodeBaseXMutation.isSuccess){
setOutput(encodeBaseXMutation.data.outputString ?? "");
encodeBaseXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBaseXMutation.isSuccess, encodeBaseXMutation.isSuccess, decodeBaseXMutation.data, encodeBaseXMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeBaseXMutation.isError){
addDanger(decodeBaseXMutation.error.message);
decodeBaseXMutation.reset();
}
if(encodeBaseXMutation.isError){
addDanger(encodeBaseXMutation.error.message);
encodeBaseXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBaseXMutation.isError, encodeBaseXMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelector
label="Base"
value={base}
onChange={setBase}
minValue={2}
maxValue={36}
/>
</div>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeBeaufort, useEncodeBeaufort } from "@/hooks/monosubstitution/BeaufortHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function BeaufortInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeBeaufortMutation = useEncodeBeaufort();
const decodeBeaufortMutation = useDecodeBeaufort();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeBeaufortMutation.mutate({
encoding: encoding,
preserveCapitals: capitals,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
keyword: keyword,
inputString: input
});
}
else{
decodeBeaufortMutation.mutate({
encoding: encoding,
preserveCapitals: capitals,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
keyword: keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeBeaufortMutation.isSuccess){
setOutput(decodeBeaufortMutation.data.outputString ?? "");
decodeBeaufortMutation.reset();
}
if(encodeBeaufortMutation.isSuccess){
setOutput(encodeBeaufortMutation.data.outputString ?? "");
encodeBeaufortMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBeaufortMutation.isSuccess, encodeBeaufortMutation.isSuccess, decodeBeaufortMutation.data, encodeBeaufortMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeBeaufortMutation.isError){
addDanger(decodeBeaufortMutation.error.message);
decodeBeaufortMutation.reset();
}
if(encodeBeaufortMutation.isError){
addDanger(encodeBeaufortMutation.error.message);
encodeBeaufortMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBeaufortMutation.isError, encodeBeaufortMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,140 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import NumberSelector from "@/components/input/NumberSelector";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeCaesar, useEncodeCaesar } from "@/hooks/monosubstitution/CaesarHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function CaesarInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ shift, setShift ] = useState(0);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeCaesarMutation = useEncodeCaesar();
const decodeCaesarMutation = useDecodeCaesar();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeCaesarMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
shiftAmount: shift,
inputString: input
});
}
else{
decodeCaesarMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
shiftAmount: shift,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, input, performCoding, shift, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeCaesarMutation.isSuccess){
setOutput(decodeCaesarMutation.data.outputString ?? "");
decodeCaesarMutation.reset();
}
if(encodeCaesarMutation.isSuccess){
setOutput(encodeCaesarMutation.data.outputString ?? "");
encodeCaesarMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeCaesarMutation.isSuccess, encodeCaesarMutation.isSuccess, decodeCaesarMutation.data, encodeCaesarMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeCaesarMutation.isError){
addDanger(decodeCaesarMutation.error.message);
decodeCaesarMutation.reset();
}
if(encodeCaesarMutation.isError){
addDanger(encodeCaesarMutation.error.message);
encodeCaesarMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeCaesarMutation.isError, encodeCaesarMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelector
label="Shift"
value={shift}
minValue={0}
maxValue={25}
onChange={setShift}
/>
</div>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordArea from "@/components/input/KeywordArea";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeOneTimePad, useEncodeOneTimePad } from "@/hooks/monosubstitution/OneTimePadHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function OneTimePadInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeOneTimePadMutation = useEncodeOneTimePad();
const decodeOneTimePadMutation = useDecodeOneTimePad();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < input.length)){
setOutput("");
return;
}
if(encoding){
encodeOneTimePadMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeOneTimePadMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeOneTimePadMutation.isSuccess){
setOutput(decodeOneTimePadMutation.data.outputString ?? "");
decodeOneTimePadMutation.reset();
}
if(encodeOneTimePadMutation.isSuccess){
setOutput(encodeOneTimePadMutation.data.outputString ?? "");
encodeOneTimePadMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeOneTimePadMutation.isSuccess, encodeOneTimePadMutation.isSuccess, decodeOneTimePadMutation.data, encodeOneTimePadMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeOneTimePadMutation.isError){
addDanger(decodeOneTimePadMutation.error.message);
decodeOneTimePadMutation.reset();
}
if(encodeOneTimePadMutation.isError){
addDanger(encodeOneTimePadMutation.error.message);
encodeOneTimePadMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeOneTimePadMutation.isError, encodeOneTimePadMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordArea
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodePorta, useEncodePorta } from "@/hooks/monosubstitution/PortaHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function PortaInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodePortaMutation = useEncodePorta();
const decodePortaMutation = useDecodePorta();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodePortaMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodePortaMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodePortaMutation.isSuccess){
setOutput(decodePortaMutation.data.outputString ?? "");
decodePortaMutation.reset();
}
if(encodePortaMutation.isSuccess){
setOutput(encodePortaMutation.data.outputString ?? "");
encodePortaMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePortaMutation.isSuccess, encodePortaMutation.isSuccess, decodePortaMutation.data, encodePortaMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodePortaMutation.isError){
addDanger(decodePortaMutation.error.message);
decodePortaMutation.reset();
}
if(encodePortaMutation.isError){
addDanger(encodePortaMutation.error.message);
encodePortaMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePortaMutation.isError, encodePortaMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeSubstitution, useEncodeSubstitution } from "@/hooks/monosubstitution/SubstitutionHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function SubstitutionInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeSubstitutionMutation = useEncodeSubstitution();
const decodeSubstitutionMutation = useDecodeSubstitution();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || ((keyword.length !== 26) && (keyword.length !== 36))){
setOutput("");
return;
}
if(encoding){
encodeSubstitutionMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeSubstitutionMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeSubstitutionMutation.isSuccess){
setOutput(decodeSubstitutionMutation.data.outputString ?? "");
decodeSubstitutionMutation.reset();
}
if(encodeSubstitutionMutation.isSuccess){
setOutput(encodeSubstitutionMutation.data.outputString ?? "");
encodeSubstitutionMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeSubstitutionMutation.isSuccess, encodeSubstitutionMutation.isSuccess, decodeSubstitutionMutation.data, encodeSubstitutionMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeSubstitutionMutation.isError){
addDanger(decodeSubstitutionMutation.error.message);
decodeSubstitutionMutation.reset();
}
if(encodeSubstitutionMutation.isError){
addDanger(encodeSubstitutionMutation.error.message);
encodeSubstitutionMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeSubstitutionMutation.isError, encodeSubstitutionMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeVigenere, useEncodeVigenere } from "@/hooks/monosubstitution/VigenereHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function VigenereInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeVigenereMutation = useEncodeVigenere();
const decodeVigenereMutation = useDecodeVigenere();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeVigenereMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeVigenereMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeVigenereMutation.isSuccess){
setOutput(decodeVigenereMutation.data.outputString ?? "");
decodeVigenereMutation.reset();
}
if(encodeVigenereMutation.isSuccess){
setOutput(encodeVigenereMutation.data.outputString ?? "");
encodeVigenereMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeVigenereMutation.isSuccess, encodeVigenereMutation.isSuccess, decodeVigenereMutation.data, encodeVigenereMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeVigenereMutation.isError){
addDanger(decodeVigenereMutation.error.message);
decodeVigenereMutation.reset();
}
if(encodeVigenereMutation.isError){
addDanger(encodeVigenereMutation.error.message);
encodeVigenereMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeVigenereMutation.isError, encodeVigenereMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeBifid, useEncodeBifid } from "@/hooks/polysubstitution/BifidHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function BifidInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeBifidMutation = useEncodeBifid();
const decodeBifidMutation = useDecodeBifid();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeBifidMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeBifidMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeBifidMutation.isSuccess){
setOutput(decodeBifidMutation.data.outputString ?? "");
decodeBifidMutation.reset();
}
if(encodeBifidMutation.isSuccess){
setOutput(encodeBifidMutation.data.outputString ?? "");
encodeBifidMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBifidMutation.isSuccess, encodeBifidMutation.isSuccess, decodeBifidMutation.data, encodeBifidMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeBifidMutation.isError){
addDanger(decodeBifidMutation.error.message);
decodeBifidMutation.reset();
}
if(encodeBifidMutation.isError){
addDanger(encodeBifidMutation.error.message);
encodeBifidMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBifidMutation.isError, encodeBifidMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeColumnar, useEncodeColumnar } from "@/hooks/polysubstitution/ColumnarHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function ColumnarInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeColumnarMutation = useEncodeColumnar();
const decodeColumnarMutation = useDecodeColumnar();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeColumnarMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeColumnarMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeColumnarMutation.isSuccess){
setOutput(decodeColumnarMutation.data.outputString ?? "");
decodeColumnarMutation.reset();
}
if(encodeColumnarMutation.isSuccess){
setOutput(encodeColumnarMutation.data.outputString ?? "");
encodeColumnarMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeColumnarMutation.isSuccess, encodeColumnarMutation.isSuccess, decodeColumnarMutation.data, encodeColumnarMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeColumnarMutation.isError){
addDanger(decodeColumnarMutation.error.message);
decodeColumnarMutation.reset();
}
if(encodeColumnarMutation.isError){
addDanger(encodeColumnarMutation.error.message);
encodeColumnarMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeColumnarMutation.isError, encodeColumnarMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import SquareNumberArray from "@/components/input/SquareNumberArray";
import { useDecodeHill, useEncodeHill } from "@/hooks/polysubstitution/HillHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function HillInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ key, setKey ] = useState([[0, 0], [0, 0]]);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeHillMutation = useEncodeHill();
const decodeHillMutation = useDecodeHill();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeHillMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
key,
inputString: input
});
}
else{
decodeHillMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
key,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, key, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeHillMutation.isSuccess){
setOutput(decodeHillMutation.data.outputString ?? "");
decodeHillMutation.reset();
}
if(encodeHillMutation.isSuccess){
setOutput(encodeHillMutation.data.outputString ?? "");
encodeHillMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeHillMutation.isSuccess, encodeHillMutation.isSuccess, decodeHillMutation.data, encodeHillMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeHillMutation.isError){
addDanger(decodeHillMutation.error.message);
decodeHillMutation.reset();
}
if(encodeHillMutation.isError){
addDanger(encodeHillMutation.error.message);
encodeHillMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeHillMutation.isError, encodeHillMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<SquareNumberArray
value={key}
onChange={setKey}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,103 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import OutputMessage from "@/components/input/OutputMessage";
import { useDecodeMorse, useEncodeMorse } from "@/hooks/polysubstitution/MorseHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function MorseInputs(){
const [ encoding, setEncoding ] = useState(true);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeMorseMutation = useEncodeMorse();
const decodeMorseMutation = useDecodeMorse();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeMorseMutation.mutate({
encoding,
inputString: input
});
}
else{
decodeMorseMutation.mutate({
encoding,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [encoding, input, performCoding]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeMorseMutation.isSuccess){
setOutput(decodeMorseMutation.data.outputString ?? "");
decodeMorseMutation.reset();
}
if(encodeMorseMutation.isSuccess){
setOutput(encodeMorseMutation.data.outputString ?? "");
encodeMorseMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeMorseMutation.isSuccess, encodeMorseMutation.isSuccess, decodeMorseMutation.data, encodeMorseMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeMorseMutation.isError){
addDanger(decodeMorseMutation.error.message);
decodeMorseMutation.reset();
}
if(encodeMorseMutation.isError){
addDanger(encodeMorseMutation.error.message);
encodeMorseMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeMorseMutation.isError, encodeMorseMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodePlayfair, useEncodePlayfair } from "@/hooks/polysubstitution/PlayfairHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function PlayfairInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodePlayfairMutation = useEncodePlayfair();
const decodePlayfairMutation = useDecodePlayfair();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodePlayfairMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodePlayfairMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodePlayfairMutation.isSuccess){
setOutput(decodePlayfairMutation.data.outputString ?? "");
decodePlayfairMutation.reset();
}
if(encodePlayfairMutation.isSuccess){
setOutput(encodePlayfairMutation.data.outputString ?? "");
encodePlayfairMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePlayfairMutation.isSuccess, encodePlayfairMutation.isSuccess, decodePlayfairMutation.data, encodePlayfairMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodePlayfairMutation.isError){
addDanger(decodePlayfairMutation.error.message);
decodePlayfairMutation.reset();
}
if(encodePlayfairMutation.isError){
addDanger(encodePlayfairMutation.error.message);
encodePlayfairMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePlayfairMutation.isError, encodePlayfairMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,128 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodePolybius, useEncodePolybius } from "@/hooks/polysubstitution/PolybiusHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function PolybiusInputs(){
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodePolybiusMutation = useEncodePolybius();
const decodePolybiusMutation = useDecodePolybius();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodePolybiusMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
keyword,
inputString: input
});
}
else{
decodePolybiusMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodePolybiusMutation.isSuccess){
setOutput(decodePolybiusMutation.data.outputString ?? "");
decodePolybiusMutation.reset();
}
if(encodePolybiusMutation.isSuccess){
setOutput(encodePolybiusMutation.data.outputString ?? "");
encodePolybiusMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePolybiusMutation.isSuccess, encodePolybiusMutation.isSuccess, decodePolybiusMutation.data, encodePolybiusMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodePolybiusMutation.isError){
addDanger(decodePolybiusMutation.error.message);
decodePolybiusMutation.reset();
}
if(encodePolybiusMutation.isError){
addDanger(encodePolybiusMutation.error.message);
encodePolybiusMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePolybiusMutation.isError, encodePolybiusMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,140 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import NumberSelector from "@/components/input/NumberSelector";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeRailFence, useEncodeRailFence } from "@/hooks/polysubstitution/RailFenceHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function RaidFenceInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ rails, setRails ] = useState(2);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeRailFenceMutation = useEncodeRailFence();
const decodeRailFenceMutation = useDecodeRailFence();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeRailFenceMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
rails,
inputString: input
});
}
else{
decodeRailFenceMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
rails,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, rails, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeRailFenceMutation.isSuccess){
setOutput(decodeRailFenceMutation.data.outputString ?? "");
decodeRailFenceMutation.reset();
}
if(encodeRailFenceMutation.isSuccess){
setOutput(encodeRailFenceMutation.data.outputString ?? "");
encodeRailFenceMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeRailFenceMutation.isSuccess, encodeRailFenceMutation.isSuccess, decodeRailFenceMutation.data, encodeRailFenceMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeRailFenceMutation.isError){
addDanger(decodeRailFenceMutation.error.message);
decodeRailFenceMutation.reset();
}
if(encodeRailFenceMutation.isError){
addDanger(encodeRailFenceMutation.error.message);
encodeRailFenceMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeRailFenceMutation.isError, encodeRailFenceMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelector
label="Rails"
value={rails}
onChange={setRails}
minValue={2}
maxValue={100}
/>
</div>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,157 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import NumberSelector from "@/components/input/NumberSelector";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeTrifid, useEncodeTrifid } from "@/hooks/polysubstitution/TrifidHooks";
import { TextInput, useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function TrifidInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ fill, setFill ] = useState("#");
const [ groupLength, setGroupLength ] = useState(1);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeTrifidMutation = useEncodeTrifid();
const decodeTrifidMutation = useDecodeTrifid();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeTrifidMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
fill,
groupLength,
inputString: input
});
}
else{
decodeTrifidMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
fill,
groupLength,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, fill, groupLength, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeTrifidMutation.isSuccess){
setOutput(decodeTrifidMutation.data.outputString ?? "");
decodeTrifidMutation.reset();
}
if(encodeTrifidMutation.isSuccess){
setOutput(encodeTrifidMutation.data.outputString ?? "");
encodeTrifidMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeTrifidMutation.isSuccess, encodeTrifidMutation.isSuccess, decodeTrifidMutation.data, encodeTrifidMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeTrifidMutation.isError){
addDanger(decodeTrifidMutation.error.message);
decodeTrifidMutation.reset();
}
if(encodeTrifidMutation.isError){
addDanger(encodeTrifidMutation.error.message);
encodeTrifidMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeTrifidMutation.isError, encodeTrifidMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelector
label="Group Size"
value={groupLength}
onChange={setGroupLength}
minValue={1}
maxValue={100}
/>
</div>
<TextInput
placeholder="Fill"
value={fill}
onChange={(e) => { if(e.target.value.length <= 1){ setFill(e.target.value); } }}
labelClassName="bg-(--bg-color) text-(--text-color)"
/>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,24 @@
import { TextArea } from "mattrixwv-components";
export default function InputMessage({
value,
onChange
}:{
value: string;
onChange: (value: string) => void;
}){
return (
<div
className="w-160"
>
<TextArea
placeholder="Input Message"
value={value}
onChange={(e) => onChange(e.target.value)}
inputClassName="h-40 w-160 [resize:none]"
labelClassName="bg-(--bg-color) text-(--text-color) peer-focus:bg-(--bg-color) peer-focus:text-(--text-color)"
/>
</div>
);
}

View File

@@ -0,0 +1,23 @@
import { TextArea } from "mattrixwv-components";
export default function KeywordArea({
value,
onChange
}:{
value: string;
onChange: (value: string) => void;
}){
return (
<div
className="w-160"
>
<TextArea
placeholder="Keyword"
value={value}
onChange={(e) => onChange(e.target.value)}
inputClassName="h-40 w-160 [resize:none]"
labelClassName="bg-(--bg-color) text-(--text-color) peer-focus:bg-(--bg-color) peer-focus:text-(--text-color)"
/>
</div>
);
}

View File

@@ -0,0 +1,23 @@
import { TextInput } from "mattrixwv-components";
export default function KeywordInput({
value,
onChange
}:{
value: string;
onChange: (newValue: string) => void;
}){
return (
<div
className="w-160"
>
<TextInput
placeholder="Keyword"
value={value}
onChange={(e) => onChange(e.target.value)}
labelClassName="bg-(--bg-color) text-(--text-color) peer-focus:bg-(--bg-color) peer-focus:text-(--text-color)"
/>
</div>
);
}

View File

@@ -0,0 +1,31 @@
import { useMemo } from "react";
import NumberSelectorArray from "./NumberSelectorArray";
export default function NumberSelector({
value,
label,
minValue,
maxValue,
onChange
}:{
value: number;
label: string;
minValue: number;
maxValue: number;
onChange: (newShift: number) => void;
}){
const shiftArray: number[] = useMemo(() => (
Array.from({ length: maxValue - minValue + 1 }, (_, i) => i + minValue)
), [ minValue, maxValue ]);
//TODO: Perform a check for minValue <= value <= maxValue
return (
<NumberSelectorArray
value={value}
label={label}
shiftArray={shiftArray}
onChange={onChange}
/>
);
}

View File

@@ -0,0 +1,59 @@
import { PrimaryButton, SuccessButton } from "mattrixwv-components";
import { useCallback, useState } from "react";
import { BsChevronLeft, BsChevronRight } from "react-icons/bs";
export default function NumberSelectorArray({
label,
shiftArray,
value,
onChange
}:{
label: string;
shiftArray: number[];
value: number;
onChange: (value: number) => void;
}){
const [ arraySubscript, setArraySubscript ] = useState(shiftArray.indexOf(value) ?? 0);
//TODO: Check if the value exists
const decrementValue = useCallback(() => {
if(arraySubscript === 0){
setArraySubscript(shiftArray.length - 1);
onChange(shiftArray[shiftArray.length - 1]);
}
else{
setArraySubscript(arraySubscript - 1);
onChange(shiftArray[arraySubscript - 1]);
}
}, [arraySubscript, shiftArray, onChange]);
const incrementValue = useCallback(() => {
if(arraySubscript === shiftArray.length - 1){
setArraySubscript(0);
onChange(shiftArray[0]);
}
else{
setArraySubscript(arraySubscript + 1);
onChange(shiftArray[arraySubscript + 1]);
}
}, [arraySubscript, shiftArray, onChange]);
return (
<div
className="flex flex-col items-center justify-center text-2xl gap-y-2"
>
{/* Label */}
<div>{label}</div>
<div
className="flex flex-row items-center justify-center"
>
<SuccessButton size="sm" shape="square" onClick={decrementValue}><BsChevronLeft className="text-3xl text-white"/></SuccessButton>
<div className="w-16 text-center">{value}</div>
<PrimaryButton size="sm" shape="square" onClick={incrementValue}><BsChevronRight className="text-3xl text-white"/></PrimaryButton>
</div>
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { TextArea } from "mattrixwv-components";
export default function OutputMessage({
value,
onChange
}:{
value: string;
onChange: (value: string) => void;
}){
return (
<div
className="w-160"
>
<TextArea
placeholder="Output Message"
value={value}
onChange={(e) => onChange(e.target.value)}
inputClassName="h-40 w-160 [resize:none]"
labelClassName="bg-(--bg-color) text-(--text-color) peer-focus:bg-(--bg-color) peer-focus:text-(--text-color)"
disabled={true}
/>
</div>
);
}

View File

@@ -0,0 +1,59 @@
import { PrimarySwitch } from "mattrixwv-components";
export default function PreservationSliders({
capitals,
setCapitals,
symbols,
setSymbols,
whitespace,
setWhitespace
}:{
capitals?: boolean;
setCapitals?: (value: boolean) => void;
symbols?: boolean;
setSymbols?: (value: boolean) => void;
whitespace?: boolean;
setWhitespace?: (value: boolean) => void;
}){
return (
<>
{
setCapitals &&
<div className="flex flex-row items-center justify-center">
<PrimarySwitch
checked={capitals}
onChange={setCapitals}
size="md"
>
<div className="pl-2">Preserve Capitals</div>
</PrimarySwitch>
</div>
}
{
setSymbols &&
<div className="flex flex-row items-center justify-center">
<PrimarySwitch
checked={symbols}
onChange={setSymbols}
size="md"
>
<div className="pl-2">Preserve Symbols</div>
</PrimarySwitch>
</div>
}
{
setWhitespace &&
<div className="flex flex-row items-center justify-center">
<PrimarySwitch
checked={whitespace}
onChange={setWhitespace}
size="md"
>
<div className="pl-2">Preserve Whitespace</div>
</PrimarySwitch>
</div>
}
</>
);
}

View File

@@ -0,0 +1,92 @@
import clsx from "clsx";
import { PrimaryButton, SuccessButton } from "mattrixwv-components";
import { useCallback } from "react";
import { BsDashLg, BsPlusLg } from "react-icons/bs";
export default function SquareNumberArray({
value,
onChange
}:{
value: number[][];
onChange: (value: number[][]) => void;
}){
//TODO: Check for a square array
const decreaseArraySize = useCallback(() => {
if(value.length <= 2){
throw new Error("Cannot decrease grid size below 2");
}
const newValue = value.slice(0, -1);
newValue.forEach((row) => {
row.pop();
});
onChange(newValue);
}, [ onChange, value ]);
const increaseArraySize = useCallback(() => {
if(value.length >= 10){
throw new Error("Cannot increase grid size above 10");
}
const newValue = [...value];
newValue.forEach((row) => {
row.push(0);
});
newValue.push(new Array(value.length + 1).fill(0) as number[]);
onChange(newValue);
}, [ onChange, value ]);
const updateValue = useCallback((rowIndex: number, cellIndex: number, newCellValue: number) => {
const newValue = [...value];
newValue[rowIndex][cellIndex] = newCellValue;
onChange(newValue);
}, [ onChange, value ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<SuccessButton size="sm" shape="square" onClick={decreaseArraySize} disabled={value.length <= 2}><BsDashLg className="text-3xl text-white"/></SuccessButton>
<PrimaryButton size="sm" shape="square" onClick={increaseArraySize} disabled={value.length >= 10}><BsPlusLg className="text-3xl text-white"/></PrimaryButton>
</div>
<table>
<tbody>
{
value.map((row, rowIndex) => (
<tr
key={`squareNumberArrayRow${rowIndex}`}
className=""
>
{
row.map((cell, cellIndex) => (
<td
key={`squareNumberArrayCell${rowIndex}${cellIndex}`}
className="w-8 h-8 border"
>
<input
type="number"
className={clsx(
"text-center spinbox-hide text-xl w-12 h-10",
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
)}
value={cell}
onChange={(e) => updateValue(rowIndex, cellIndex, parseInt(e.target.value))}
/>
</td>
))
}
</tr>
))
}
</tbody>
</table>
</div>
);
}

View File

@@ -0,0 +1,53 @@
import { combinationLinks } from "@/util/LinksUtil";
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { Link } from "@tanstack/react-router";
import clsx from "clsx";
import { IoMdArrowDropdown } from "react-icons/io";
export default function CombinationLinks(){
return (
<Popover>
<PopoverButton
className={clsx(
"navBarLink outline-none",
"peer flex flex-row items-center justify-center"
)}
>
Combination
<IoMdArrowDropdown
className="mt-1"
size={22}
/>
</PopoverButton>
<PopoverPanel
anchor={{to: "top"}}
className={clsx(
"absolute z-50 w-(--button-width) rounded-lg py-2",
"flex flex-col items-start justify-center",
"bg-gray-600 dark:bg-neutral-700",
"shadow-md shadow-gray-950"
)}
>
<Link
className="w-full px-4 py-2 text-start"
to="/combination"
>
Overview
</Link>
<hr className="bg-neutral-500 h-0.5 w-full"/>
{
combinationLinks.map((link) => (
<Link
key={link.to}
className="w-full px-4 py-2 text-start"
to={link.to}
>
{link.label}
</Link>
))
}
</PopoverPanel>
</Popover>
);
}

View File

@@ -0,0 +1,36 @@
import { useTheme } from "@/providers/ThemeProvider";
import { BsLightbulb, BsLightbulbFill } from "react-icons/bs";
export default function DarkModeToggle(){
const { theme, setTheme } = useTheme();
return (
<div className="cursor-pointer">
<input
id="darkModeCheckbox"
type="checkbox"
className="peer hidden"
onChange={() => setTheme(theme === "dark" ? "light" : "dark")}
defaultChecked={theme === "dark"}
/>
<label
htmlFor="darkModeCheckbox"
className="block peer-checked:hidden cursor-pointer"
>
<BsLightbulbFill
size={20}
/>
</label>
<label
htmlFor="darkModeCheckbox"
className="hidden peer-checked:block cursor-pointer"
>
<BsLightbulb
size={20}
/>
</label>
</div>
);
}

View File

@@ -0,0 +1,53 @@
import { monosubstitutionLinks } from "@/util/LinksUtil";
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { Link } from "@tanstack/react-router";
import clsx from "clsx";
import { IoMdArrowDropdown } from "react-icons/io";
export default function MonoLinks(){
return (
<Popover>
<PopoverButton
className={clsx(
"navBarLink outline-none",
"peer flex flex-row items-center justify-center"
)}
>
Mono-Substitution
<IoMdArrowDropdown
className="mt-1"
size={22}
/>
</PopoverButton>
<PopoverPanel
anchor={{to: "top"}}
className={clsx(
"absolute z-50 w-(--button-width) rounded-lg py-1",
"flex flex-col items-start justify-center",
"bg-gray-600 dark:bg-neutral-700",
"shadow-md shadow-gray-950"
)}
>
<Link
className="w-full px-4 py-1 text-start"
to="/monosubstitution"
>
Overview
</Link>
<hr className="bg-neutral-500 h-0.5 my-1 w-full"/>
{
monosubstitutionLinks.map((link) => (
<Link
key={link.to}
className="w-full px-4 py-1 text-start"
to={link.to}
>
{link.label}
</Link>
))
}
</PopoverPanel>
</Popover>
);
}

View File

@@ -0,0 +1,69 @@
import cipherStreamIcon from "@/assets/cipherStreamIcon.svg";
import { PopoverGroup } from "@headlessui/react";
import { Link } from "@tanstack/react-router";
import clsx from "clsx";
import { BsList } from "react-icons/bs";
import CombinationLinks from "./CombinationLinks";
import DarkModeToggle from "./DarkModeToggle";
import MonoLinks from "./MonoLinks";
import PolyLinks from "./PolyLinks";
import TutorialLink from "./TutorialLink";
export default function NavBar(){
return (
<>
<nav
className={clsx(
"border-b-2 z-40",
"bg-gray-700 border-gray-600 text-white",
"dark:bg-zinc-900 dark:border-neutral-850"
)}
>
<div
className="navContents"
>
<Link
to="/"
className="flex items-center space-x-3 rtl:space-x-reverse"
>
<img
src={cipherStreamIcon}
alt="Cipher Stream Icon"
width={30}
height={30}
fetchPriority="high"
/>
<span
className="self-center text-2xl font-semibold whitespace-nowrap"
>
Cipher Stream
</span>
</Link>
<div
className="peer md:hidden text-3xl"
>
<BsList/>
</div>
<div
className={clsx(
"relative top-0 left-0 flex flex-row items-center rounded-lg gap-x-4",
"bg-gray-700 dark:bg-zinc-900"
)}
>
<PopoverGroup
className="flex flex-row items-center justify-center gap-x-4"
>
<MonoLinks/>
<PolyLinks/>
<CombinationLinks/>
</PopoverGroup>
<TutorialLink/>
<DarkModeToggle/>
</div>
</div>
<span className="bg-white"/>
</nav>
</>
);
}

View File

@@ -0,0 +1,53 @@
import { polysubstitutionLinks } from "@/util/LinksUtil";
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { Link } from "@tanstack/react-router";
import clsx from "clsx";
import { IoMdArrowDropdown } from "react-icons/io";
export default function PolyLinks(){
return (
<Popover>
<PopoverButton
className={clsx(
"navBarLink outline-none",
"peer flex flex-row items-center justify-center"
)}
>
Poly-Substitution
<IoMdArrowDropdown
className="mt-1"
size={22}
/>
</PopoverButton>
<PopoverPanel
anchor={{to: "top"}}
className={clsx(
"absolute z-50 w-(--button-width) rounded-lg py-1",
"flex flex-col items-start justify-center",
"bg-gray-600 dark:bg-neutral-700",
"shadow-md shadow-gray-950"
)}
>
<Link
className="w-full px-4 py-1 text-start"
to="/polysubstitution"
>
Overview
</Link>
<hr className="bg-neutral-500 h-0.5 my-1 w-full"/>
{
polysubstitutionLinks.map((link) => (
<Link
key={link.to}
className="w-full px-4 py-1 text-start"
to={link.to}
>
{link.label}
</Link>
))
}
</PopoverPanel>
</Popover>
);
}

View File

@@ -0,0 +1,30 @@
import { useTheme } from "@/providers/ThemeProvider";
import { Link } from "@tanstack/react-router";
import { BsQuestion } from "react-icons/bs";
import { Tooltip } from "react-tooltip";
export default function TutorialLink(){
const { theme } = useTheme();
return (
<>
<Link
id="tutorialLink"
to="/tutorial"
aria-label="Learn how to use Cipher Stream"
>
<BsQuestion
size={32}
/>
</Link>
<Tooltip
anchorSelect="#tutorialLink"
place="bottom-end"
variant={theme === "dark" ? "light" : "dark"}
>
Learn how to use Cipher Stream
</Tooltip>
</>
);
}

View File

@@ -0,0 +1,26 @@
import { useState } from "react";
import EncodingDecodingButton from "../button/EncodingDecodingButton";
export default function EncodingTutorial(){
const [ encoding, setEncoding ] = useState(true);
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Encoding/Decoding Button</h3>
<p>
Click this button to toggle between the input being encoded or decoded.
</p>
<div
className="mt-4">
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { useState } from "react";
import InputMessage from "../input/InputMessage";
export default function InputTutorial(){
const [ inputValue, setInputValue ] = useState("");
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Input</h3>
<p>
Enter text here to be encoded or decoded, depending on the Coding Button selection.
</p>
<div className="mt-4">
<InputMessage
value={inputValue}
onChange={setInputValue}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { useState } from "react";
import KeywordInput from "../input/KeywordInput";
export default function KeywordTutorial(){
const [ keyword, setKeyword ] = useState("");
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Keyword</h3>
<p>
Enter a keyword used in the encryption.
</p>
<div className="mt-4">
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,26 @@
import { useState } from "react";
import NumberSelector from "../input/NumberSelector";
export default function NumberSelectorTutorial(){
const [ value, setValue ] = useState(0);
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Number Selector</h3>
<p>
Click the up and down arrows to select a number as a key.
</p>
<NumberSelector
label=""
value={value}
onChange={setValue}
minValue={0}
maxValue={100}
/>
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { useState } from "react";
import OutputMessage from "../input/OutputMessage";
export default function OutputTutorial(){
const [ outputValue, setOutputValue ] = useState("");
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Output</h3>
<p>
This is where the result of the encoding or decoding of the message will appear.
</p>
<div className="mt-4">
<OutputMessage
value={outputValue}
onChange={setOutputValue}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,22 @@
import { PrimarySwitch } from "mattrixwv-components";
export default function SwitchTutorial(){
return (
<div
className="flex flex-col justify-center items-center"
>
<h3 className="text-center text-2xl">Preserve Element Switch</h3>
<p>
These switches indicate what types of elements in the inputs message will be preserved through the coding process.
<br/>
They are normally listed as Capitals, Symbols (punctuation and other special characters), and Whitespace.
<br/>
Remember: The more elements you leave in the cipher text the easier it will be to crack!
</p>
<div className="flex flex-row items-center justify-center mt-4">
<PrimarySwitch defaultChecked={true} size="md"><div className="pl-2">Preserve Element</div></PrimarySwitch>
</div>
</div>
);
}