index.html 40 KB

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