index.html 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  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>GrabZilla 2.1</title>
  7. <script src="https://cdn.tailwindcss.com"></script>
  8. <link rel="stylesheet" href="styles/main.css">
  9. <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
  10. </head>
  11. <body class="bg-[#1d293d] text-white min-h-screen flex flex-col font-['Inter']">
  12. <!-- Header - macOS Title Bar Style -->
  13. <header class="bg-[#0f172b] h-[41px] flex items-center justify-center border-b border-[#314158] shrink-0 relative"
  14. role="banner" aria-label="GrabZilla application header" style="-webkit-app-region: drag;">
  15. <!-- Centered Title -->
  16. <div class="flex items-center gap-2" style="-webkit-app-region: no-drag;">
  17. <div class="bg-[#155dfc] w-6 h-6 rounded flex items-center justify-center">
  18. <img src="assets/icons/logo.svg" alt="GrabZilla Logo" width="16" height="16">
  19. </div>
  20. <h1 class="font-medium text-base text-white tracking-[-0.3125px] leading-6">GrabZilla 2.1</h1>
  21. </div>
  22. </header>
  23. <!-- Input Section - Exact Figma: 161px height -->
  24. <section class="h-[161px] border-b border-[#314158] px-4 py-4 shrink-0 flex flex-col gap-4" role="region"
  25. aria-label="Video URL input and configuration" aria-describedby="input-section-help">
  26. <div id="input-section-help" class="sr-only">
  27. Enter YouTube or Vimeo URLs to add videos to the download queue. Configure default quality and format
  28. settings.
  29. </div>
  30. <!-- URL Input Row -->
  31. <div class="flex gap-2 h-20">
  32. <!-- Textarea -->
  33. <textarea id="urlInput"
  34. class="flex-1 bg-[#314158] border border-[#45556c] rounded-lg p-3 text-sm resize-none text-[#90a1b9] placeholder-[#90a1b9] tracking-[-0.1504px]"
  35. placeholder="Paste YouTube/Vimeo URLs here (one per line)..." aria-label="YouTube and Vimeo URLs input"
  36. aria-describedby="url-help"></textarea>
  37. <div id="url-help" class="sr-only">Enter one URL per line. Supports YouTube and Vimeo links.</div>
  38. <!-- Action Buttons -->
  39. <div class="flex flex-col gap-2 w-[140px]">
  40. <button id="addVideoBtn"
  41. class="bg-[#155dfc] text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center gap-2 h-9 tracking-[-0.1504px]">
  42. <img src="assets/icons/add.svg" alt="Add" width="16" height="16">
  43. Add Video
  44. </button>
  45. <button id="importUrlsBtn"
  46. class="border border-[#45556c] text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center gap-2 h-9 tracking-[-0.1504px]">
  47. <img src="assets/icons/import.svg" alt="Import" width="16" height="16">
  48. Import URLs
  49. </button>
  50. </div>
  51. </div>
  52. <!-- Configuration Row -->
  53. <div class="flex items-center gap-4 h-8">
  54. <!-- Save Path Section -->
  55. <div class="flex items-center gap-2">
  56. <button id="savePathBtn"
  57. class="border border-[#45556c] text-white px-3 py-2 rounded-lg font-medium flex items-center gap-2 h-8 text-sm tracking-[-0.1504px]">
  58. <img src="assets/icons/folder.svg" alt="Folder" width="16" height="16">
  59. Set Save Path...
  60. </button>
  61. <div
  62. class="bg-[#314158] px-3 py-1.5 rounded h-7 flex items-center text-[#cad5e2] text-sm tracking-[-0.1504px]">
  63. <span id="savePath">C:\Users\Admin\Desktop\GrabZilla_Videos</span>
  64. </div>
  65. </div>
  66. <!-- Defaults Section -->
  67. <div class="flex items-center gap-2">
  68. <img src="assets/icons/clock.svg" alt="Clock" width="16" height="16">
  69. <span class="text-[#90a1b9] text-sm tracking-[-0.1504px]">Defaults:</span>
  70. <!-- Quality Dropdown -->
  71. <select id="defaultQuality"
  72. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-3 py-1 rounded-lg text-xs h-7 font-medium"
  73. aria-label="Default video quality">
  74. <option value="1080p">1080p</option>
  75. <option value="720p">720p</option>
  76. <option value="4K">4K</option>
  77. <option value="1440p">1440p</option>
  78. </select>
  79. <!-- Format Dropdown -->
  80. <select id="defaultFormat"
  81. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-3 py-1 rounded-lg text-xs h-7 font-medium"
  82. aria-label="Default conversion format">
  83. <option value="None">None</option>
  84. <option value="H264">H264</option>
  85. <option value="ProRes">ProRes</option>
  86. <option value="DNxHR">DNxHR</option>
  87. <option value="Audio only">Audio only</option>
  88. </select>
  89. <!-- Cookie File -->
  90. <div class="flex items-center gap-2">
  91. <span class="text-[#90a1b9] text-sm tracking-[-0.1504px]">Cookie:</span>
  92. <button id="cookieFileBtn"
  93. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-3 py-1 rounded-lg text-xs font-medium flex items-center gap-2 h-7">
  94. <img src="assets/icons/folder.svg" alt="File" width="16" height="16">
  95. Select File
  96. </button>
  97. <span id="cookieFilePath" class="text-[#90a1b9] text-xs italic max-w-[200px] truncate" title=""></span>
  98. </div>
  99. </div>
  100. </div>
  101. </section>
  102. <!-- Video List - Flex grow to fill remaining space -->
  103. <main class="flex-1 overflow-hidden" role="main" aria-label="Video download queue"
  104. aria-describedby="main-content-help">
  105. <div id="main-content-help" class="sr-only">
  106. Video download queue. Use arrow keys to navigate, Enter or Space to select videos, Delete to remove videos.
  107. </div>
  108. <!-- Table Header -->
  109. <div class="grid grid-cols-[40px_40px_1fr_120px_100px_120px_100px] gap-4 px-4 py-4 text-sm font-medium text-[#90a1b9] tracking-[-0.1504px]"
  110. role="row" aria-label="Video list column headers">
  111. <div role="columnheader" aria-label="Selection checkbox"></div>
  112. <div role="columnheader" aria-label="Drag handle"></div>
  113. <div role="columnheader">Title</div>
  114. <div role="columnheader">Duration</div>
  115. <div role="columnheader">Quality</div>
  116. <div role="columnheader">Conversion</div>
  117. <div role="columnheader">Status</div>
  118. </div>
  119. <!-- Video Items Container -->
  120. <div id="videoList" class="px-4 pt-2 pb-4 space-y-2 overflow-y-auto h-full" role="grid"
  121. aria-label="Video download queue" aria-describedby="video-list-instructions" tabindex="0">
  122. <div id="video-list-instructions" class="sr-only">
  123. Use arrow keys to navigate between videos. Press Enter or Space to select videos. Press Delete to remove
  124. videos. Press Ctrl+A to select all videos.
  125. </div>
  126. <!-- Sample Video Items - Matching Figma Design -->
  127. <!-- Video Item 1 - Ready State -->
  128. <div class="video-item grid grid-cols-[40px_40px_1fr_120px_100px_120px_100px] gap-4 items-center p-2 rounded bg-[#314158] hover:bg-[#3a4a68] transition-colors duration-200"
  129. data-video-id="video-1" role="gridcell" tabindex="0" aria-rowindex="1"
  130. aria-describedby="video-1-description">
  131. <!-- Checkbox -->
  132. <div class="flex items-center justify-center">
  133. <button
  134. class="video-checkbox w-6 h-6 rounded flex items-center justify-center hover:bg-[#45556c] transition-colors"
  135. role="checkbox" aria-checked="false" aria-label="Select Interstellar 2014 Trailer" tabindex="0">
  136. <svg width="16" height="16" viewBox="0 0 16 16" fill="none" class="text-white">
  137. <rect x="3" y="3" width="10" height="10" stroke="currentColor" stroke-width="1.5"
  138. fill="none" rx="2" />
  139. </svg>
  140. </button>
  141. </div>
  142. <!-- Drag Handle -->
  143. <div
  144. class="flex items-center justify-center text-[#90a1b9] hover:text-white cursor-grab transition-colors">
  145. <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
  146. <circle cx="4" cy="4" r="1" />
  147. <circle cx="4" cy="8" r="1" />
  148. <circle cx="4" cy="12" r="1" />
  149. <circle cx="8" cy="4" r="1" />
  150. <circle cx="8" cy="8" r="1" />
  151. <circle cx="8" cy="12" r="1" />
  152. <circle cx="12" cy="4" r="1" />
  153. <circle cx="12" cy="8" r="1" />
  154. <circle cx="12" cy="12" r="1" />
  155. </svg>
  156. </div>
  157. <!-- Video Info -->
  158. <div class="flex items-center gap-3 min-w-0">
  159. <div class="w-16 h-12 bg-[#45556c] rounded overflow-hidden flex-shrink-0">
  160. <div
  161. class="w-full h-full bg-gradient-to-br from-[#4a5568] to-[#2d3748] flex items-center justify-center">
  162. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-[#90a1b9]">
  163. <path d="M8 5V19L19 12L8 5Z" stroke="currentColor" stroke-width="2"
  164. stroke-linejoin="round" />
  165. </svg>
  166. </div>
  167. </div>
  168. <div class="min-w-0 flex-1">
  169. <div class="text-sm text-white truncate font-medium">Interstellar 2014 Trailer | 4K Ultra HD
  170. </div>
  171. </div>
  172. </div>
  173. <!-- Duration -->
  174. <div class="text-sm text-[#cad5e2] text-center">2:25</div>
  175. <!-- Quality Dropdown -->
  176. <div class="flex justify-center">
  177. <select
  178. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center"
  179. aria-label="Quality for Interstellar 2014 Trailer">
  180. <option value="4K" selected>4K</option>
  181. <option value="1440p">1440p</option>
  182. <option value="1080p">1080p</option>
  183. <option value="720p">720p</option>
  184. </select>
  185. </div>
  186. <!-- Format Dropdown -->
  187. <div class="flex justify-center">
  188. <select
  189. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center"
  190. aria-label="Format for Interstellar 2014 Trailer">
  191. <option value="None" selected>None</option>
  192. <option value="H264">H264</option>
  193. <option value="ProRes">ProRes</option>
  194. <option value="DNxHR">DNxHR</option>
  195. <option value="Audio only">Audio only</option>
  196. </select>
  197. </div>
  198. <!-- Status Badge -->
  199. <div class="flex justify-center status-column">
  200. <span class="status-badge ready" role="status" aria-live="polite"
  201. aria-label="Video ready for download">
  202. Ready
  203. </span>
  204. </div>
  205. <!-- Video Description for Screen Readers -->
  206. <div id="video-1-description" class="sr-only">
  207. Video: Interstellar 2014 Trailer | 4K Ultra HD, Duration: 2:25, Status: Ready. Press Enter or Space
  208. to select, Delete to remove.
  209. </div>
  210. </div>
  211. <!-- Video Item 2 - Downloading State -->
  212. <div class="video-item grid grid-cols-[40px_40px_1fr_120px_100px_120px_100px] gap-4 items-center p-2 rounded bg-[#314158] hover:bg-[#3a4a68] transition-colors duration-200"
  213. data-video-id="video-2">
  214. <!-- Checkbox -->
  215. <div class="flex items-center justify-center">
  216. <button
  217. class="w-6 h-6 rounded flex items-center justify-center hover:bg-[#45556c] transition-colors">
  218. <svg width="16" height="16" viewBox="0 0 16 16" fill="none" class="text-white">
  219. <rect x="3" y="3" width="10" height="10" stroke="currentColor" stroke-width="1.5"
  220. fill="none" rx="2" />
  221. </svg>
  222. </button>
  223. </div>
  224. <!-- Drag Handle -->
  225. <div
  226. class="flex items-center justify-center text-[#90a1b9] hover:text-white cursor-grab transition-colors">
  227. <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
  228. <circle cx="4" cy="4" r="1" />
  229. <circle cx="4" cy="8" r="1" />
  230. <circle cx="4" cy="12" r="1" />
  231. <circle cx="8" cy="4" r="1" />
  232. <circle cx="8" cy="8" r="1" />
  233. <circle cx="8" cy="12" r="1" />
  234. <circle cx="12" cy="4" r="1" />
  235. <circle cx="12" cy="8" r="1" />
  236. <circle cx="12" cy="12" r="1" />
  237. </svg>
  238. </div>
  239. <!-- Video Info -->
  240. <div class="flex items-center gap-3 min-w-0">
  241. <div class="w-16 h-12 bg-[#45556c] rounded overflow-hidden flex-shrink-0">
  242. <div
  243. class="w-full h-full bg-gradient-to-br from-[#4a5568] to-[#2d3748] flex items-center justify-center">
  244. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-[#90a1b9]">
  245. <path d="M8 5V19L19 12L8 5Z" stroke="currentColor" stroke-width="2"
  246. stroke-linejoin="round" />
  247. </svg>
  248. </div>
  249. </div>
  250. <div class="min-w-0 flex-1">
  251. <div class="text-sm text-white truncate font-medium">Greenland (2020) 4K Trailer | Upscaled
  252. Trailers</div>
  253. </div>
  254. </div>
  255. <!-- Duration -->
  256. <div class="text-sm text-[#cad5e2] text-center">2:30</div>
  257. <!-- Quality Dropdown -->
  258. <div class="flex justify-center">
  259. <select
  260. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center">
  261. <option value="1080p" selected>1080p</option>
  262. <option value="4K">4K</option>
  263. <option value="1440p">1440p</option>
  264. <option value="720p">720p</option>
  265. </select>
  266. </div>
  267. <!-- Format Dropdown -->
  268. <div class="flex justify-center">
  269. <select
  270. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center">
  271. <option value="ProRes" selected>ProRes</option>
  272. <option value="None">None</option>
  273. <option value="H264">H264</option>
  274. <option value="DNxHR">DNxHR</option>
  275. <option value="Audio only">Audio only</option>
  276. </select>
  277. </div>
  278. <!-- Status Badge with Integrated Progress -->
  279. <div class="flex justify-center status-column">
  280. <span class="status-badge downloading" role="status" aria-live="polite" aria-label="Downloading 65%"
  281. data-progress="65">
  282. Downloading 65%
  283. </span>
  284. </div>
  285. </div>
  286. <!-- Video Item 3 - Converting State -->
  287. <div class="video-item grid grid-cols-[40px_40px_1fr_120px_100px_120px_100px] gap-4 items-center p-2 rounded bg-[#314158] hover:bg-[#3a4a68] transition-colors duration-200"
  288. data-video-id="video-3">
  289. <!-- Checkbox -->
  290. <div class="flex items-center justify-center">
  291. <button
  292. class="w-6 h-6 rounded flex items-center justify-center hover:bg-[#45556c] transition-colors">
  293. <svg width="16" height="16" viewBox="0 0 16 16" fill="none" class="text-white">
  294. <rect x="3" y="3" width="10" height="10" stroke="currentColor" stroke-width="1.5"
  295. fill="none" rx="2" />
  296. </svg>
  297. </button>
  298. </div>
  299. <!-- Drag Handle -->
  300. <div
  301. class="flex items-center justify-center text-[#90a1b9] hover:text-white cursor-grab transition-colors">
  302. <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
  303. <circle cx="4" cy="4" r="1" />
  304. <circle cx="4" cy="8" r="1" />
  305. <circle cx="4" cy="12" r="1" />
  306. <circle cx="8" cy="4" r="1" />
  307. <circle cx="8" cy="8" r="1" />
  308. <circle cx="8" cy="12" r="1" />
  309. <circle cx="12" cy="4" r="1" />
  310. <circle cx="12" cy="8" r="1" />
  311. <circle cx="12" cy="12" r="1" />
  312. </svg>
  313. </div>
  314. <!-- Video Info -->
  315. <div class="flex items-center gap-3 min-w-0">
  316. <div class="w-16 h-12 bg-[#45556c] rounded overflow-hidden flex-shrink-0">
  317. <div
  318. class="w-full h-full bg-gradient-to-br from-[#4a5568] to-[#2d3748] flex items-center justify-center">
  319. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-[#90a1b9]">
  320. <path d="M8 5V19L19 12L8 5Z" stroke="currentColor" stroke-width="2"
  321. stroke-linejoin="round" />
  322. </svg>
  323. </div>
  324. </div>
  325. <div class="min-w-0 flex-1">
  326. <div class="text-sm text-white truncate font-medium">GREENLAND Trailer German Deutsch (2020)
  327. </div>
  328. </div>
  329. </div>
  330. <!-- Duration -->
  331. <div class="text-sm text-[#cad5e2] text-center">2:38</div>
  332. <!-- Quality Dropdown -->
  333. <div class="flex justify-center">
  334. <select
  335. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center">
  336. <option value="1080p" selected>1080p</option>
  337. <option value="4K">4K</option>
  338. <option value="1440p">1440p</option>
  339. <option value="720p">720p</option>
  340. </select>
  341. </div>
  342. <!-- Format Dropdown -->
  343. <div class="flex justify-center">
  344. <select
  345. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center">
  346. <option value="H264" selected>H264</option>
  347. <option value="None">None</option>
  348. <option value="ProRes">ProRes</option>
  349. <option value="DNxHR">DNxHR</option>
  350. <option value="Audio only">Audio only</option>
  351. </select>
  352. </div>
  353. <!-- Status Badge with Integrated Progress -->
  354. <div class="flex justify-center status-column">
  355. <span class="status-badge converting" role="status" aria-live="polite" aria-label="Converting 42%"
  356. data-progress="42">
  357. Converting 42%
  358. </span>
  359. </div>
  360. </div>
  361. <!-- Video Item 4 - Completed State -->
  362. <div class="video-item grid grid-cols-[40px_40px_1fr_120px_100px_120px_100px] gap-4 items-center p-2 rounded bg-[#314158] hover:bg-[#3a4a68] transition-colors duration-200"
  363. data-video-id="video-4">
  364. <!-- Checkbox -->
  365. <div class="flex items-center justify-center">
  366. <button
  367. class="w-6 h-6 rounded flex items-center justify-center hover:bg-[#45556c] transition-colors">
  368. <svg width="16" height="16" viewBox="0 0 16 16" fill="none" class="text-white">
  369. <rect x="3" y="3" width="10" height="10" stroke="currentColor" stroke-width="1.5"
  370. fill="none" rx="2" />
  371. </svg>
  372. </button>
  373. </div>
  374. <!-- Drag Handle -->
  375. <div
  376. class="flex items-center justify-center text-[#90a1b9] hover:text-white cursor-grab transition-colors">
  377. <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
  378. <circle cx="4" cy="4" r="1" />
  379. <circle cx="4" cy="8" r="1" />
  380. <circle cx="4" cy="12" r="1" />
  381. <circle cx="8" cy="4" r="1" />
  382. <circle cx="8" cy="8" r="1" />
  383. <circle cx="8" cy="12" r="1" />
  384. <circle cx="12" cy="4" r="1" />
  385. <circle cx="12" cy="8" r="1" />
  386. <circle cx="12" cy="12" r="1" />
  387. </svg>
  388. </div>
  389. <!-- Video Info -->
  390. <div class="flex items-center gap-3 min-w-0">
  391. <div class="w-16 h-12 bg-[#45556c] rounded overflow-hidden flex-shrink-0">
  392. <div
  393. class="w-full h-full bg-gradient-to-br from-[#4a5568] to-[#2d3748] flex items-center justify-center">
  394. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-[#90a1b9]">
  395. <path d="M8 5V19L19 12L8 5Z" stroke="currentColor" stroke-width="2"
  396. stroke-linejoin="round" />
  397. </svg>
  398. </div>
  399. </div>
  400. <div class="min-w-0 flex-1">
  401. <div class="text-sm text-white truncate font-medium">A Quiet Place (2018) - Official Trailer -
  402. Paramount Pictures</div>
  403. </div>
  404. </div>
  405. <!-- Duration -->
  406. <div class="text-sm text-[#cad5e2] text-center">1:56</div>
  407. <!-- Quality Dropdown -->
  408. <div class="flex justify-center">
  409. <select
  410. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center">
  411. <option value="720p" selected>720p</option>
  412. <option value="4K">4K</option>
  413. <option value="1440p">1440p</option>
  414. <option value="1080p">1080p</option>
  415. </select>
  416. </div>
  417. <!-- Format Dropdown -->
  418. <div class="flex justify-center">
  419. <select
  420. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center">
  421. <option value="Audio only" selected>Audio only</option>
  422. <option value="None">None</option>
  423. <option value="H264">H264</option>
  424. <option value="ProRes">ProRes</option>
  425. <option value="DNxHR">DNxHR</option>
  426. </select>
  427. </div>
  428. <!-- Status Badge -->
  429. <div class="flex justify-center status-column">
  430. <span class="status-badge completed" role="status" aria-live="polite"
  431. aria-label="Video download completed">
  432. Completed
  433. </span>
  434. </div>
  435. </div>
  436. <!-- Video Item 5 - Error State -->
  437. <div class="video-item grid grid-cols-[40px_40px_1fr_120px_100px_120px_100px] gap-4 items-center p-2 rounded bg-[#314158] hover:bg-[#3a4a68] transition-colors duration-200"
  438. data-video-id="video-5">
  439. <!-- Checkbox -->
  440. <div class="flex items-center justify-center">
  441. <button
  442. class="w-6 h-6 rounded flex items-center justify-center hover:bg-[#45556c] transition-colors">
  443. <svg width="16" height="16" viewBox="0 0 16 16" fill="none" class="text-white">
  444. <rect x="3" y="3" width="10" height="10" stroke="currentColor" stroke-width="1.5"
  445. fill="none" rx="2" />
  446. </svg>
  447. </button>
  448. </div>
  449. <!-- Drag Handle -->
  450. <div
  451. class="flex items-center justify-center text-[#90a1b9] hover:text-white cursor-grab transition-colors">
  452. <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
  453. <circle cx="4" cy="4" r="1" />
  454. <circle cx="4" cy="8" r="1" />
  455. <circle cx="4" cy="12" r="1" />
  456. <circle cx="8" cy="4" r="1" />
  457. <circle cx="8" cy="8" r="1" />
  458. <circle cx="8" cy="12" r="1" />
  459. <circle cx="12" cy="4" r="1" />
  460. <circle cx="12" cy="8" r="1" />
  461. <circle cx="12" cy="12" r="1" />
  462. </svg>
  463. </div>
  464. <!-- Video Info -->
  465. <div class="flex items-center gap-3 min-w-0">
  466. <div class="w-16 h-12 bg-[#45556c] rounded overflow-hidden flex-shrink-0">
  467. <div
  468. class="w-full h-full bg-gradient-to-br from-[#4a5568] to-[#2d3748] flex items-center justify-center">
  469. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-[#90a1b9]">
  470. <path d="M8 5V19L19 12L8 5Z" stroke="currentColor" stroke-width="2"
  471. stroke-linejoin="round" />
  472. </svg>
  473. </div>
  474. </div>
  475. <div class="min-w-0 flex-1">
  476. <div class="text-sm text-white truncate font-medium">Blade Runner 2049 - Official Trailer -
  477. Warner Bros. Pictures</div>
  478. </div>
  479. </div>
  480. <!-- Duration -->
  481. <div class="text-sm text-[#cad5e2] text-center">3:47</div>
  482. <!-- Quality Dropdown -->
  483. <div class="flex justify-center">
  484. <select
  485. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center">
  486. <option value="4K" selected>4K</option>
  487. <option value="1440p">1440p</option>
  488. <option value="1080p">1080p</option>
  489. <option value="720p">720p</option>
  490. </select>
  491. </div>
  492. <!-- Format Dropdown -->
  493. <div class="flex justify-center">
  494. <select
  495. class="bg-[#314158] border border-[#45556c] text-[#cad5e2] px-2 py-1 rounded text-xs font-medium min-w-0 w-full text-center">
  496. <option value="H264" selected>H264</option>
  497. <option value="None">None</option>
  498. <option value="ProRes">ProRes</option>
  499. <option value="DNxHR">DNxHR</option>
  500. <option value="Audio only">Audio only</option>
  501. </select>
  502. </div>
  503. <!-- Status Badge -->
  504. <div class="flex justify-center status-column">
  505. <span class="status-badge error" role="status" aria-live="polite"
  506. aria-label="Video download failed">
  507. Error
  508. </span>
  509. </div>
  510. </div>
  511. </div>
  512. </main>
  513. <!-- Control Panel - Exact Figma: 93px height -->
  514. <footer class="h-[93px] border-t border-[#314158] px-4 py-4 shrink-0 flex flex-col gap-2" role="contentinfo"
  515. aria-label="Download controls and actions" aria-describedby="control-panel-help">
  516. <div id="control-panel-help" class="sr-only">
  517. Control panel with actions for managing downloads. Use Ctrl+D to start downloads quickly.
  518. </div>
  519. <!-- Button Row -->
  520. <div class="flex items-center justify-between h-9">
  521. <div class="flex items-center gap-2">
  522. <button id="clearListBtn"
  523. class="border border-[#45556c] text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center gap-2 h-9 tracking-[-0.1504px]"
  524. aria-label="Clear all videos from list">
  525. <img src="assets/icons/trash.svg" alt="" width="16" height="16" loading="lazy">
  526. Clear List
  527. </button>
  528. <button id="updateDepsBtn"
  529. class="border border-[#45556c] text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center gap-2 h-9 tracking-[-0.1504px]"
  530. aria-label="Check for updates to yt-dlp and ffmpeg">
  531. <img src="assets/icons/refresh.svg" alt="" width="16" height="16" loading="lazy">
  532. Check for Updates
  533. </button>
  534. <button id="cancelDownloadsBtn"
  535. class="bg-[#e7000b] text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center gap-2 h-9 tracking-[-0.1504px]"
  536. aria-label="Cancel all active downloads">
  537. <img src="assets/icons/close.svg" alt="Cancel" width="16" height="16">
  538. Cancel Downloads
  539. </button>
  540. </div>
  541. <button id="downloadVideosBtn"
  542. class="bg-[#00a63e] text-white px-6 py-2.5 rounded-lg text-sm font-medium flex items-center gap-2 h-9 tracking-[-0.1504px]">
  543. <img src="assets/icons/download.svg" alt="Download" width="16" height="16">
  544. Download Videos
  545. </button>
  546. </div>
  547. <!-- Status Message & Binary Versions -->
  548. <div class="flex items-center justify-between text-xs text-[#90a1b9] h-6 px-4">
  549. <!-- Left: Status Message -->
  550. <span id="statusMessage" role="status" aria-live="polite">Ready to download videos</span>
  551. <!-- Right: Binary Versions -->
  552. <div id="binaryVersions" class="flex items-center gap-4">
  553. <div id="ytdlpVersion" class="flex items-center gap-2">
  554. <span class="font-medium text-[#cad5e2]">yt-dlp:</span>
  555. <span id="ytdlpVersionNumber">--</span>
  556. <span id="ytdlpUpdateBadge" class="hidden update-badge" title="Update available">●</span>
  557. </div>
  558. <div id="ffmpegVersion" class="flex items-center gap-2">
  559. <span class="font-medium text-[#cad5e2]">ffmpeg:</span>
  560. <span id="ffmpegVersionNumber">--</span>
  561. </div>
  562. <span id="lastUpdateCheck" class="text-[#62748e] text-[10px]" title="Last update check">--</span>
  563. </div>
  564. </div>
  565. </footer>
  566. <!-- Load modular scripts in dependency order -->
  567. <script>
  568. // Track script loading
  569. window.scriptLoadErrors = [];
  570. function loadScript(src, callback) {
  571. const script = document.createElement('script');
  572. script.src = src;
  573. script.onload = () => {
  574. console.log(`✓ Loaded: ${src}`);
  575. if (callback) callback();
  576. };
  577. script.onerror = () => {
  578. console.error(`✗ Failed to load: ${src}`);
  579. window.scriptLoadErrors.push(src);
  580. if (callback) callback();
  581. };
  582. document.head.appendChild(script);
  583. }
  584. // Load modular scripts in correct dependency order
  585. loadScript('scripts/utils/config.js', () => {
  586. loadScript('scripts/utils/url-validator.js', () => {
  587. loadScript('scripts/core/event-bus.js', () => {
  588. loadScript('scripts/models/Video.js', () => {
  589. loadScript('scripts/models/AppState.js', () => {
  590. loadScript('scripts/utils/error-handler.js', () => {
  591. loadScript('scripts/utils/desktop-notifications.js', () => {
  592. loadScript('scripts/utils/live-region-manager.js', () => {
  593. loadScript('scripts/utils/accessibility-manager.js', () => {
  594. loadScript('scripts/utils/keyboard-navigation.js', () => {
  595. loadScript('scripts/utils/ipc-integration.js', () => {
  596. loadScript('scripts/services/metadata-service.js', () => {
  597. loadScript('scripts/utils/enhanced-download-methods.js', () => {
  598. loadScript('scripts/app.js', () => {
  599. loadScript('scripts/utils/download-integration-patch.js', () => {
  600. console.log('✅ All modular scripts loaded successfully');
  601. if (window.scriptLoadErrors.length > 0) {
  602. console.warn('⚠️ Some scripts failed to load:', window.scriptLoadErrors);
  603. }
  604. // Initialize app after all scripts have loaded
  605. if (typeof window.initializeGrabZilla === 'function') {
  606. console.log('🚀 Initializing GrabZilla app...');
  607. window.initializeGrabZilla();
  608. } else {
  609. console.error('❌ initializeGrabZilla function not found');
  610. }
  611. });
  612. });
  613. });
  614. });
  615. });
  616. });
  617. });
  618. });
  619. });
  620. });
  621. });
  622. });
  623. });
  624. });
  625. });
  626. </script>
  627. <!-- Debug script -->
  628. <script>
  629. // Debug logging
  630. console.log('All scripts loaded');
  631. // Check if buttons exist when DOM is ready
  632. document.addEventListener('DOMContentLoaded', () => {
  633. console.log('DOM Content Loaded - checking buttons...');
  634. const buttons = ['addVideoBtn', 'importUrlsBtn', 'savePathBtn', 'cookieFileBtn'];
  635. buttons.forEach(id => {
  636. const btn = document.getElementById(id);
  637. console.log(`Button ${id}:`, btn ? 'FOUND' : 'NOT FOUND');
  638. });
  639. // Check if app was initialized and provide fallback
  640. setTimeout(() => {
  641. console.log('App instance:', window.app ? 'EXISTS' : 'NOT FOUND');
  642. console.log('Script load errors:', window.scriptLoadErrors || 'none');
  643. if (window.app) {
  644. console.log('App state:', window.app.state);
  645. console.log('App initialized successfully');
  646. } else {
  647. console.log('App not initialized, setting up fallback button listeners...');
  648. // Create a minimal app-like object for basic functionality
  649. window.fallbackApp = {
  650. handleAddVideo: function () {
  651. const urlInput = document.getElementById('urlInput');
  652. const inputText = urlInput ? urlInput.value.trim() : '';
  653. if (!inputText) {
  654. alert('Please enter a URL');
  655. return;
  656. }
  657. console.log('Processing URLs:', inputText);
  658. alert(`Would add video(s): ${inputText}`);
  659. if (urlInput) urlInput.value = '';
  660. },
  661. handleImportUrls: function () {
  662. alert('Import URLs functionality (requires Electron)');
  663. },
  664. handleSelectSavePath: function () {
  665. alert('Save path selection (requires Electron)');
  666. },
  667. handleSelectCookieFile: function () {
  668. alert('Cookie file selection (requires Electron)');
  669. }
  670. };
  671. // Attach fallback event listeners
  672. const addVideoBtn = document.getElementById('addVideoBtn');
  673. if (addVideoBtn) {
  674. addVideoBtn.addEventListener('click', window.fallbackApp.handleAddVideo);
  675. console.log('✓ Fallback listener attached to Add Video button');
  676. }
  677. const importUrlsBtn = document.getElementById('importUrlsBtn');
  678. if (importUrlsBtn) {
  679. importUrlsBtn.addEventListener('click', window.fallbackApp.handleImportUrls);
  680. console.log('✓ Fallback listener attached to Import URLs button');
  681. }
  682. const savePathBtn = document.getElementById('savePathBtn');
  683. if (savePathBtn) {
  684. savePathBtn.addEventListener('click', window.fallbackApp.handleSelectSavePath);
  685. console.log('✓ Fallback listener attached to Save Path button');
  686. }
  687. const cookieFileBtn = document.getElementById('cookieFileBtn');
  688. if (cookieFileBtn) {
  689. cookieFileBtn.addEventListener('click', window.fallbackApp.handleSelectCookieFile);
  690. console.log('✓ Fallback listener attached to Cookie File button');
  691. }
  692. console.log('Fallback initialization complete');
  693. }
  694. }, 3000);
  695. });
  696. // Catch any errors
  697. window.addEventListener('error', (e) => {
  698. console.error('JavaScript Error:', e.error);
  699. console.error('File:', e.filename, 'Line:', e.lineno);
  700. });
  701. </script>
  702. </body>
  703. </html>