screensnip-scribe / index.html
Homaste747's picture
Приложение для распознавания выделенной область на экране и автомотическго запись в текстовый файл. Приложение работает поверх других приложений
749cd9e verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ScreenSnip Scribe</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tesseract.js/4.1.1/tesseract.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.waves.min.js"></script>
<style>
.selection-box {
position: absolute;
border: 2px dashed rgba(59, 130, 246, 0.8);
background-color: rgba(59, 130, 246, 0.2);
pointer-events: none;
z-index: 9999;
}
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9998;
display: none;
}
</style>
</head>
<body class="bg-gray-900 text-gray-100 min-h-screen">
<div id="vanta-bg" class="fixed inset-0 z-0"></div>
<div class="relative z-10 container mx-auto px-4 py-12">
<header class="mb-12 text-center">
<h1 class="text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-600">ScreenSnip Scribe</h1>
<p class="text-xl text-gray-300 max-w-2xl mx-auto">Capture any screen area and automatically save the text to a file with this magical OCR tool ✨</p>
</header>
<main class="bg-gray-800 bg-opacity-70 backdrop-blur-lg rounded-xl p-8 max-w-3xl mx-auto shadow-2xl border border-gray-700">
<div class="flex flex-col items-center">
<div class="w-full mb-8">
<div class="flex items-center justify-center gap-4 mb-6">
<button id="startCaptureBtn" class="px-6 py-3 bg-blue-600 hover:bg-blue-700 rounded-lg font-medium flex items-center gap-2 transition-all transform hover:scale-105">
<i data-feather="crop"></i> Start Capture
</button>
<button id="saveBtn" disabled class="px-6 py-3 bg-purple-600 hover:bg-purple-700 rounded-lg font-medium flex items-center gap-2 transition-all opacity-70">
<i data-feather="save"></i> Save Text
</button>
</div>
<div class="bg-gray-900 rounded-lg p-4 min-h-40 max-h-96 overflow-y-auto">
<h3 class="text-lg font-medium mb-3 text-blue-400">Extracted Text:</h3>
<div id="extractedText" class="text-gray-300 whitespace-pre-wrap"></div>
</div>
</div>
<div class="w-full">
<div class="bg-gray-900 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-medium text-blue-400">Settings</h3>
<i data-feather="settings" class="text-gray-400"></i>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">Output Format</label>
<select id="outputFormat" class="w-full bg-gray-800 border border-gray-700 rounded-md px-3 py-2 text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="txt">Text File (.txt)</option>
<option value="doc">Word Document (.doc)</option>
<option value="pdf">PDF (.pdf)</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">Auto Save Location</label>
<div class="flex gap-2">
<input type="text" id="savePath" class="flex-1 bg-gray-800 border border-gray-700 rounded-md px-3 py-2 text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="C:/ScreenCaptures/" readonly>
<button id="changePathBtn" class="px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded-md text-sm font-medium transition-colors">
<i data-feather="folder"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<div id="overlay" class="overlay"></div>
<div id="selectionBox" class="selection-box"></div>
</div>
<script>
// Initialize Vanta.js background
VANTA.WAVES({
el: "#vanta-bg",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x1e3a8a,
shininess: 50.00,
waveHeight: 20.00,
waveSpeed: 0.50,
zoom: 0.75
});
// Initialize feather icons
feather.replace();
// App functionality
document.addEventListener('DOMContentLoaded', () => {
const startCaptureBtn = document.getElementById('startCaptureBtn');
const saveBtn = document.getElementById('saveBtn');
const extractedText = document.getElementById('extractedText');
const overlay = document.getElementById('overlay');
const selectionBox = document.getElementById('selectionBox');
const outputFormat = document.getElementById('outputFormat');
const savePath = document.getElementById('savePath');
const changePathBtn = document.getElementById('changePathBtn');
let isSelecting = false;
let startX, startY, endX, endY;
// Set default save path (electron would handle this differently)
savePath.value = "Documents/ScreenSnips/";
startCaptureBtn.addEventListener('click', () => {
isSelecting = true;
overlay.style.display = 'block';
document.body.style.cursor = 'crosshair';
startCaptureBtn.disabled = true;
startCaptureBtn.classList.add('opacity-70');
});
overlay.addEventListener('mousedown', (e) => {
if (!isSelecting) return;
startX = e.clientX;
startY = e.clientY;
selectionBox.style.left = startX + 'px';
selectionBox.style.top = startY + 'px';
selectionBox.style.width = '0';
selectionBox.style.height = '0';
selectionBox.style.display = 'block';
});
overlay.addEventListener('mousemove', (e) => {
if (!isSelecting || !startX) return;
endX = e.clientX;
endY = e.clientY;
selectionBox.style.left = Math.min(startX, endX) + 'px';
selectionBox.style.top = Math.min(startY, endY) + 'px';
selectionBox.style.width = Math.abs(endX - startX) + 'px';
selectionBox.style.height = Math.abs(endY - startY) + 'px';
});
overlay.addEventListener('mouseup', async () => {
if (!isSelecting || !startX) return;
isSelecting = false;
document.body.style.cursor = '';
// Hide overlay and selection box
overlay.style.display = 'none';
selectionBox.style.display = 'none';
// Get the selected area coordinates
const left = Math.min(startX, endX);
const top = Math.min(startY, endY);
const width = Math.abs(endX - startX);
const height = Math.abs(endY - startY);
// In a real Electron app, we would use the desktopCapturer API here
// For this demo, we'll simulate with html2canvas
try {
// Show loading state
extractedText.textContent = "Processing...";
// In a real app, we would capture the screen here
// For demo purposes, we'll just simulate with some sample text
setTimeout(() => {
// Simulate OCR processing
const sampleText = `Sample extracted text from screen area:
Left: ${left}px
Top: ${top}px
Width: ${width}px
Height: ${height}px
This is where the actual OCR text would appear. In a real app, this would be the text extracted from the selected screen area using Tesseract.js or similar OCR technology.
The text would then be saved to a file in the selected format (${outputFormat.value}) at the specified location.`;
extractedText.textContent = sampleText;
saveBtn.disabled = false;
saveBtn.classList.remove('opacity-70');
startCaptureBtn.disabled = false;
startCaptureBtn.classList.remove('opacity-70');
}, 1500);
} catch (error) {
console.error('Capture error:', error);
extractedText.textContent = "Error capturing screen area. Please try again.";
startCaptureBtn.disabled = false;
startCaptureBtn.classList.remove('opacity-70');
}
});
saveBtn.addEventListener('click', () => {
if (!extractedText.textContent.trim()) return;
// In a real Electron app, we would use the fs module here
// For demo, we'll just show a success message
saveBtn.disabled = true;
saveBtn.classList.add('opacity-70');
const format = outputFormat.value;
const path = savePath.value;
extractedText.textContent += `\n\nFile saved to: ${path}capture_${Date.now()}.${format}`;
setTimeout(() => {
saveBtn.disabled = false;
saveBtn.classList.remove('opacity-70');
}, 2000);
});
changePathBtn.addEventListener('click', () => {
// In a real Electron app, we would use dialog.showOpenDialog here
// For demo, we'll just show a simulated path change
savePath.value = "Documents/ScreenSnips/NewFolder/";
});
});
</script>
</body>
</html>