Files
dewedev/src/pages/Base64Tool.js
dwindown e1bc8d193d Fix HTML Preview Tool critical bugs: PreviewFrame ref and click handler
- Fixed missing ref={previewFrameRef} on first PreviewFrame component (line 336)
  * This was causing 'PreviewFrame API not available' errors during save operations
  * Both fullscreen and normal mode PreviewFrame instances now have proper ref connection

- Fixed click handler attachment bug in setupInspectModeStyles function
  * Click handler was being skipped when styles were already injected
  * Now always attaches click handler when inspect mode is activated
  * Added proper cleanup to prevent duplicate event listeners

- Fixed variable scope issues in PreviewFrame.fresh.js
  * styleElement and cursorStyleElement now properly scoped for cleanup function
  * Added references to existing elements when styles already present

- Removed unused variables and fixed eslint warnings
  * Removed unused indentSize variable in BeautifierTool.js
  * Removed unused onSave and onDomUpdate props in PreviewFrame.fresh.js
  * Fixed unnecessary escape character in script tag

These fixes restore the Enhanced Option A DOM manipulation architecture:
- Inspector sidebar should now appear when clicking elements in inspect mode
- Save functionality should work without 'PreviewFrame ref not available' errors
- Live editing of element properties should work through PreviewFrame API
- Iframe refresh prevention during inspector operations maintained
2025-08-03 22:04:25 +07:00

185 lines
5.8 KiB
JavaScript

import React, { useState } from 'react';
import { Hash, Upload } from 'lucide-react';
import ToolLayout from '../components/ToolLayout';
import CopyButton from '../components/CopyButton';
const Base64Tool = () => {
const [input, setInput] = useState('');
const [output, setOutput] = useState('');
const [mode, setMode] = useState('encode'); // 'encode' or 'decode'
const encodeBase64 = () => {
try {
const encoded = btoa(unescape(encodeURIComponent(input)));
setOutput(encoded);
} catch (err) {
setOutput(`Error: ${err.message}`);
}
};
const decodeBase64 = () => {
try {
const decoded = decodeURIComponent(escape(atob(input)));
setOutput(decoded);
} catch (err) {
setOutput(`Error: Invalid Base64 string`);
}
};
const handleProcess = () => {
if (mode === 'encode') {
encodeBase64();
} else {
decodeBase64();
}
};
const handleFileUpload = (event) => {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
if (mode === 'encode') {
setInput(e.target.result);
} else {
// For decode mode, read as text
const textReader = new FileReader();
textReader.onload = (textEvent) => {
setInput(textEvent.target.result);
};
textReader.readAsText(file);
}
};
if (mode === 'encode') {
reader.readAsText(file);
} else {
reader.readAsText(file);
}
}
};
const clearAll = () => {
setInput('');
setOutput('');
};
const loadSample = () => {
if (mode === 'encode') {
setInput('Hello, World! This is a sample text for Base64 encoding.');
} else {
setInput('SGVsbG8sIFdvcmxkISBUaGlzIGlzIGEgc2FtcGxlIHRleHQgZm9yIEJhc2U2NCBlbmNvZGluZy4=');
}
};
return (
<ToolLayout
title="Base64 Encoder/Decoder"
description="Convert text to Base64 and back with support for files"
icon={Hash}
>
{/* Mode Toggle */}
<div className="flex bg-gray-100 dark:bg-gray-800 rounded-lg p-1 mb-6 w-fit">
<button
onClick={() => setMode('encode')}
className={`px-4 py-2 rounded-md font-medium transition-colors ${
mode === 'encode'
? 'bg-white dark:bg-gray-700 text-primary-600 shadow-sm'
: 'text-gray-600 dark:text-gray-400'
}`}
>
Encode
</button>
<button
onClick={() => setMode('decode')}
className={`px-4 py-2 rounded-md font-medium transition-colors ${
mode === 'decode'
? 'bg-white dark:bg-gray-700 text-primary-600 shadow-sm'
: 'text-gray-600 dark:text-gray-400'
}`}
>
Decode
</button>
</div>
{/* Controls */}
<div className="flex flex-wrap gap-3 mb-6">
<button onClick={handleProcess} className="tool-button">
{mode === 'encode' ? 'Encode to Base64' : 'Decode from Base64'}
</button>
<label className="tool-button-secondary cursor-pointer flex items-center space-x-2">
<Upload className="h-4 w-4" />
<span>Upload File</span>
<input
type="file"
onChange={handleFileUpload}
className="hidden"
accept=".txt,.json,.xml,.csv"
/>
</label>
<button onClick={loadSample} className="tool-button-secondary">
Load Sample
</button>
<button onClick={clearAll} className="tool-button-secondary">
Clear All
</button>
</div>
{/* Input/Output Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Input */}
<div className="space-y-2">
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
{mode === 'encode' ? 'Text to Encode' : 'Base64 to Decode'}
</label>
<div className="relative">
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder={
mode === 'encode'
? 'Enter text to encode to Base64...'
: 'Enter Base64 string to decode...'
}
className="tool-input h-96"
/>
</div>
</div>
{/* Output */}
<div className="space-y-2">
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
{mode === 'encode' ? 'Base64 Output' : 'Decoded Text'}
</label>
<div className="relative">
<textarea
value={output}
readOnly
placeholder={
mode === 'encode'
? 'Base64 encoded text will appear here...'
: 'Decoded text will appear here...'
}
className="tool-input h-96 bg-gray-50 dark:bg-gray-800"
/>
{output && <CopyButton text={output} />}
</div>
</div>
</div>
{/* Usage Tips */}
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-md p-4 mt-6">
<h4 className="text-blue-800 dark:text-blue-200 font-medium mb-2">Usage Tips</h4>
<ul className="text-blue-700 dark:text-blue-300 text-sm space-y-1">
<li> Base64 encoding is commonly used for data transmission and storage</li>
<li> Upload text files to encode/decode their contents</li>
<li> Encoded Base64 strings are safe for URLs and email transmission</li>
<li> Use the toggle to switch between encode and decode modes</li>
</ul>
</div>
</ToolLayout>
);
};
export default Base64Tool;