Freefall commited on
Commit
a5178b8
·
verified ·
1 Parent(s): 9bbf93e

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +1083 -111
index.html CHANGED
@@ -3,50 +3,149 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Media Viewer Pro</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
- .media-container {
11
- transition: transform 0.3s ease;
12
- transform-origin: 0 0;
 
 
 
 
13
  }
14
- .custom-scrollbar::-webkit-scrollbar {
15
- width: 6px;
16
- height: 6px;
 
17
  }
18
- .custom-scrollbar::-webkit-scrollbar-track {
19
- background: #f1f1f1;
 
20
  }
21
- .custom-scrollbar::-webkit-scrollbar-thumb {
22
- background: #888;
23
- border-radius: 3px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  }
25
- .custom-scrollbar::-webkit-scrollbar-thumb:hover {
26
- background: #555;
 
27
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  .thumbnail {
29
  transition: all 0.2s ease;
 
30
  }
 
31
  .thumbnail:hover {
32
  transform: scale(1.05);
33
- box-shadow: 0 4px 8px rgba(0,0,0,0.2);
34
  }
 
35
  .thumbnail.active {
36
- border: 3px solid #3b82f6;
37
- box-shadow: 0 0 0 2px white;
38
  }
 
39
  .tooltip {
40
  position: relative;
41
  }
 
42
  .tooltip:before {
43
  content: attr(data-tooltip);
44
  position: absolute;
45
  bottom: 100%;
46
  left: 50%;
47
  transform: translateX(-50%);
48
- background: #333;
49
- color: white;
50
  padding: 4px 8px;
51
  border-radius: 4px;
52
  font-size: 12px;
@@ -54,135 +153,428 @@
54
  opacity: 0;
55
  visibility: hidden;
56
  transition: all 0.2s ease;
 
 
57
  }
 
58
  .tooltip:hover:before {
59
  opacity: 1;
60
  visibility: visible;
61
  bottom: calc(100% + 5px);
62
  }
63
- .dropdown {
64
- position: relative;
65
- display: inline-block;
66
- }
67
  .dropdown-content {
68
  display: none;
69
  position: absolute;
70
- background-color: #f9f9f9;
71
  min-width: 160px;
72
- box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
73
  z-index: 1;
74
  border-radius: 4px;
75
  overflow: hidden;
 
76
  }
 
77
  .dropdown-content a {
78
- color: black;
79
  padding: 8px 12px;
80
  text-decoration: none;
81
  display: block;
82
  font-size: 14px;
 
83
  }
 
84
  .dropdown-content a:hover {
85
- background-color: #3b82f6;
86
  color: white;
87
  }
 
88
  .dropdown:hover .dropdown-content {
89
  display: block;
90
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  </style>
92
  </head>
93
- <body class="bg-gray-100 font-sans">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  <div class="container mx-auto p-4 max-w-6xl">
95
- <div class="bg-white rounded-xl shadow-lg overflow-hidden">
96
- <!-- Header -->
97
- <div class="bg-gray-800 text-white p-4 flex justify-between items-center">
98
- <h1 class="text-xl font-bold">Media Viewer Pro</h1>
99
- <div class="flex space-x-2">
100
- <div class="dropdown">
101
- <button id="open-files" class="bg-blue-600 hover:bg-blue-700 px-3 py-1 rounded tooltip" data-tooltip="Open Media">
102
- <i class="fas fa-folder-open mr-1"></i> Open <i class="fas fa-caret-down ml-1"></i>
103
- </button>
104
- <div class="dropdown-content">
105
- <a href="#" id="open-files-btn">Files</a>
106
- <a href="#" id="open-folder-btn">Folder</a>
107
- </div>
 
108
  </div>
109
- <input type="file" id="file-input" class="hidden" multiple accept="image/*,video/*">
110
- <input type="file" id="folder-input" class="hidden" webkitdirectory directory multiple accept="image/*,video/*">
111
  </div>
 
 
 
 
 
 
112
  </div>
113
-
114
- <!-- Main Content -->
115
- <div class="flex flex-col md:flex-row h-[70vh]">
116
- <!-- Media Display Area -->
117
- <div class="flex-1 relative overflow-hidden bg-black flex items-center justify-center">
118
- <div id="media-display" class="w-full h-full flex items-center justify-center relative">
119
- <div id="no-media" class="text-gray-400 text-center p-8">
120
- <i class="fas fa-images text-5xl mb-4"></i>
121
- <p class="text-xl">No media selected</p>
122
- <p class="text-sm mt-2">Click "Open" to browse files or folders</p>
123
- </div>
124
-
125
- <div id="image-container" class="hidden absolute inset-0 overflow-auto custom-scrollbar">
126
- <div id="image-wrapper" class="media-container">
127
- <img id="current-image" class="max-w-full max-h-full" src="" alt="">
128
- </div>
129
- </div>
130
-
131
- <div id="video-container" class="hidden relative w-full h-full">
132
- <video id="current-video" class="max-w-full max-h-full" controls>
133
- Your browser does not support the video tag.
134
- </video>
135
  </div>
136
  </div>
137
 
138
- <!-- Navigation Arrows -->
139
- <button id="prev-btn" class="hidden absolute left-4 top-1/2 -translate-y-1/2 bg-black bg-opacity-50 text-white p-3 rounded-full hover:bg-opacity-70">
140
- <i class="fas fa-chevron-left text-xl"></i>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  </button>
142
- <button id="next-btn" class="hidden absolute right-4 top-1/2 -translate-y-1/2 bg-black bg-opacity-50 text-white p-3 rounded-full hover:bg-opacity-70">
143
- <i class="fas fa-chevron-right text-xl"></i>
 
 
 
 
 
144
  </button>
145
-
146
- <!-- Zoom Controls -->
147
- <div id="zoom-controls" class="hidden absolute bottom-4 right-4 bg-black bg-opacity-50 text-white p-2 rounded-lg">
148
- <button id="zoom-in" class="p-1 hover:bg-gray-700 rounded">
149
- <i class="fas fa-search-plus"></i>
150
- </button>
151
- <div class="h-px bg-gray-500 my-1"></div>
152
- <button id="zoom-out" class="p-1 hover:bg-gray-700 rounded">
153
- <i class="fas fa-search-minus"></i>
154
- </button>
155
- <div class="h-px bg-gray-500 my-1"></div>
156
- <button id="zoom-reset" class="p-1 hover:bg-gray-700 rounded">
157
- <i class="fas fa-expand"></i>
158
- </button>
159
- </div>
160
  </div>
161
 
162
- <!-- Thumbnail Sidebar -->
163
- <div id="thumbnail-sidebar" class="hidden w-full md:w-48 bg-gray-100 border-l border-gray-200 overflow-y-auto custom-scrollbar p-2">
164
- <div id="thumbnail-container" class="grid grid-cols-2 md:grid-cols-1 gap-2">
165
- <!-- Thumbnails will be added here -->
 
 
 
 
 
 
 
 
 
 
166
  </div>
167
  </div>
168
  </div>
169
 
 
 
 
 
 
 
 
170
  <!-- Controls -->
171
- <div class="bg-gray-200 p-4 border-t border-gray-300">
172
  <div class="flex flex-wrap items-center justify-between gap-4">
173
  <!-- Playback Controls -->
174
  <div class="flex items-center space-x-2">
175
- <button id="play-pause" class="bg-blue-600 text-white p-2 rounded-full hover:bg-blue-700 tooltip" data-tooltip="Play/Pause">
176
- <i class="fas fa-play"></i>
177
  </button>
178
- <button id="stop" class="bg-gray-600 text-white p-2 rounded-full hover:bg-gray-700 tooltip" data-tooltip="Stop">
179
- <i class="fas fa-stop"></i>
180
  </button>
181
- <button id="prev" class="bg-gray-600 text-white p-2 rounded-full hover:bg-gray-700 tooltip" data-tooltip="Previous">
182
- <i class="fas fa-step-backward"></i>
183
  </button>
184
- <button id="next" class="bg-gray-600 text-white p-2 rounded-full hover:bg-gray-700 tooltip" data-tooltip="Next">
185
- <i class="fas fa-step-forward"></i>
186
  </button>
187
  </div>
188
 
@@ -190,7 +582,7 @@
190
  <div class="flex items-center space-x-4">
191
  <div class="flex items-center">
192
  <span class="text-sm mr-2">Speed:</span>
193
- <select id="slideshow-speed" class="bg-white border border-gray-300 rounded px-2 py-1 text-sm">
194
  <option value="1000">1 sec</option>
195
  <option value="2000" selected>2 sec</option>
196
  <option value="3000">3 sec</option>
@@ -198,7 +590,7 @@
198
  <option value="10000">10 sec</option>
199
  </select>
200
  </div>
201
- <button id="toggle-slideshow" class="bg-green-600 text-white px-3 py-1 rounded hover:bg-green-700 tooltip" data-tooltip="Start Slideshow">
202
  <i class="fas fa-images mr-1"></i> Slideshow
203
  </button>
204
  </div>
@@ -207,27 +599,25 @@
207
  <div class="flex items-center space-x-4">
208
  <div class="flex items-center">
209
  <span class="text-sm mr-2">Size:</span>
210
- <select id="image-size" class="bg-white border border-gray-300 rounded px-2 py-1 text-sm">
211
  <option value="contain">Fit</option>
212
  <option value="cover">Fill</option>
213
  <option value="original">Original</option>
214
  </select>
215
  </div>
216
- <button id="toggle-sidebar" class="bg-gray-600 text-white px-3 py-1 rounded hover:bg-gray-700 tooltip" data-tooltip="Toggle Thumbnails">
217
  <i class="fas fa-th mr-1"></i> Thumbnails
218
  </button>
219
  </div>
220
  </div>
221
 
222
- <!-- Progress Bar -->
223
- <div class="mt-4">
224
- <div class="flex justify-between text-xs text-gray-600 mb-1">
225
- <span id="current-index">0/0</span>
226
- <span id="media-name"></span>
227
- </div>
228
- <div class="w-full bg-gray-300 rounded-full h-2">
229
- <div id="progress-bar" class="bg-blue-600 h-2 rounded-full" style="width: 0%"></div>
230
  </div>
 
231
  </div>
232
  </div>
233
  </div>
@@ -246,5 +636,587 @@
246
  const videoContainer = document.getElementById('video-container');
247
  const currentImage = document.getElementById('current-image');
248
  const currentVideo = document.getElementById('current-video');
249
- const thumbnail
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>WontView LeeT - Cyber Media Viewer</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
+ <script>
10
+ tailwind.config = {
11
+ theme: {
12
+ extend: {
13
+ colors: {
14
+ cyber: {
15
+ primary: '#00ff9d',
16
+ secondary: '#00b8ff',
17
+ dark: '#0a0a1a',
18
+ darker: '#050510',
19
+ accent: '#ff00aa',
20
+ glow: 'rgba(0, 255, 157, 0.3)'
21
+ }
22
+ },
23
+ fontFamily: {
24
+ 'cyber': ['"Courier New"', 'monospace']
25
+ },
26
+ boxShadow: {
27
+ 'cyber': '0 0 10px rgba(0, 255, 157, 0.7)',
28
+ 'cyber-sm': '0 0 5px rgba(0, 255, 157, 0.5)',
29
+ 'cyber-lg': '0 0 15px rgba(0, 255, 157, 0.9)'
30
+ }
31
+ }
32
+ }
33
+ }
34
+ </script>
35
  <style>
36
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
37
+
38
+ body {
39
+ font-family: 'Orbitron', sans-serif;
40
+ background-color: #050510;
41
+ color: #00ff9d;
42
+ overflow-x: hidden;
43
  }
44
+
45
+ .cyber-border {
46
+ border: 1px solid #00ff9d;
47
+ box-shadow: 0 0 10px rgba(0, 255, 157, 0.3);
48
  }
49
+
50
+ .cyber-bg {
51
+ background: linear-gradient(135deg, #0a0a1a 0%, #050510 100%);
52
  }
53
+
54
+ .cyber-text {
55
+ text-shadow: 0 0 5px rgba(0, 255, 157, 0.7);
56
+ }
57
+
58
+ .cyber-button {
59
+ transition: all 0.2s ease;
60
+ position: relative;
61
+ overflow: hidden;
62
+ }
63
+
64
+ .cyber-button:hover {
65
+ transform: translateY(-2px);
66
+ box-shadow: 0 0 15px rgba(0, 255, 157, 0.7);
67
+ }
68
+
69
+ .cyber-button:active {
70
+ transform: translateY(0);
71
+ }
72
+
73
+ .cyber-button:after {
74
+ content: '';
75
+ position: absolute;
76
+ top: 0;
77
+ left: -100%;
78
+ width: 100%;
79
+ height: 100%;
80
+ background: linear-gradient(90deg, transparent, rgba(0, 255, 157, 0.4), transparent);
81
+ transition: all 0.5s ease;
82
+ }
83
+
84
+ .cyber-button:hover:after {
85
+ left: 100%;
86
+ }
87
+
88
+ .glow {
89
+ animation: glow 2s infinite alternate;
90
+ }
91
+
92
+ @keyframes glow {
93
+ from {
94
+ box-shadow: 0 0 5px rgba(0, 255, 157, 0.5);
95
+ }
96
+ to {
97
+ box-shadow: 0 0 15px rgba(0, 255, 157, 0.9);
98
+ }
99
  }
100
+
101
+ .pulse {
102
+ animation: pulse 2s infinite;
103
  }
104
+
105
+ @keyframes pulse {
106
+ 0% {
107
+ opacity: 0.7;
108
+ }
109
+ 50% {
110
+ opacity: 1;
111
+ }
112
+ 100% {
113
+ opacity: 0.7;
114
+ }
115
+ }
116
+
117
+ .media-container {
118
+ transition: transform 0.3s ease;
119
+ transform-origin: 0 0;
120
+ }
121
+
122
  .thumbnail {
123
  transition: all 0.2s ease;
124
+ position: relative;
125
  }
126
+
127
  .thumbnail:hover {
128
  transform: scale(1.05);
129
+ box-shadow: 0 0 10px rgba(0, 255, 157, 0.7);
130
  }
131
+
132
  .thumbnail.active {
133
+ border: 2px solid #00ff9d;
134
+ box-shadow: 0 0 15px rgba(0, 255, 157, 0.9);
135
  }
136
+
137
  .tooltip {
138
  position: relative;
139
  }
140
+
141
  .tooltip:before {
142
  content: attr(data-tooltip);
143
  position: absolute;
144
  bottom: 100%;
145
  left: 50%;
146
  transform: translateX(-50%);
147
+ background: #0a0a1a;
148
+ color: #00ff9d;
149
  padding: 4px 8px;
150
  border-radius: 4px;
151
  font-size: 12px;
 
153
  opacity: 0;
154
  visibility: hidden;
155
  transition: all 0.2s ease;
156
+ border: 1px solid #00ff9d;
157
+ box-shadow: 0 0 5px rgba(0, 255, 157, 0.5);
158
  }
159
+
160
  .tooltip:hover:before {
161
  opacity: 1;
162
  visibility: visible;
163
  bottom: calc(100% + 5px);
164
  }
165
+
 
 
 
166
  .dropdown-content {
167
  display: none;
168
  position: absolute;
169
+ background-color: #0a0a1a;
170
  min-width: 160px;
171
+ box-shadow: 0 0 15px rgba(0, 255, 157, 0.5);
172
  z-index: 1;
173
  border-radius: 4px;
174
  overflow: hidden;
175
+ border: 1px solid #00ff9d;
176
  }
177
+
178
  .dropdown-content a {
179
+ color: #00ff9d;
180
  padding: 8px 12px;
181
  text-decoration: none;
182
  display: block;
183
  font-size: 14px;
184
+ transition: all 0.2s ease;
185
  }
186
+
187
  .dropdown-content a:hover {
188
+ background-color: rgba(0, 255, 157, 0.2);
189
  color: white;
190
  }
191
+
192
  .dropdown:hover .dropdown-content {
193
  display: block;
194
  }
195
+
196
+ .progress-bar {
197
+ height: 4px;
198
+ background: #0a0a1a;
199
+ border-radius: 2px;
200
+ overflow: hidden;
201
+ }
202
+
203
+ .progress-fill {
204
+ height: 100%;
205
+ background: linear-gradient(90deg, #00ff9d, #00b8ff);
206
+ transition: width 0.1s linear;
207
+ }
208
+
209
+ .volume-slider {
210
+ -webkit-appearance: none;
211
+ width: 100px;
212
+ height: 4px;
213
+ background: #0a0a1a;
214
+ border-radius: 2px;
215
+ outline: none;
216
+ }
217
+
218
+ .volume-slider::-webkit-slider-thumb {
219
+ -webkit-appearance: none;
220
+ appearance: none;
221
+ width: 12px;
222
+ height: 12px;
223
+ border-radius: 50%;
224
+ background: #00ff9d;
225
+ cursor: pointer;
226
+ box-shadow: 0 0 5px rgba(0, 255, 157, 0.7);
227
+ }
228
+
229
+ .volume-slider::-moz-range-thumb {
230
+ width: 12px;
231
+ height: 12px;
232
+ border-radius: 50%;
233
+ background: #00ff9d;
234
+ cursor: pointer;
235
+ box-shadow: 0 0 5px rgba(0, 255, 157, 0.7);
236
+ }
237
+
238
+ .drag-overlay {
239
+ position: fixed;
240
+ top: 0;
241
+ left: 0;
242
+ right: 0;
243
+ bottom: 0;
244
+ background: rgba(5, 5, 16, 0.8);
245
+ border: 4px dashed #00ff9d;
246
+ display: flex;
247
+ align-items: center;
248
+ justify-content: center;
249
+ z-index: 1000;
250
+ pointer-events: none;
251
+ opacity: 0;
252
+ transition: opacity 0.3s ease;
253
+ }
254
+
255
+ .drag-overlay.active {
256
+ opacity: 1;
257
+ pointer-events: all;
258
+ }
259
+
260
+ .nav-arrow {
261
+ position: absolute;
262
+ top: 50%;
263
+ transform: translateY(-50%);
264
+ width: 50px;
265
+ height: 100px;
266
+ background: rgba(10, 10, 26, 0.7);
267
+ display: flex;
268
+ align-items: center;
269
+ justify-content: center;
270
+ cursor: pointer;
271
+ opacity: 0;
272
+ transition: opacity 0.3s ease;
273
+ border: 1px solid #00ff9d;
274
+ z-index: 10;
275
+ }
276
+
277
+ .nav-arrow:hover {
278
+ background: rgba(0, 255, 157, 0.2);
279
+ opacity: 1 !important;
280
+ }
281
+
282
+ .media-area:hover .nav-arrow {
283
+ opacity: 0.7;
284
+ }
285
+
286
+ .nav-arrow.left {
287
+ left: 0;
288
+ border-left: none;
289
+ border-radius: 0 5px 5px 0;
290
+ }
291
+
292
+ .nav-arrow.right {
293
+ right: 0;
294
+ border-right: none;
295
+ border-radius: 5px 0 0 5px;
296
+ }
297
+
298
+ .settings-panel {
299
+ position: fixed;
300
+ top: 50%;
301
+ left: 50%;
302
+ transform: translate(-50%, -50%);
303
+ background: #0a0a1a;
304
+ border: 1px solid #00ff9d;
305
+ box-shadow: 0 0 20px rgba(0, 255, 157, 0.5);
306
+ z-index: 100;
307
+ padding: 20px;
308
+ border-radius: 5px;
309
+ max-width: 500px;
310
+ width: 90%;
311
+ opacity: 0;
312
+ pointer-events: none;
313
+ transition: all 0.3s ease;
314
+ }
315
+
316
+ .settings-panel.active {
317
+ opacity: 1;
318
+ pointer-events: all;
319
+ }
320
+
321
+ .settings-overlay {
322
+ position: fixed;
323
+ top: 0;
324
+ left: 0;
325
+ right: 0;
326
+ bottom: 0;
327
+ background: rgba(0, 0, 0, 0.7);
328
+ z-index: 99;
329
+ opacity: 0;
330
+ pointer-events: none;
331
+ transition: opacity 0.3s ease;
332
+ }
333
+
334
+ .settings-overlay.active {
335
+ opacity: 1;
336
+ pointer-events: all;
337
+ }
338
+
339
+ .checkbox-container {
340
+ display: block;
341
+ position: relative;
342
+ padding-left: 30px;
343
+ margin-bottom: 12px;
344
+ cursor: pointer;
345
+ user-select: none;
346
+ }
347
+
348
+ .checkbox-container input {
349
+ position: absolute;
350
+ opacity: 0;
351
+ cursor: pointer;
352
+ height: 0;
353
+ width: 0;
354
+ }
355
+
356
+ .checkmark {
357
+ position: absolute;
358
+ top: 0;
359
+ left: 0;
360
+ height: 20px;
361
+ width: 20px;
362
+ background-color: #050510;
363
+ border: 1px solid #00ff9d;
364
+ border-radius: 3px;
365
+ }
366
+
367
+ .checkbox-container:hover input ~ .checkmark {
368
+ background-color: rgba(0, 255, 157, 0.1);
369
+ }
370
+
371
+ .checkbox-container input:checked ~ .checkmark {
372
+ background-color: #00ff9d;
373
+ }
374
+
375
+ .checkmark:after {
376
+ content: "";
377
+ position: absolute;
378
+ display: none;
379
+ }
380
+
381
+ .checkbox-container input:checked ~ .checkmark:after {
382
+ display: block;
383
+ }
384
+
385
+ .checkbox-container .checkmark:after {
386
+ left: 7px;
387
+ top: 3px;
388
+ width: 5px;
389
+ height: 10px;
390
+ border: solid #050510;
391
+ border-width: 0 2px 2px 0;
392
+ transform: rotate(45deg);
393
+ }
394
+
395
+ .scrollbar-hide::-webkit-scrollbar {
396
+ display: none;
397
+ }
398
+
399
+ .scrollbar-hide {
400
+ -ms-overflow-style: none;
401
+ scrollbar-width: none;
402
+ }
403
  </style>
404
  </head>
405
+ <body class="bg-cyber-darker text-cyber-primary">
406
+ <!-- Drag and Drop Overlay -->
407
+ <div id="drag-overlay" class="drag-overlay">
408
+ <div class="text-center p-8 cyber-border rounded-lg bg-cyber-dark">
409
+ <i class="fas fa-cloud-upload-alt text-6xl mb-4 text-cyber-accent"></i>
410
+ <h2 class="text-2xl mb-2">Drop Media Here</h2>
411
+ <p class="text-cyber-secondary">Images or Videos</p>
412
+ </div>
413
+ </div>
414
+
415
+ <!-- Settings Panel -->
416
+ <div id="settings-overlay" class="settings-overlay"></div>
417
+ <div id="settings-panel" class="settings-panel">
418
+ <div class="flex justify-between items-center mb-4 border-b border-cyber-primary pb-2">
419
+ <h3 class="text-xl">Settings</h3>
420
+ <button id="close-settings" class="text-cyber-primary hover:text-cyber-accent">
421
+ <i class="fas fa-times"></i>
422
+ </button>
423
+ </div>
424
+
425
+ <div class="space-y-4">
426
+ <div>
427
+ <h4 class="text-lg mb-2">Mouse Wheel Behavior</h4>
428
+ <label class="checkbox-container">Zoom with mouse wheel
429
+ <input type="radio" name="wheel-behavior" value="zoom" checked>
430
+ <span class="checkmark"></span>
431
+ </label>
432
+ <label class="checkbox-container">Navigate with mouse wheel
433
+ <input type="radio" name="wheel-behavior" value="navigate">
434
+ <span class="checkmark"></span>
435
+ </label>
436
+ </div>
437
+
438
+ <div>
439
+ <h4 class="text-lg mb-2">Slideshow Options</h4>
440
+ <label class="checkbox-container">Skip videos during slideshow
441
+ <input type="checkbox" id="skip-videos" checked>
442
+ <span class="checkmark"></span>
443
+ </label>
444
+ </div>
445
+
446
+ <div>
447
+ <h4 class="text-lg mb-2">Appearance</h4>
448
+ <label class="checkbox-container">Enable cyber effects
449
+ <input type="checkbox" id="cyber-effects" checked>
450
+ <span class="checkmark"></span>
451
+ </label>
452
+ </div>
453
+ </div>
454
+
455
+ <div class="mt-6 pt-4 border-t border-cyber-primary">
456
+ <button id="save-settings" class="w-full bg-cyber-primary text-cyber-dark py-2 rounded hover:bg-cyber-secondary transition-all">
457
+ Save Settings
458
+ </button>
459
+ </div>
460
+ </div>
461
+
462
+ <!-- Main Container -->
463
  <div class="container mx-auto p-4 max-w-6xl">
464
+ <!-- Header -->
465
+ <div class="flex justify-between items-center mb-6">
466
+ <div>
467
+ <h1 class="text-3xl font-bold cyber-text glow">WontView LeeT</h1>
468
+ <p class="text-cyber-secondary text-sm">Cyber Media Viewer v1.0</p>
469
+ </div>
470
+ <div class="flex space-x-3">
471
+ <div class="dropdown">
472
+ <button id="open-files" class="cyber-button bg-cyber-dark px-4 py-2 rounded cyber-border hover:shadow-cyber">
473
+ <i class="fas fa-folder-open mr-2"></i> Open <i class="fas fa-caret-down ml-1"></i>
474
+ </button>
475
+ <div class="dropdown-content">
476
+ <a href="#" id="open-files-btn"><i class="fas fa-file-image mr-2"></i> Files</a>
477
+ <a href="#" id="open-folder-btn"><i class="fas fa-folder mr-2"></i> Folder</a>
478
  </div>
 
 
479
  </div>
480
+ <input type="file" id="file-input" class="hidden" multiple accept="image/*,video/*">
481
+ <input type="file" id="folder-input" class="hidden" webkitdirectory directory multiple accept="image/*,video/*">
482
+
483
+ <button id="settings-btn" class="cyber-button bg-cyber-dark px-4 py-2 rounded cyber-border hover:shadow-cyber tooltip" data-tooltip="Settings">
484
+ <i class="fas fa-cog"></i>
485
+ </button>
486
  </div>
487
+ </div>
488
+
489
+ <!-- Main Content -->
490
+ <div class="cyber-bg cyber-border rounded-xl overflow-hidden">
491
+ <!-- Media Display Area -->
492
+ <div class="media-area relative h-[70vh] bg-black flex items-center justify-center">
493
+ <div id="media-display" class="w-full h-full flex items-center justify-center relative">
494
+ <div id="no-media" class="text-cyber-secondary text-center p-8">
495
+ <i class="fas fa-images text-6xl mb-4 text-cyber-accent pulse"></i>
496
+ <p class="text-xl mb-2">No media selected</p>
497
+ <p class="text-sm">Drag & drop files or click "Open"</p>
498
+ <p class="text-xs mt-4 text-cyber-secondary">Supports: JPG, PNG, GIF, MP4, WEBM</p>
499
+ </div>
500
+
501
+ <div id="image-container" class="hidden absolute inset-0 overflow-auto">
502
+ <div id="image-wrapper" class="media-container">
503
+ <img id="current-image" class="max-w-full max-h-full" src="" alt="">
 
 
 
 
 
504
  </div>
505
  </div>
506
 
507
+ <div id="video-container" class="hidden relative w-full h-full">
508
+ <video id="current-video" class="max-w-full max-h-full" controls>
509
+ Your browser does not support the video tag.
510
+ </video>
511
+ </div>
512
+ </div>
513
+
514
+ <!-- Navigation Arrows -->
515
+ <div id="prev-btn" class="nav-arrow left tooltip" data-tooltip="Previous (←)">
516
+ <i class="fas fa-chevron-left text-2xl"></i>
517
+ </div>
518
+ <div id="next-btn" class="nav-arrow right tooltip" data-tooltip="Next (→)">
519
+ <i class="fas fa-chevron-right text-2xl"></i>
520
+ </div>
521
+
522
+ <!-- Zoom Controls -->
523
+ <div id="zoom-controls" class="hidden absolute bottom-4 right-4 bg-cyber-dark bg-opacity-90 text-cyber-primary p-2 rounded cyber-border">
524
+ <button id="zoom-in" class="p-2 hover:text-cyber-accent tooltip" data-tooltip="Zoom In (+)">
525
+ <i class="fas fa-search-plus"></i>
526
  </button>
527
+ <div class="h-px bg-cyber-primary my-1"></div>
528
+ <button id="zoom-out" class="p-2 hover:text-cyber-accent tooltip" data-tooltip="Zoom Out (-)">
529
+ <i class="fas fa-search-minus"></i>
530
+ </button>
531
+ <div class="h-px bg-cyber-primary my-1"></div>
532
+ <button id="zoom-reset" class="p-2 hover:text-cyber-accent tooltip" data-tooltip="Reset Zoom (0)">
533
+ <i class="fas fa-expand"></i>
534
  </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
535
  </div>
536
 
537
+ <!-- Video Controls -->
538
+ <div id="video-controls" class="hidden absolute bottom-4 left-4 right-4 bg-cyber-dark bg-opacity-90 text-cyber-primary p-3 rounded cyber-border flex items-center justify-between">
539
+ <button id="play-pause" class="p-2 hover:text-cyber-accent tooltip" data-tooltip="Play/Pause (Space)">
540
+ <i class="fas fa-play" id="play-icon"></i>
541
+ </button>
542
+ <div class="flex-1 mx-4">
543
+ <div class="progress-bar">
544
+ <div id="progress-fill" class="progress-fill" style="width: 0%"></div>
545
+ </div>
546
+ </div>
547
+ <div class="flex items-center space-x-3">
548
+ <i class="fas fa-volume-down"></i>
549
+ <input type="range" id="volume-slider" class="volume-slider" min="0" max="1" step="0.01" value="1">
550
+ <i class="fas fa-volume-up"></i>
551
  </div>
552
  </div>
553
  </div>
554
 
555
+ <!-- Thumbnail Sidebar -->
556
+ <div id="thumbnail-sidebar" class="hidden w-full bg-cyber-dark border-t border-cyber-primary p-2 overflow-x-auto scrollbar-hide">
557
+ <div id="thumbnail-container" class="flex space-x-2">
558
+ <!-- Thumbnails will be added here -->
559
+ </div>
560
+ </div>
561
+
562
  <!-- Controls -->
563
+ <div class="bg-cyber-dark p-4 border-t border-cyber-primary">
564
  <div class="flex flex-wrap items-center justify-between gap-4">
565
  <!-- Playback Controls -->
566
  <div class="flex items-center space-x-2">
567
+ <button id="play-pause-bottom" class="cyber-button bg-cyber-dark px-3 py-1 rounded cyber-border hover:shadow-cyber tooltip" data-tooltip="Play/Pause (Space)">
568
+ <i class="fas fa-play mr-1" id="play-icon-bottom"></i> Play
569
  </button>
570
+ <button id="stop-bottom" class="cyber-button bg-cyber-dark px-3 py-1 rounded cyber-border hover:shadow-cyber tooltip" data-tooltip="Stop">
571
+ <i class="fas fa-stop mr-1"></i> Stop
572
  </button>
573
+ <button id="prev-bottom" class="cyber-button bg-cyber-dark px-3 py-1 rounded cyber-border hover:shadow-cyber tooltip" data-tooltip="Previous (←)">
574
+ <i class="fas fa-step-backward mr-1"></i> Prev
575
  </button>
576
+ <button id="next-bottom" class="cyber-button bg-cyber-dark px-3 py-1 rounded cyber-border hover:shadow-cyber tooltip" data-tooltip="Next (→)">
577
+ <i class="fas fa-step-forward mr-1"></i> Next
578
  </button>
579
  </div>
580
 
 
582
  <div class="flex items-center space-x-4">
583
  <div class="flex items-center">
584
  <span class="text-sm mr-2">Speed:</span>
585
+ <select id="slideshow-speed" class="bg-cyber-dark border border-cyber-primary rounded px-2 py-1 text-sm text-cyber-primary">
586
  <option value="1000">1 sec</option>
587
  <option value="2000" selected>2 sec</option>
588
  <option value="3000">3 sec</option>
 
590
  <option value="10000">10 sec</option>
591
  </select>
592
  </div>
593
+ <button id="toggle-slideshow" class="cyber-button bg-cyber-dark px-3 py-1 rounded cyber-border hover:shadow-cyber tooltip" data-tooltip="Start Slideshow">
594
  <i class="fas fa-images mr-1"></i> Slideshow
595
  </button>
596
  </div>
 
599
  <div class="flex items-center space-x-4">
600
  <div class="flex items-center">
601
  <span class="text-sm mr-2">Size:</span>
602
+ <select id="image-size" class="bg-cyber-dark border border-cyber-primary rounded px-2 py-1 text-sm text-cyber-primary">
603
  <option value="contain">Fit</option>
604
  <option value="cover">Fill</option>
605
  <option value="original">Original</option>
606
  </select>
607
  </div>
608
+ <button id="toggle-sidebar" class="cyber-button bg-cyber-dark px-3 py-1 rounded cyber-border hover:shadow-cyber tooltip" data-tooltip="Toggle Thumbnails (T)">
609
  <i class="fas fa-th mr-1"></i> Thumbnails
610
  </button>
611
  </div>
612
  </div>
613
 
614
+ <!-- Status Bar -->
615
+ <div class="mt-4 flex justify-between items-center text-sm">
616
+ <div>
617
+ <span id="current-index" class="text-cyber-secondary">0/0</span>
618
+ <span id="media-name" class="ml-2 text-cyber-primary"></span>
 
 
 
619
  </div>
620
+ <div id="status-message" class="text-cyber-accent pulse"></div>
621
  </div>
622
  </div>
623
  </div>
 
636
  const videoContainer = document.getElementById('video-container');
637
  const currentImage = document.getElementById('current-image');
638
  const currentVideo = document.getElementById('current-video');
639
+ const thumbnailContainer = document.getElementById('thumbnail-container');
640
+ const thumbnailSidebar = document.getElementById('thumbnail-sidebar');
641
+ const prevBtn = document.getElementById('prev-btn');
642
+ const nextBtn = document.getElementById('next-btn');
643
+ const prevBottomBtn = document.getElementById('prev-bottom');
644
+ const nextBottomBtn = document.getElementById('next-bottom');
645
+ const zoomInBtn = document.getElementById('zoom-in');
646
+ const zoomOutBtn = document.getElementById('zoom-out');
647
+ const zoomResetBtn = document.getElementById('zoom-reset');
648
+ const zoomControls = document.getElementById('zoom-controls');
649
+ const playPauseBtn = document.getElementById('play-pause');
650
+ const playPauseBottomBtn = document.getElementById('play-pause-bottom');
651
+ const stopBottomBtn = document.getElementById('stop-bottom');
652
+ const playIcon = document.getElementById('play-icon');
653
+ const playIconBottom = document.getElementById('play-icon-bottom');
654
+ const toggleSlideshowBtn = document.getElementById('toggle-slideshow');
655
+ const toggleSidebarBtn = document.getElementById('toggle-sidebar');
656
+ const currentIndexDisplay = document.getElementById('current-index');
657
+ const mediaNameDisplay = document.getElementById('media-name');
658
+ const progressFill = document.getElementById('progress-fill');
659
+ const videoControls = document.getElementById('video-controls');
660
+ const volumeSlider = document.getElementById('volume-slider');
661
+ const imageSizeSelect = document.getElementById('image-size');
662
+ const slideshowSpeedSelect = document.getElementById('slideshow-speed');
663
+ const dragOverlay = document.getElementById('drag-overlay');
664
+ const settingsBtn = document.getElementById('settings-btn');
665
+ const settingsPanel = document.getElementById('settings-panel');
666
+ const settingsOverlay = document.getElementById('settings-overlay');
667
+ const closeSettingsBtn = document.getElementById('close-settings');
668
+ const saveSettingsBtn = document.getElementById('save-settings');
669
+ const statusMessage = document.getElementById('status-message');
670
+
671
+ // State variables
672
+ let mediaFiles = [];
673
+ let currentIndex = 0;
674
+ let isSlideshowRunning = false;
675
+ let slideshowInterval;
676
+ let zoomLevel = 1;
677
+ let isDragging = false;
678
+ let startX, startY, translateX = 0, translateY = 0;
679
+ let wheelBehavior = 'zoom'; // 'zoom' or 'navigate'
680
+ let skipVideosInSlideshow = true;
681
+ let cyberEffectsEnabled = true;
682
+
683
+ // Initialize settings from localStorage
684
+ loadSettings();
685
+
686
+ // Event Listeners for file/folder opening
687
+ openFilesBtn.addEventListener('click', () => fileInput.click());
688
+ openFolderBtn.addEventListener('click', () => folderInput.click());
689
+
690
+ fileInput.addEventListener('change', handleFileSelection);
691
+ folderInput.addEventListener('change', handleFileSelection);
692
+
693
+ // Drag and drop functionality
694
+ document.addEventListener('dragover', (e) => {
695
+ e.preventDefault();
696
+ dragOverlay.classList.add('active');
697
+ });
698
+
699
+ document.addEventListener('dragleave', () => {
700
+ dragOverlay.classList.remove('active');
701
+ });
702
+
703
+ document.addEventListener('drop', (e) => {
704
+ e.preventDefault();
705
+ dragOverlay.classList.remove('active');
706
+
707
+ if (e.dataTransfer.items) {
708
+ const files = [];
709
+ const items = e.dataTransfer.items;
710
+
711
+ // Check if it's a directory (Chrome only)
712
+ const entry = items[0].webkitGetAsEntry();
713
+ if (entry && entry.isDirectory) {
714
+ statusMessage.textContent = "Please use the folder open option for directories";
715
+ setTimeout(() => statusMessage.textContent = "", 3000);
716
+ return;
717
+ }
718
+
719
+ // Handle files
720
+ for (let i = 0; i < items.length; i++) {
721
+ if (items[i].kind === 'file') {
722
+ const file = items[i].getAsFile();
723
+ if (file.type.startsWith('image/') || file.type.startsWith('video/')) {
724
+ files.push(file);
725
+ }
726
+ }
727
+ }
728
+
729
+ if (files.length > 0) {
730
+ mediaFiles = files;
731
+ currentIndex = 0;
732
+ displayCurrentMedia();
733
+ updateThumbnails();
734
+ showStatusMessage(`Loaded ${files.length} files`);
735
+ }
736
+ }
737
+ });
738
+
739
+ // Navigation controls
740
+ prevBtn.addEventListener('click', goToPrevious);
741
+ nextBtn.addEventListener('click', goToNext);
742
+ prevBottomBtn.addEventListener('click', goToPrevious);
743
+ nextBottomBtn.addEventListener('click', goToNext);
744
+
745
+ // Zoom controls
746
+ zoomInBtn.addEventListener('click', () => zoomImage(1.2));
747
+ zoomOutBtn.addEventListener('click', () => zoomImage(0.8));
748
+ zoomResetBtn.addEventListener('click', resetZoom);
749
+
750
+ // Playback controls
751
+ playPauseBtn.addEventListener('click', togglePlayPause);
752
+ playPauseBottomBtn.addEventListener('click', togglePlayPause);
753
+ stopBottomBtn.addEventListener('click', stopPlayback);
754
+
755
+ // Video controls
756
+ currentVideo.addEventListener('timeupdate', updateVideoProgress);
757
+ currentVideo.addEventListener('play', () => {
758
+ playIcon.className = 'fas fa-pause';
759
+ playIconBottom.className = 'fas fa-pause';
760
+ });
761
+ currentVideo.addEventListener('pause', () => {
762
+ playIcon.className = 'fas fa-play';
763
+ playIconBottom.className = 'fas fa-play';
764
+ });
765
+ currentVideo.addEventListener('ended', goToNext);
766
+ volumeSlider.addEventListener('input', () => {
767
+ currentVideo.volume = volumeSlider.value;
768
+ });
769
+
770
+ // Slideshow controls
771
+ toggleSlideshowBtn.addEventListener('click', toggleSlideshow);
772
+
773
+ // Display options
774
+ toggleSidebarBtn.addEventListener('click', toggleThumbnailSidebar);
775
+ imageSizeSelect.addEventListener('change', () => {
776
+ if (mediaFiles.length > 0) {
777
+ applyImageSize();
778
+ }
779
+ });
780
+
781
+ // Mouse wheel behavior
782
+ mediaDisplay.addEventListener('wheel', handleWheelEvent);
783
+
784
+ // Mouse drag for panning zoomed images
785
+ imageContainer.addEventListener('mousedown', startDrag);
786
+ document.addEventListener('mousemove', dragImage);
787
+ document.addEventListener('mouseup', endDrag);
788
+ document.addEventListener('mouseleave', endDrag);
789
+
790
+ // Keyboard shortcuts
791
+ document.addEventListener('keydown', handleKeyboardShortcuts);
792
+
793
+ // Settings
794
+ settingsBtn.addEventListener('click', () => {
795
+ settingsPanel.classList.add('active');
796
+ settingsOverlay.classList.add('active');
797
+ });
798
+
799
+ closeSettingsBtn.addEventListener('click', closeSettings);
800
+ settingsOverlay.addEventListener('click', closeSettings);
801
+ saveSettingsBtn.addEventListener('click', saveSettings);
802
+
803
+ // Functions
804
+ function handleFileSelection(e) {
805
+ const files = Array.from(e.target.files);
806
+ if (files.length > 0) {
807
+ mediaFiles = files.filter(file =>
808
+ file.type.startsWith('image/') || file.type.startsWith('video/')
809
+ );
810
+ currentIndex = 0;
811
+ displayCurrentMedia();
812
+ updateThumbnails();
813
+ showStatusMessage(`Loaded ${mediaFiles.length} files`);
814
+ }
815
+ e.target.value = ''; // Reset input to allow selecting same files again
816
+ }
817
+
818
+ function displayCurrentMedia() {
819
+ if (mediaFiles.length === 0) {
820
+ noMedia.classList.remove('hidden');
821
+ imageContainer.classList.add('hidden');
822
+ videoContainer.classList.add('hidden');
823
+ zoomControls.classList.add('hidden');
824
+ videoControls.classList.add('hidden');
825
+ currentIndexDisplay.textContent = '0/0';
826
+ mediaNameDisplay.textContent = '';
827
+ return;
828
+ }
829
+
830
+ noMedia.classList.add('hidden');
831
+ const file = mediaFiles[currentIndex];
832
+
833
+ if (file.type.startsWith('image/')) {
834
+ // Display image
835
+ const reader = new FileReader();
836
+ reader.onload = function(e) {
837
+ currentImage.src = e.target.result;
838
+ imageContainer.classList.remove('hidden');
839
+ videoContainer.classList.add('hidden');
840
+ zoomControls.classList.remove('hidden');
841
+ videoControls.classList.add('hidden');
842
+ resetZoom();
843
+ applyImageSize();
844
+ };
845
+ reader.readAsDataURL(file);
846
+ } else if (file.type.startsWith('video/')) {
847
+ // Display video
848
+ const reader = new FileReader();
849
+ reader.onload = function(e) {
850
+ currentVideo.src = e.target.result;
851
+ imageContainer.classList.add('hidden');
852
+ videoContainer.classList.remove('hidden');
853
+ zoomControls.classList.add('hidden');
854
+ videoControls.classList.remove('hidden');
855
+ currentVideo.volume = volumeSlider.value;
856
+ playIcon.className = 'fas fa-play';
857
+ playIconBottom.className = 'fas fa-play';
858
+ };
859
+ reader.readAsDataURL(file);
860
+ }
861
+
862
+ // Update current index display
863
+ currentIndexDisplay.textContent = `${currentIndex + 1}/${mediaFiles.length}`;
864
+ mediaNameDisplay.textContent = file.name;
865
+
866
+ // Highlight active thumbnail
867
+ const thumbnails = document.querySelectorAll('.thumbnail');
868
+ thumbnails.forEach((thumb, index) => {
869
+ if (index === currentIndex) {
870
+ thumb.classList.add('active');
871
+ // Scroll thumbnail into view
872
+ thumb.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
873
+ } else {
874
+ thumb.classList.remove('active');
875
+ }
876
+ });
877
+ }
878
+
879
+ function updateThumbnails() {
880
+ thumbnailContainer.innerHTML = '';
881
+
882
+ if (mediaFiles.length === 0) {
883
+ thumbnailSidebar.classList.add('hidden');
884
+ return;
885
+ }
886
+
887
+ thumbnailSidebar.classList.remove('hidden');
888
+
889
+ mediaFiles.forEach((file, index) => {
890
+ const thumbnail = document.createElement('div');
891
+ thumbnail.className = `thumbnail flex-shrink-0 w-20 h-20 bg-cyber-darker rounded overflow-hidden cursor-pointer ${index === currentIndex ? 'active' : ''}`;
892
+ thumbnail.dataset.index = index;
893
+
894
+ if (file.type.startsWith('image/')) {
895
+ const reader = new FileReader();
896
+ reader.onload = function(e) {
897
+ thumbnail.innerHTML = `<img src="${e.target.result}" class="w-full h-full object-cover" alt="${file.name}">`;
898
+ };
899
+ reader.readAsDataURL(file);
900
+ } else if (file.type.startsWith('video/')) {
901
+ thumbnail.innerHTML = `
902
+ <div class="relative w-full h-full bg-cyber-dark flex items-center justify-center">
903
+ <i class="fas fa-play text-cyber-accent text-xl"></i>
904
+ <div class="absolute bottom-0 left-0 right-0 bg-cyber-primary bg-opacity-70 text-cyber-dark text-xs p-1 truncate">${file.name}</div>
905
+ </div>
906
+ `;
907
+ }
908
+
909
+ thumbnail.addEventListener('click', () => {
910
+ currentIndex = index;
911
+ displayCurrentMedia();
912
+ });
913
+
914
+ thumbnailContainer.appendChild(thumbnail);
915
+ });
916
+ }
917
+
918
+ function goToPrevious() {
919
+ if (mediaFiles.length === 0) return;
920
+
921
+ currentIndex = (currentIndex - 1 + mediaFiles.length) % mediaFiles.length;
922
+ displayCurrentMedia();
923
+
924
+ // If slideshow is running and current media is video and skip videos is enabled
925
+ if (isSlideshowRunning && skipVideosInSlideshow && mediaFiles[currentIndex].type.startsWith('video/')) {
926
+ setTimeout(goToPrevious, 100); // Skip this video
927
+ }
928
+ }
929
+
930
+ function goToNext() {
931
+ if (mediaFiles.length === 0) return;
932
+
933
+ currentIndex = (currentIndex + 1) % mediaFiles.length;
934
+ displayCurrentMedia();
935
+
936
+ // If slideshow is running and current media is video and skip videos is enabled
937
+ if (isSlideshowRunning && skipVideosInSlideshow && mediaFiles[currentIndex].type.startsWith('video/')) {
938
+ setTimeout(goToNext, 100); // Skip this video
939
+ }
940
+ }
941
+
942
+ function zoomImage(factor) {
943
+ if (!mediaFiles[currentIndex]?.type.startsWith('image/')) return;
944
+
945
+ zoomLevel *= factor;
946
+ const imageWrapper = document.getElementById('image-wrapper');
947
+
948
+ imageWrapper.style.transform = `scale(${zoomLevel}) translate(${translateX}px, ${translateY}px)`;
949
+ }
950
+
951
+ function resetZoom() {
952
+ if (!mediaFiles[currentIndex]?.type.startsWith('image/')) return;
953
+
954
+ zoomLevel = 1;
955
+ translateX = 0;
956
+ translateY = 0;
957
+ const imageWrapper = document.getElementById('image-wrapper');
958
+
959
+ imageWrapper.style.transform = `scale(${zoomLevel}) translate(${translateX}px, ${translateY}px)`;
960
+ }
961
+
962
+ function applyImageSize() {
963
+ if (!mediaFiles[currentIndex]?.type.startsWith('image/')) return;
964
+
965
+ const size = imageSizeSelect.value;
966
+ const img = document.getElementById('current-image');
967
+
968
+ switch (size) {
969
+ case 'contain':
970
+ img.style.objectFit = 'contain';
971
+ img.style.width = 'auto';
972
+ img.style.height = 'auto';
973
+ img.style.maxWidth = '100%';
974
+ img.style.maxHeight = '100%';
975
+ break;
976
+ case 'cover':
977
+ img.style.objectFit = 'cover';
978
+ img.style.width = '100%';
979
+ img.style.height = '100%';
980
+ break;
981
+ case 'original':
982
+ img.style.objectFit = 'none';
983
+ img.style.width = 'auto';
984
+ img.style.height = 'auto';
985
+ img.style.maxWidth = 'none';
986
+ img.style.maxHeight = 'none';
987
+ break;
988
+ }
989
+
990
+ resetZoom();
991
+ }
992
+
993
+ function togglePlayPause() {
994
+ if (!mediaFiles[currentIndex]?.type.startsWith('video/')) {
995
+ if (!isSlideshowRunning) {
996
+ toggleSlideshow();
997
+ } else {
998
+ stopSlideshow();
999
+ }
1000
+ return;
1001
+ }
1002
+
1003
+ if (currentVideo.paused) {
1004
+ currentVideo.play();
1005
+ playIcon.className = 'fas fa-pause';
1006
+ playIconBottom.className = 'fas fa-pause';
1007
+ } else {
1008
+ currentVideo.pause();
1009
+ playIcon.className = 'fas fa-play';
1010
+ playIconBottom.className = 'fas fa-play';
1011
+ }
1012
+ }
1013
+
1014
+ function stopPlayback() {
1015
+ if (isSlideshowRunning) {
1016
+ stopSlideshow();
1017
+ }
1018
+
1019
+ if (mediaFiles[currentIndex]?.type.startsWith('video/')) {
1020
+ currentVideo.pause();
1021
+ currentVideo.currentTime = 0;
1022
+ playIcon.className = 'fas fa-play';
1023
+ playIconBottom.className = 'fas fa-play';
1024
+ }
1025
+ }
1026
+
1027
+ function updateVideoProgress() {
1028
+ const percent = (currentVideo.currentTime / currentVideo.duration) * 100;
1029
+ progressFill.style.width = `${percent}%`;
1030
+ }
1031
+
1032
+ function toggleSlideshow() {
1033
+ if (isSlideshowRunning) {
1034
+ stopSlideshow();
1035
+ } else {
1036
+ startSlideshow();
1037
+ }
1038
+ }
1039
+
1040
+ function startSlideshow() {
1041
+ if (mediaFiles.length === 0) return;
1042
+
1043
+ isSlideshowRunning = true;
1044
+ toggleSlideshowBtn.textContent = 'Stop Slideshow';
1045
+ toggleSlideshowBtn.classList.remove('bg-cyber-dark');
1046
+ toggleSlideshowBtn.classList.add('bg-cyber-accent', 'text-cyber-dark');
1047
+
1048
+ const speed = parseInt(slideshowSpeedSelect.value);
1049
+ slideshowInterval = setInterval(goToNext, speed);
1050
+
1051
+ showStatusMessage('Slideshow started');
1052
+ }
1053
+
1054
+ function stopSlideshow() {
1055
+ isSlideshowRunning = false;
1056
+ clearInterval(slideshowInterval);
1057
+ toggleSlideshowBtn.textContent = 'Slideshow';
1058
+ toggleSlideshowBtn.classList.remove('bg-cyber-accent', 'text-cyber-dark');
1059
+ toggleSlideshowBtn.classList.add('bg-cyber-dark');
1060
+
1061
+ showStatusMessage('Slideshow stopped');
1062
+ }
1063
+
1064
+ function toggleThumbnailSidebar() {
1065
+ thumbnailSidebar.classList.toggle('hidden');
1066
+ }
1067
+
1068
+ function handleWheelEvent(e) {
1069
+ e.preventDefault();
1070
+
1071
+ if (wheelBehavior === 'zoom' && mediaFiles[currentIndex]?.type.startsWith('image/')) {
1072
+ // Zoom with wheel
1073
+ const delta = -e.deltaY;
1074
+ const factor = delta > 0 ? 1.1 : 0.9;
1075
+ zoomImage(factor);
1076
+ } else if (wheelBehavior === 'navigate') {
1077
+ // Navigate with wheel
1078
+ if (e.deltaY > 0) {
1079
+ goToNext();
1080
+ } else {
1081
+ goToPrevious();
1082
+ }
1083
+ }
1084
+ }
1085
+
1086
+ function startDrag(e) {
1087
+ if (zoomLevel <= 1 || !mediaFiles[currentIndex]?.type.startsWith('image/')) return;
1088
+
1089
+ isDragging = true;
1090
+ startX = e.clientX - translateX;
1091
+ startY = e.clientY - translateY;
1092
+ imageContainer.style.cursor = 'grabbing';
1093
+ }
1094
+
1095
+ function dragImage(e) {
1096
+ if (!isDragging) return;
1097
+
1098
+ e.preventDefault();
1099
+ translateX = e.clientX - startX;
1100
+ translateY = e.clientY - startY;
1101
+
1102
+ const imageWrapper = document.getElementById('image-wrapper');
1103
+ imageWrapper.style.transform = `scale(${zoomLevel}) translate(${translateX}px, ${translateY}px)`;
1104
+ }
1105
+
1106
+ function endDrag() {
1107
+ isDragging = false;
1108
+ imageContainer.style.cursor = 'grab';
1109
+ }
1110
+
1111
+ function handleKeyboardShortcuts(e) {
1112
+ if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT' || e.target.tagName === 'TEXTAREA') return;
1113
+
1114
+ switch (e.key) {
1115
+ case 'ArrowLeft':
1116
+ goToPrevious();
1117
+ break;
1118
+ case 'ArrowRight':
1119
+ goToNext();
1120
+ break;
1121
+ case '+':
1122
+ case '=':
1123
+ zoomImage(1.2);
1124
+ break;
1125
+ case '-':
1126
+ case '_':
1127
+ zoomImage(0.8);
1128
+ break;
1129
+ case '0':
1130
+ resetZoom();
1131
+ break;
1132
+ case ' ':
1133
+ togglePlayPause();
1134
+ break;
1135
+ case 'ArrowUp':
1136
+ if (mediaFiles[currentIndex]?.type.startsWith('video/')) {
1137
+ currentVideo.volume = Math.min(1, currentVideo.volume + 0.1);
1138
+ volumeSlider.value = currentVideo.volume;
1139
+ }
1140
+ break;
1141
+ case 'ArrowDown':
1142
+ if (mediaFiles[currentIndex]?.type.startsWith('video/')) {
1143
+ currentVideo.volume = Math.max(0, currentVideo.volume - 0.1);
1144
+ volumeSlider.value = currentVideo.volume;
1145
+ }
1146
+ break;
1147
+ case 't':
1148
+ case 'T':
1149
+ toggleThumbnailSidebar();
1150
+ break;
1151
+ case 's':
1152
+ case 'S':
1153
+ toggleSlideshow();
1154
+ break;
1155
+ case 'Escape':
1156
+ closeSettings();
1157
+ break;
1158
+ }
1159
+ }
1160
+
1161
+ function showStatusMessage(message) {
1162
+ statusMessage.textContent = message;
1163
+ setTimeout(() => {
1164
+ statusMessage.textContent = "";
1165
+ }, 3000);
1166
+ }
1167
+
1168
+ function closeSettings() {
1169
+ settingsPanel.classList.remove('active');
1170
+ settingsOverlay.classList.remove('active');
1171
+ }
1172
+
1173
+ function saveSettings() {
1174
+ wheelBehavior = document.querySelector('input[name="wheel-behavior"]:checked').value;
1175
+ skipVideosInSlideshow = document.getElementById('skip-videos').checked;
1176
+ cyberEffectsEnabled = document.getElementById('cyber-effects').checked;
1177
+
1178
+ localStorage.setItem('wheelBehavior', wheelBehavior);
1179
+ localStorage.setItem('skipVideosInSlideshow', skipVideosInSlideshow);
1180
+ localStorage.setItem('cyberEffectsEnabled', cyberEffectsEnabled);
1181
+
1182
+ applyCyberEffects();
1183
+ closeSettings();
1184
+ showStatusMessage('Settings saved');
1185
+ }
1186
+
1187
+ function loadSettings() {
1188
+ const savedWheelBehavior = localStorage.getItem('wheelBehavior');
1189
+ const savedSkipVideos = localStorage.getItem('skipVideosInSlideshow');
1190
+ const savedCyberEffects = localStorage.getItem('cyberEffectsEnabled');
1191
+
1192
+ if (savedWheelBehavior) {
1193
+ wheelBehavior = savedWheelBehavior;
1194
+ document.querySelector(`input[name="wheel-behavior"][value="${savedWheelBehavior}"]`).checked = true;
1195
+ }
1196
+
1197
+ if (savedSkipVideos !== null) {
1198
+ skipVideosInSlideshow = savedSkipVideos === 'true';
1199
+ document.getElementById('skip-videos').checked = skipVideosInSlideshow;
1200
+ }
1201
+
1202
+ if (savedCyberEffects !== null) {
1203
+ cyberEffectsEnabled = savedCyberEffects === 'true';
1204
+ document.getElementById('cyber-effects').checked = cyberEffectsEnabled;
1205
+ }
1206
+
1207
+ applyCyberEffects();
1208
+ }
1209
+
1210
+ function applyCyberEffects() {
1211
+ if (cyberEffectsEnabled) {
1212
+ document.body.classList.add('glow');
1213
+ document.querySelectorAll('.cyber-text').forEach(el => el.classList.add('cyber-text'));
1214
+ } else {
1215
+ document.body.classList.remove('glow');
1216
+ document.querySelectorAll('.cyber-text').forEach(el => el.classList.remove('cyber-text'));
1217
+ }
1218
+ }
1219
+ });
1220
+ </script>
1221
+ <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=Freefall/media-viewer-pro" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1222
  </html>