1using System; 2using System.Collections.Generic; 3using System.Drawing; 4using System.IO; 5using System.Net; 6using System.Threading; 7using System.Windows.Forms; 8using WindowCapture.Detection; 9using WindowCapture.Models; 10 11namespace WindowCapture.UI 12{ 13 /// <summary> 14 /// Dialog for displaying and downloading found media items 15 /// </summary> 16 public class MediaDownloadDialog : Form 17 { 18 private ListView listView; 19 private Button btnDownload; 20 private Button btnDownloadAll; 21 private Button btnClose; 22 private Label lblStatus; 23 private ProgressBar progressBar; 24 private ImageList imageList; 25 private List<MediaItem> mediaItems; 26 27 public MediaDownloadDialog(List<MediaItem> items) 28 { 29 mediaItems = items; 30 InitializeComponents(); 31 PopulateList(); 32 } 33 34 private void InitializeComponents() 35 { 36 Text = "Media Parser - Found " + mediaItems.Count + " item(s)"; 37 Size = new Size(700, 500); 38 MinimumSize = new Size(500, 300); 39 StartPosition = FormStartPosition.CenterScreen; 40 BackColor = Color.FromArgb(30, 30, 30); 41 ForeColor = Color.White; 42 Font = new Font("Segoe UI", 9f); 43 44 // Image list for icons 45 imageList = new ImageList(); 46 imageList.ImageSize = new Size(48, 48); 47 imageList.ColorDepth = ColorDepth.Depth32Bit; 48 49 // List view 50 listView = new ListView(); 51 listView.View = View.Details; 52 listView.FullRowSelect = true; 53 listView.MultiSelect = true; 54 listView.BackColor = Color.FromArgb(45, 45, 45); 55 listView.ForeColor = Color.White; 56 listView.BorderStyle = BorderStyle.None; 57 listView.Dock = DockStyle.Top; 58 listView.Height = 350; 59 listView.SmallImageList = imageList; 60 61 listView.Columns.Add("Type", 60); 62 listView.Columns.Add("Filename", 200); 63 listView.Columns.Add("URL", 400); 64 65 listView.DoubleClick += ListView_DoubleClick; 66 67 // Buttons panel 68 var buttonPanel = new Panel(); 69 buttonPanel.Dock = DockStyle.Bottom; 70 buttonPanel.Height = 80; 71 buttonPanel.Padding = new Padding(10); 72 73 btnDownload = CreateButton("Download Selected", 10, 10, 130); 74 btnDownload.Click += BtnDownload_Click; 75 76 btnDownloadAll = CreateButton("Download All", 150, 10, 100); 77 btnDownloadAll.Click += BtnDownloadAll_Click; 78 79 btnClose = CreateButton("Close", 580, 10, 80); 80 btnClose.Click += (s, e) => Close(); 81 82 lblStatus = new Label(); 83 lblStatus.Location = new Point(10, 45); 84 lblStatus.Size = new Size(400, 20); 85 lblStatus.ForeColor = Color.LightGray; 86 87 progressBar = new ProgressBar(); 88 progressBar.Location = new Point(10, 65); 89 progressBar.Size = new Size(650, 10); 90 progressBar.Style = ProgressBarStyle.Continuous; 91 progressBar.Visible = false; 92 93 buttonPanel.Controls.AddRange(new Control[] { btnDownload, btnDownloadAll, btnClose, lblStatus, progressBar }); 94 95 Controls.Add(listView); 96 Controls.Add(buttonPanel); 97 } 98 99 private Button CreateButton(string text, int x, int y, int width) 100 { 101 var btn = new Button(); 102 btn.Text = text; 103 btn.Location = new Point(x, y); 104 btn.Size = new Size(width, 28); 105 btn.FlatStyle = FlatStyle.Flat; 106 btn.FlatAppearance.BorderColor = Color.FromArgb(80, 80, 80); 107 btn.BackColor = Color.FromArgb(60, 60, 60); 108 btn.ForeColor = Color.White; 109 btn.Cursor = Cursors.Hand; 110 return btn; 111 } 112 113 private void PopulateList() 114 { 115 listView.Items.Clear(); 116 117 foreach (var item in mediaItems) 118 { 119 var lvi = new ListViewItem(); 120 121 // Type icon 122 string typeIcon = ""; 123 switch (item.Type) 124 { 125 case "image": typeIcon = "IMG"; break; 126 case "video": typeIcon = "VID"; break; 127 case "audio": typeIcon = "AUD"; break; 128 } 129 lvi.Text = typeIcon; 130 131 lvi.SubItems.Add(item.FileName); 132 lvi.SubItems.Add(item.Url); 133 lvi.Tag = item; 134 135 // Color by type 136 switch (item.Type) 137 { 138 case "image": lvi.ForeColor = Color.LightGreen; break; 139 case "video": lvi.ForeColor = Color.LightBlue; break; 140 case "audio": lvi.ForeColor = Color.Orange; break; 141 } 142 143 listView.Items.Add(lvi); 144 } 145 146 if (mediaItems.Count == 0) 147 { 148 lblStatus.Text = "No media found at this location"; 149 } 150 else 151 { 152 lblStatus.Text = "Double-click to preview, or select and download"; 153 } 154 } 155 156 private void ListView_DoubleClick(object sender, EventArgs e) 157 { 158 if (listView.SelectedItems.Count == 0) return; 159 160 var item = listView.SelectedItems[0].Tag as MediaItem; 161 if (item == null) return; 162 163 // Open URL in browser 164 try 165 { 166 System.Diagnostics.Process.Start(item.Url); 167 } 168 catch (Exception ex) 169 { 170 MessageBox.Show("Cannot open URL: " + ex.Message, "Error", 171 MessageBoxButtons.OK, MessageBoxIcon.Error); 172 } 173 } 174 175 private void BtnDownload_Click(object sender, EventArgs e) 176 { 177 if (listView.SelectedItems.Count == 0) 178 { 179 lblStatus.Text = "Select items to download"; 180 return; 181 } 182 183 var items = new List<MediaItem>(); 184 foreach (ListViewItem lvi in listView.SelectedItems) 185 { 186 var item = lvi.Tag as MediaItem; 187 if (item != null) items.Add(item); 188 } 189 190 DownloadItems(items); 191 } 192 193 private void BtnDownloadAll_Click(object sender, EventArgs e) 194 { 195 if (mediaItems.Count == 0) 196 { 197 lblStatus.Text = "No items to download"; 198 return; 199 } 200 201 DownloadItems(mediaItems); 202 } 203 204 private void DownloadItems(List<MediaItem> items) 205 { 206 // Ask for download folder 207 using (var fbd = new FolderBrowserDialog()) 208 { 209 fbd.Description = "Select download folder"; 210 fbd.ShowNewFolderButton = true; 211 212 // Default to Downloads folder 213 string downloads = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads"); 214 if (Directory.Exists(downloads)) 215 fbd.SelectedPath = downloads; 216 217 if (fbd.ShowDialog() != DialogResult.OK) 218 return; 219 220 string folder = fbd.SelectedPath; 221 222 // Download in background 223 btnDownload.Enabled = false; 224 btnDownloadAll.Enabled = false; 225 progressBar.Visible = true; 226 progressBar.Maximum = items.Count; 227 progressBar.Value = 0; 228 229 ThreadPool.QueueUserWorkItem(state => 230 { 231 int success = 0; 232 int failed = 0; 233 234 for (int i = 0; i < items.Count; i++) 235 { 236 var item = items[i]; 237 238 int currentIndex = i; 239 // Stop quietly if the user closed the dialog mid-download (otherwise Invoke throws on this pool thread). 240 if (IsDisposed || !IsHandleCreated) return; 241 try 242 { 243 Invoke(new Action(() => 244 { 245 lblStatus.Text = string.Format("Downloading {0}/{1}: {2}", currentIndex + 1, items.Count, item.FileName); 246 progressBar.Value = currentIndex; 247 })); 248 } 249 catch { return; } 250 251 // Generate unique filename 252 string fileName = item.FileName; 253 string savePath = Path.Combine(folder, fileName); 254 255 // Add number if exists 256 int num = 1; 257 while (File.Exists(savePath)) 258 { 259 string ext = Path.GetExtension(fileName); 260 string name = Path.GetFileNameWithoutExtension(fileName); 261 savePath = Path.Combine(folder, name + "_" + num + ext); 262 num++; 263 } 264 265 if (MediaParser.DownloadMedia(item, savePath)) 266 success++; 267 else 268 failed++; 269 } 270 271 if (IsDisposed || !IsHandleCreated) return; 272 try 273 { 274 Invoke(new Action(() => 275 { 276 progressBar.Value = items.Count; 277 lblStatus.Text = string.Format("Done! Downloaded: {0}, Failed: {1}", success, failed); 278 btnDownload.Enabled = true; 279 btnDownloadAll.Enabled = true; 280 281 if (success > 0) 282 { 283 // Open folder 284 System.Diagnostics.Process.Start("explorer.exe", folder); 285 } 286 })); 287 } 288 catch { } 289 }); 290 } 291 } 292 293 protected override void OnResize(EventArgs e) 294 { 295 base.OnResize(e); 296 if (listView != null) 297 { 298 listView.Height = Height - 130; 299 if (listView.Columns.Count >= 3) 300 { 301 listView.Columns[2].Width = Width - 300; 302 } 303 } 304 if (btnClose != null) 305 { 306 btnClose.Left = Width - 110; 307 } 308 if (progressBar != null) 309 { 310 progressBar.Width = Width - 50; 311 } 312 } 313 } 314}