Ultronprime commited on
Commit
b974798
·
verified ·
1 Parent(s): 23bce6a

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +495 -19
  3. prompts.txt +1 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Snapitraph
3
- emoji: 🚀
4
- colorFrom: blue
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: snapitraph
3
+ emoji: 🐳
4
+ colorFrom: purple
5
+ colorTo: green
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,495 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>QuickSnap - Fast Photo Capture</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .camera-container {
11
+ position: relative;
12
+ overflow: hidden;
13
+ border-radius: 1rem;
14
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
15
+ }
16
+ .camera-view {
17
+ width: 100%;
18
+ height: 100%;
19
+ object-fit: cover;
20
+ transform: scaleX(-1);
21
+ }
22
+ .flash {
23
+ position: absolute;
24
+ top: 0;
25
+ left: 0;
26
+ width: 100%;
27
+ height: 100%;
28
+ background-color: white;
29
+ opacity: 0;
30
+ pointer-events: none;
31
+ transition: opacity 0.3s;
32
+ }
33
+ .flash.active {
34
+ opacity: 0.8;
35
+ }
36
+ .category-chip {
37
+ transition: all 0.2s;
38
+ }
39
+ .category-chip:hover {
40
+ transform: scale(1.05);
41
+ }
42
+ .category-chip.active {
43
+ background-color: #3b82f6;
44
+ color: white;
45
+ }
46
+ .snap-btn {
47
+ transition: all 0.2s;
48
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
49
+ }
50
+ .snap-btn:active {
51
+ transform: scale(0.95);
52
+ }
53
+ .photo-thumbnail {
54
+ transition: all 0.2s;
55
+ }
56
+ .photo-thumbnail:hover {
57
+ transform: scale(1.03);
58
+ }
59
+ .modal {
60
+ transition: opacity 0.3s, visibility 0.3s;
61
+ }
62
+ .drawer {
63
+ transition: transform 0.3s;
64
+ }
65
+ .drawer.closed {
66
+ transform: translateX(100%);
67
+ }
68
+ </style>
69
+ </head>
70
+ <body class="bg-gray-100 min-h-screen">
71
+ <div class="container mx-auto px-4 py-8">
72
+ <!-- Header -->
73
+ <header class="flex justify-between items-center mb-8">
74
+ <h1 class="text-3xl font-bold text-blue-600">QuickSnap</h1>
75
+ <button id="settings-btn" class="p-2 rounded-full hover:bg-gray-200">
76
+ <i class="fas fa-cog text-gray-600 text-xl"></i>
77
+ </button>
78
+ </header>
79
+
80
+ <!-- Main Content -->
81
+ <main>
82
+ <!-- Camera Section -->
83
+ <div class="mb-8">
84
+ <div class="camera-container bg-gray-200 aspect-video relative mb-4">
85
+ <video id="camera-view" class="camera-view" autoplay playsinline></video>
86
+ <div id="flash" class="flash"></div>
87
+ </div>
88
+
89
+ <div class="flex justify-center">
90
+ <button id="snap-btn" class="snap-btn bg-blue-600 text-white rounded-full p-4 hover:bg-blue-700 focus:outline-none">
91
+ <i class="fas fa-camera text-2xl"></i>
92
+ </button>
93
+ </div>
94
+ </div>
95
+
96
+ <!-- Categories Section -->
97
+ <div class="mb-8">
98
+ <div class="flex justify-between items-center mb-4">
99
+ <h2 class="text-xl font-semibold text-gray-800">Categories</h2>
100
+ <button id="add-category-btn" class="text-blue-600 hover:text-blue-800">
101
+ <i class="fas fa-plus mr-1"></i> Add
102
+ </button>
103
+ </div>
104
+
105
+ <div id="categories-container" class="flex flex-wrap gap-2">
106
+ <!-- Categories will be added here dynamically -->
107
+ </div>
108
+ </div>
109
+
110
+ <!-- Gallery Section -->
111
+ <div>
112
+ <h2 class="text-xl font-semibold text-gray-800 mb-4">Your Snaps</h2>
113
+ <div id="gallery-container" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
114
+ <!-- Photos will be added here dynamically -->
115
+ </div>
116
+ </div>
117
+ </main>
118
+
119
+ <!-- Add Category Modal -->
120
+ <div id="add-category-modal" class="modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center opacity-0 invisible z-50">
121
+ <div class="bg-white rounded-lg p-6 w-full max-w-md">
122
+ <div class="flex justify-between items-center mb-4">
123
+ <h3 class="text-xl font-semibold">Add New Category</h3>
124
+ <button id="close-category-modal" class="text-gray-500 hover:text-gray-700">
125
+ <i class="fas fa-times"></i>
126
+ </button>
127
+ </div>
128
+ <input id="category-name-input" type="text" placeholder="Category name" class="w-full px-4 py-2 border rounded-lg mb-4 focus:outline-none focus:ring-2 focus:ring-blue-500">
129
+ <div class="flex justify-end space-x-2">
130
+ <button id="cancel-category-btn" class="px-4 py-2 border rounded-lg hover:bg-gray-100">Cancel</button>
131
+ <button id="save-category-btn" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">Save</button>
132
+ </div>
133
+ </div>
134
+ </div>
135
+
136
+ <!-- Settings Drawer -->
137
+ <div id="settings-drawer" class="drawer fixed top-0 right-0 h-full w-64 bg-white shadow-lg z-50 p-4 transform translate-x-full">
138
+ <div class="flex justify-between items-center mb-6">
139
+ <h3 class="text-xl font-semibold">Settings</h3>
140
+ <button id="close-settings-btn" class="text-gray-500 hover:text-gray-700">
141
+ <i class="fas fa-times"></i>
142
+ </button>
143
+ </div>
144
+ <div class="space-y-4">
145
+ <div>
146
+ <label class="block text-gray-700 mb-2">Flash</label>
147
+ <select id="flash-setting" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
148
+ <option value="auto">Auto</option>
149
+ <option value="on">On</option>
150
+ <option value="off">Off</option>
151
+ </select>
152
+ </div>
153
+ <div>
154
+ <label class="block text-gray-700 mb-2">Camera</label>
155
+ <select id="camera-setting" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
156
+ <!-- Camera options will be added dynamically -->
157
+ </select>
158
+ </div>
159
+ <div>
160
+ <button id="clear-storage-btn" class="w-full px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700">
161
+ Clear All Data
162
+ </button>
163
+ </div>
164
+ </div>
165
+ </div>
166
+ </div>
167
+
168
+ <script>
169
+ document.addEventListener('DOMContentLoaded', function() {
170
+ // DOM Elements
171
+ const cameraView = document.getElementById('camera-view');
172
+ const snapBtn = document.getElementById('snap-btn');
173
+ const flash = document.getElementById('flash');
174
+ const categoriesContainer = document.getElementById('categories-container');
175
+ const galleryContainer = document.getElementById('gallery-container');
176
+ const addCategoryBtn = document.getElementById('add-category-btn');
177
+ const addCategoryModal = document.getElementById('add-category-modal');
178
+ const closeCategoryModal = document.getElementById('close-category-modal');
179
+ const cancelCategoryBtn = document.getElementById('cancel-category-btn');
180
+ const saveCategoryBtn = document.getElementById('save-category-btn');
181
+ const categoryNameInput = document.getElementById('category-name-input');
182
+ const settingsBtn = document.getElementById('settings-btn');
183
+ const settingsDrawer = document.getElementById('settings-drawer');
184
+ const closeSettingsBtn = document.getElementById('close-settings-btn');
185
+ const flashSetting = document.getElementById('flash-setting');
186
+ const cameraSetting = document.getElementById('camera-setting');
187
+ const clearStorageBtn = document.getElementById('clear-storage-btn');
188
+
189
+ // App State
190
+ let currentCategory = 'default';
191
+ let mediaStream = null;
192
+ let cameras = [];
193
+ let selectedCameraId = null;
194
+
195
+ // Initialize the app
196
+ initApp();
197
+
198
+ // Functions
199
+ async function initApp() {
200
+ // Load categories and photos from localStorage
201
+ loadCategories();
202
+ loadPhotos();
203
+
204
+ // Initialize camera
205
+ await initCamera();
206
+
207
+ // Set up event listeners
208
+ setupEventListeners();
209
+ }
210
+
211
+ async function initCamera() {
212
+ try {
213
+ // Stop any existing stream
214
+ if (mediaStream) {
215
+ mediaStream.getTracks().forEach(track => track.stop());
216
+ }
217
+
218
+ // Get available cameras
219
+ const devices = await navigator.mediaDevices.enumerateDevices();
220
+ cameras = devices.filter(device => device.kind === 'videoinput');
221
+
222
+ // Update camera selector
223
+ updateCameraSelector();
224
+
225
+ // Start with default camera (or the one saved in settings)
226
+ const savedCameraId = localStorage.getItem('selectedCameraId');
227
+ const cameraId = savedCameraId || (cameras.length > 0 ? cameras[0].deviceId : null);
228
+
229
+ if (cameraId) {
230
+ await startCamera(cameraId);
231
+ selectedCameraId = cameraId;
232
+ cameraSetting.value = cameraId;
233
+ }
234
+ } catch (error) {
235
+ console.error('Error initializing camera:', error);
236
+ alert('Could not access the camera. Please make sure you have granted camera permissions.');
237
+ }
238
+ }
239
+
240
+ async function startCamera(deviceId) {
241
+ const constraints = {
242
+ video: {
243
+ deviceId: { exact: deviceId },
244
+ width: { ideal: 1280 },
245
+ height: { ideal: 720 },
246
+ facingMode: 'environment'
247
+ }
248
+ };
249
+
250
+ try {
251
+ mediaStream = await navigator.mediaDevices.getUserMedia(constraints);
252
+ cameraView.srcObject = mediaStream;
253
+ } catch (error) {
254
+ console.error('Error starting camera:', error);
255
+ // Fallback to any camera if the selected one fails
256
+ if (deviceId !== cameras[0]?.deviceId) {
257
+ await startCamera(cameras[0]?.deviceId);
258
+ }
259
+ }
260
+ }
261
+
262
+ function updateCameraSelector() {
263
+ cameraSetting.innerHTML = '';
264
+ cameras.forEach(camera => {
265
+ const option = document.createElement('option');
266
+ option.value = camera.deviceId;
267
+ option.text = camera.label || `Camera ${cameraSetting.options.length + 1}`;
268
+ cameraSetting.appendChild(option);
269
+ });
270
+ }
271
+
272
+ function loadCategories() {
273
+ // Load categories from localStorage
274
+ const categories = JSON.parse(localStorage.getItem('categories')) || ['default', 'work', 'personal'];
275
+
276
+ // Clear existing categories
277
+ categoriesContainer.innerHTML = '';
278
+
279
+ // Add each category
280
+ categories.forEach(category => {
281
+ addCategoryToUI(category);
282
+ });
283
+
284
+ // Set the first category as active
285
+ if (categories.length > 0) {
286
+ setActiveCategory(categories[0]);
287
+ }
288
+ }
289
+
290
+ function addCategoryToUI(category) {
291
+ const categoryElement = document.createElement('div');
292
+ categoryElement.className = `category-chip px-4 py-2 bg-gray-200 rounded-full cursor-pointer ${currentCategory === category ? 'active' : ''}`;
293
+ categoryElement.textContent = category;
294
+ categoryElement.dataset.category = category;
295
+
296
+ categoryElement.addEventListener('click', () => {
297
+ setActiveCategory(category);
298
+ });
299
+
300
+ categoriesContainer.appendChild(categoryElement);
301
+ }
302
+
303
+ function setActiveCategory(category) {
304
+ // Update active state in UI
305
+ document.querySelectorAll('.category-chip').forEach(chip => {
306
+ chip.classList.toggle('active', chip.dataset.category === category);
307
+ });
308
+
309
+ // Update current category
310
+ currentCategory = category;
311
+
312
+ // Reload photos for this category
313
+ loadPhotos();
314
+ }
315
+
316
+ function loadPhotos() {
317
+ // Load photos from localStorage for the current category
318
+ const allPhotos = JSON.parse(localStorage.getItem('photos')) || {};
319
+ const categoryPhotos = allPhotos[currentCategory] || [];
320
+
321
+ // Clear gallery
322
+ galleryContainer.innerHTML = '';
323
+
324
+ // Add each photo to the gallery
325
+ categoryPhotos.forEach((photoData, index) => {
326
+ addPhotoToGallery(photoData, index);
327
+ });
328
+ }
329
+
330
+ function addPhotoToGallery(photoData, index) {
331
+ const photoElement = document.createElement('div');
332
+ photoElement.className = 'photo-thumbnail bg-white rounded-lg overflow-hidden shadow-md hover:shadow-lg';
333
+
334
+ const img = document.createElement('img');
335
+ img.src = photoData.image;
336
+ img.alt = `Snap ${index + 1}`;
337
+ img.className = 'w-full h-32 object-cover';
338
+
339
+ const footer = document.createElement('div');
340
+ footer.className = 'p-2 text-sm text-gray-700 truncate';
341
+ footer.textContent = new Date(photoData.timestamp).toLocaleString();
342
+
343
+ photoElement.appendChild(img);
344
+ photoElement.appendChild(footer);
345
+
346
+ galleryContainer.appendChild(photoElement);
347
+ }
348
+
349
+ function takeSnapshot() {
350
+ // Create canvas to capture the photo
351
+ const canvas = document.createElement('canvas');
352
+ canvas.width = cameraView.videoWidth;
353
+ canvas.height = cameraView.videoHeight;
354
+ const ctx = canvas.getContext('2d');
355
+
356
+ // Draw the current frame to canvas
357
+ ctx.drawImage(cameraView, 0, 0, canvas.width, canvas.height);
358
+
359
+ // Get the image data
360
+ const imageData = canvas.toDataURL('image/png');
361
+
362
+ // Create photo object
363
+ const photo = {
364
+ image: imageData,
365
+ category: currentCategory,
366
+ timestamp: Date.now()
367
+ };
368
+
369
+ // Save to localStorage
370
+ savePhoto(photo);
371
+
372
+ // Add to gallery
373
+ addPhotoToGallery(photo, galleryContainer.children.length);
374
+
375
+ // Flash effect
376
+ if (flashSetting.value !== 'off') {
377
+ flash.classList.add('active');
378
+ setTimeout(() => {
379
+ flash.classList.remove('active');
380
+ }, 200);
381
+ }
382
+ }
383
+
384
+ function savePhoto(photo) {
385
+ // Load existing photos
386
+ const allPhotos = JSON.parse(localStorage.getItem('photos')) || {};
387
+
388
+ // Initialize category if it doesn't exist
389
+ if (!allPhotos[photo.category]) {
390
+ allPhotos[photo.category] = [];
391
+ }
392
+
393
+ // Add the new photo
394
+ allPhotos[photo.category].unshift(photo); // Add to beginning of array
395
+
396
+ // Save back to localStorage
397
+ localStorage.setItem('photos', JSON.stringify(allPhotos));
398
+ }
399
+
400
+ function addNewCategory(name) {
401
+ // Validate name
402
+ if (!name.trim()) {
403
+ alert('Please enter a category name');
404
+ return;
405
+ }
406
+
407
+ // Load existing categories
408
+ const categories = JSON.parse(localStorage.getItem('categories')) || ['default', 'work', 'personal'];
409
+
410
+ // Check if category already exists
411
+ if (categories.includes(name)) {
412
+ alert('This category already exists');
413
+ return;
414
+ }
415
+
416
+ // Add new category
417
+ categories.push(name);
418
+
419
+ // Save to localStorage
420
+ localStorage.setItem('categories', JSON.stringify(categories));
421
+
422
+ // Add to UI
423
+ addCategoryToUI(name);
424
+
425
+ // Close modal and clear input
426
+ toggleModal(addCategoryModal, false);
427
+ categoryNameInput.value = '';
428
+ }
429
+
430
+ function clearAllData() {
431
+ if (confirm('Are you sure you want to clear all photos and categories? This cannot be undone.')) {
432
+ localStorage.removeItem('photos');
433
+ localStorage.removeItem('categories');
434
+ localStorage.removeItem('selectedCameraId');
435
+ loadCategories();
436
+ loadPhotos();
437
+ toggleModal(settingsDrawer, false);
438
+ }
439
+ }
440
+
441
+ function toggleModal(modal, show) {
442
+ if (show) {
443
+ modal.classList.remove('invisible', 'opacity-0');
444
+ if (modal === settingsDrawer) {
445
+ modal.classList.remove('closed');
446
+ }
447
+ } else {
448
+ modal.classList.add('invisible', 'opacity-0');
449
+ if (modal === settingsDrawer) {
450
+ modal.classList.add('closed');
451
+ }
452
+ }
453
+ }
454
+
455
+ function setupEventListeners() {
456
+ // Snap button
457
+ snapBtn.addEventListener('click', takeSnapshot);
458
+
459
+ // Add category
460
+ addCategoryBtn.addEventListener('click', () => toggleModal(addCategoryModal, true));
461
+ closeCategoryModal.addEventListener('click', () => toggleModal(addCategoryModal, false));
462
+ cancelCategoryBtn.addEventListener('click', () => toggleModal(addCategoryModal, false));
463
+ saveCategoryBtn.addEventListener('click', () => addNewCategory(categoryNameInput.value));
464
+
465
+ // Settings
466
+ settingsBtn.addEventListener('click', () => toggleModal(settingsDrawer, true));
467
+ closeSettingsBtn.addEventListener('click', () => toggleModal(settingsDrawer, false));
468
+
469
+ // Flash setting
470
+ flashSetting.addEventListener('change', () => {
471
+ // Save preference (though we don't need to save to localStorage for this demo)
472
+ });
473
+
474
+ // Camera setting
475
+ cameraSetting.addEventListener('change', async () => {
476
+ selectedCameraId = cameraSetting.value;
477
+ localStorage.setItem('selectedCameraId', selectedCameraId);
478
+ await startCamera(selectedCameraId);
479
+ });
480
+
481
+ // Clear storage
482
+ clearStorageBtn.addEventListener('click', clearAllData);
483
+
484
+ // Keyboard shortcut for snapping (Spacebar)
485
+ document.addEventListener('keydown', (e) => {
486
+ if (e.code === 'Space') {
487
+ e.preventDefault();
488
+ takeSnapshot();
489
+ }
490
+ });
491
+ }
492
+ });
493
+ </script>
494
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Ultronprime/snapitraph" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
495
+ </html>
prompts.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ create an app to snap easily and store in each categories which i will ad the categories on my presistance storage. with a simple fast snap icon