public SubdirSelector(DownloadDBModel dbm) { InitializeComponent(); Titles = new List <string>(); var comp = new Strings.NaturalComparer(); var folders = Directory.GetDirectories(dbm.Directory).ToList(); Title = dbm.ShortInfo; superpath = dbm.Directory; folders.Sort((x, y) => comp.Compare(x, y)); folders.ForEach(x => Titles.Add(Path.GetFileName(x))); BindingContext = this; }
public DownloadElement(DownloadDBModel dbm) { InitializeComponent(); Commands.SetTap(Body, new Command(async() => { await(Application.Current.MainPage as MainPage).NaviInstance.PushAsync(new DownloadInfoPage(dbm)); })); Spinner.IsVisible = false; if (!string.IsNullOrWhiteSpace(dbm.Url) && (dbm.Url.StartsWith("http://") || dbm.Url.StartsWith("https://"))) { SetupFavicon(dbm.Url); } if (!string.IsNullOrWhiteSpace(dbm.ShortInfo)) { Info.Text = dbm.ShortInfo; } else { Info.Text = dbm.Url; } ProgressText.IsVisible = true; ProgressText.Text = "날짜"; ProgressProgressText.IsVisible = true; ProgressProgressText.Text = dbm.StartsTime.ToString(); switch (dbm.State) { case DownloadDBState.Aborted: Status.Text = "다운로드 취소됨"; break; case DownloadDBState.Downloaded: Status.Text = "다운로드됨"; break; case DownloadDBState.ErrorOccured: Status.Text = "다운로드 중 오류발생"; break; case DownloadDBState.Downloading: Status.Text = "다운로드 중단됨"; break; case DownloadDBState.Forbidden: Status.Text = "다운로드 금지됨"; break; } if (!string.IsNullOrWhiteSpace(dbm.ThumbnailCahce)) { Task.Run(() => { Thread.Sleep(500); Device.BeginInvokeOnMainThread(() => { var thumbnail = dbm.ThumbnailCahce; Thumbnail.HeightRequest = Height - 8; Thumbnail.IsVisible = true; Thumbnail.Source = thumbnail; }); }); } }
public DownloadElement(string url) { InitializeComponent(); DownloadInfo.DownloadStarts = DateTime.Now; Info.Text = url; int hitomi_id = 0; if (int.TryParse(url, out hitomi_id)) { url = "https://hitomi.la/galleries/" + url + ".html"; } var dbm = new DownloadDBModel(); dbm.Url = url; dbm.StartsTime = DownloadInfo.DownloadStarts; dbm.State = DownloadDBState.Downloading; DownloadDBManager.Instance.Add(dbm); Commands.SetTap(Body, new Command(async() => { await(Application.Current.MainPage as MainPage).NaviInstance.PushAsync(new DownloadInfoPage(dbm)); })); if (!url.StartsWith("http://") && !url.StartsWith("https://")) { Status.Text = "옳바른 URL이 아닙니다!"; Status.TextColor = Color.Red; Spinner.IsVisible = false; dbm.State = DownloadDBState.ErrorOccured; DownloadDBManager.Instance.Add(dbm); return; } SetupFavicon(url); Task.Run(() => { var extractor = ExtractorManager.Instance.GetExtractor(url); if (extractor == null) { Device.BeginInvokeOnMainThread(() => { Status.Text = "적절한 다운로드작업을 찾을 수 없습니다!"; Status.TextColor = Color.Red; Spinner.IsVisible = false; }); dbm.State = DownloadDBState.ErrorOccured; DownloadDBManager.Instance.Update(dbm); return; } if (extractor.IsForbidden) { Device.BeginInvokeOnMainThread(() => { Status.Text = "정책상 금지된 작업입니다."; Status.TextColor = Color.Red; Spinner.IsVisible = false; }); dbm.State = DownloadDBState.Forbidden; DownloadDBManager.Instance.Update(dbm); return; } WAIT_ANOTHER_TASKS: if (DownloadAvailable == 4) { Device.BeginInvokeOnMainThread(() => { Status.Text = $"다른 작업이 끝나길 기다리는 중 입니다..."; }); while (DownloadAvailable >= 4) { Thread.Sleep(1000); } } if (Interlocked.Increment(ref DownloadAvailable) > 4) { goto WAIT_ANOTHER_TASKS; } Device.BeginInvokeOnMainThread(() => { Info.Text = extractor.GetType().Name.Replace("Extractor", "") + " (" + "/" + string.Join("/", url.Split('/').Skip(3)) + ")"; dbm.ShortInfo = Info.Text; DownloadDBManager.Instance.Update(dbm); Status.Text = "다운로드 정보를 추출 중 입니다..."; }); var option = extractor.RecommendOption(url); long extracting_progress_max = 0; long extracting_cumulative_count = 0; option.ProgressMax = (count) => { extracting_progress_max = count; Device.BeginInvokeOnMainThread(() => { ProgressProgressText.IsVisible = false; Progress.IsVisible = true; }); }; option.PostStatus = (count) => { var val = Interlocked.Add(ref extracting_cumulative_count, count); Device.BeginInvokeOnMainThread(() => { if (extracting_progress_max != 0) { Progress.Progress = val / (double)extracting_progress_max; Status.Text = $"추출중...[{val}/{extracting_progress_max}]"; } else { Status.Text = $"추출중...[{val}개 항목 추출됨]"; } }); }; option.SimpleInfoCallback = (info) => { Device.BeginInvokeOnMainThread(() => { Info.Text = $"{info}"; dbm.ShortInfo = info; DownloadDBManager.Instance.Update(dbm); }); }; option.ThumbnailCallback = (thumbnail) => { Task.Run(async() => { var ttask = NetTask.MakeDefault(thumbnail.Url); ttask.Priority = new NetPriority { Type = NetPriorityType.Trivial }; ttask.Filename = Path.Combine(AppProvider.ApplicationPath, (url + "*thumbnail" + dbm.Id).GetHashMD5() + Path.GetExtension(thumbnail.Filename)); ttask.Headers = thumbnail.Headers; ttask.Referer = thumbnail.Referer; ttask.Cookie = thumbnail.Cookie; ttask.Accept = thumbnail.Accept; ttask.UserAgent = thumbnail.UserAgent; dbm.ThumbnailCahce = ttask.Filename; await NetTools.DownloadFileAsync(ttask); DownloadDBManager.Instance.Update(dbm); Device.BeginInvokeOnMainThread(() => { Thumbnail.HeightRequest = Height - 8; Thumbnail.IsVisible = true; Thumbnail.Source = ttask.Filename; }); }); }; (List <NetTask>, ExtractedInfo)tasks; try { tasks = extractor.Extract(url, option); } catch (Exception e) { Logs.Instance.PushError(e.Message); Logs.Instance.PushError(e.StackTrace); Device.BeginInvokeOnMainThread(() => { ProgressProgressText.IsVisible = true; ProgressProgressText.Text = ""; ProgressText.Text = ""; Progress.IsVisible = false; Spinner.IsVisible = false; Status.Text = "추출 작업 중 오류가 발생했습니다 :(\n" + e.Message; Status.TextColor = Color.Red; }); Interlocked.Decrement(ref DownloadAvailable); dbm.State = DownloadDBState.ErrorOccured; DownloadDBManager.Instance.Update(dbm); return; } if (tasks.Item1 == null) { Device.BeginInvokeOnMainThread(() => { ProgressProgressText.IsVisible = true; ProgressProgressText.Text = ""; ProgressText.Text = ""; Progress.IsVisible = false; Spinner.IsVisible = false; Status.Text = "다운로드할 내용이 없습니다 :("; }); Interlocked.Decrement(ref DownloadAvailable); dbm.State = DownloadDBState.ErrorOccured; DownloadDBManager.Instance.Update(dbm); return; } if (tasks.Item2 != null) { ExtractedInfo = tasks.Item2; CacheManager.Instance.Append(url + "*info" + dbm.Id, ExtractedInfo); dbm.InfoCache = url + "*info" + dbm.Id; DownloadDBManager.Instance.Update(dbm); } var format = extractor.RecommendFormat(option); Device.BeginInvokeOnMainThread(() => { Spinner.IsVisible = false; Status.Text = "다운로드 중..."; ProgressProgressText.IsVisible = false; Progress.IsVisible = true; }); int download_count = 0; long download_bytes = 0; long download_1s = 0; int task_count = AppProvider.Scheduler.LatestPriority != null ? AppProvider.Scheduler.LatestPriority.TaskPriority : 0; int post_process_count = 0; int post_process_progress = 0; bool canceled = false; if (tasks.Item1.Count > 0) { var hash_set = new HashSet <string>(); tasks.Item1.ForEach(x => hash_set.Add(Path.GetDirectoryName(Path.Combine("/", x.Format.Formatting(format))))); if (hash_set.Count == 1) { dbm.Directory = Path.GetDirectoryName(Path.Combine(Settings.Instance.Model.SuperPath, tasks.Item1[0].Format.Formatting(format))); } else { dbm.Directory = Path.GetDirectoryName(Path.GetDirectoryName(Path.Combine(Settings.Instance.Model.SuperPath, tasks.Item1[0].Format.Formatting(format)))); } dbm.CountOfFiles = tasks.Item1.Count; DownloadDBManager.Instance.Update(dbm); } tasks.Item1.ForEach(task => { task.Priority.TaskPriority = task_count++; task.Filename = Path.Combine(Settings.Instance.Model.SuperPath, task.Format.Formatting(format)); if (!Directory.Exists(Path.GetDirectoryName(task.Filename))) { Directory.CreateDirectory(Path.GetDirectoryName(task.Filename)); } task.DownloadCallback = (sz) => { Interlocked.Add(ref download_1s, sz); Interlocked.Add(ref download_bytes, sz); }; task.CompleteCallback = () => { var cur = Interlocked.Increment(ref download_count); Device.BeginInvokeOnMainThread(() => { Progress.Progress = cur / (double)tasks.Item1.Count; }); }; task.CancleCallback = () => { if (!canceled) { dbm.State = DownloadDBState.Aborted; DownloadDBManager.Instance.Update(dbm); } canceled = true; }; task.Cancel = CancelSource.Token; if (task.PostProcess != null) { task.StartPostprocessorCallback = () => { Interlocked.Increment(ref post_process_count); }; task.PostProcess.CompletePostprocessor = (index) => { Interlocked.Increment(ref post_process_progress); }; } AppProvider.Scheduler.Add(task); }); while (tasks.Item1.Count != download_count && !canceled) { Thread.Sleep(1000); Device.BeginInvokeOnMainThread(() => { Status.Text = $"[{download_count}/{tasks.Item1.Count}] ({convert_bytes2string(download_1s)}/S {convert_bytes2string(download_bytes)})"; Interlocked.Exchange(ref download_1s, 0); }); } Interlocked.Decrement(ref DownloadAvailable); dbm.State = DownloadDBState.Downloaded; dbm.EndsTime = DateTime.Now; dbm.SizeOfContents = download_bytes; DownloadDBManager.Instance.Update(dbm); while (post_process_progress != post_process_count && !canceled) { Device.BeginInvokeOnMainThread(() => { Status.Text = $"후처리 작업 중...[{post_process_progress}/{post_process_count}]"; Progress.Progress = post_process_progress / (double)post_process_count; }); Thread.Sleep(1000); } if (!canceled) { Device.BeginInvokeOnMainThread(() => { Status.Text = "다운로드 완료"; ProgressProgressText.IsVisible = true; ProgressProgressText.Text = ""; ProgressText.Text = ""; Progress.IsVisible = false; Plugin.XSnack.CrossXSnack.Current.ShowMessage(Info.Text + " 항목의 다운로드가 완료되었습니다."); }); } else { Device.BeginInvokeOnMainThread(() => { Status.Text = "다운로드 취소됨"; ProgressProgressText.IsVisible = true; ProgressProgressText.Text = ""; ProgressText.Text = ""; Progress.IsVisible = false; Plugin.XSnack.CrossXSnack.Current.ShowMessage(Info.Text + " 항목의 다운로드가 취소되었습니다."); }); } DownloadInfo.DownloadEnds = DateTime.Now; }); }
public DownloadInfoPage(DownloadDBModel dbm) { InitializeComponent(); DBM = dbm; if (!string.IsNullOrWhiteSpace(dbm.ShortInfo)) { Information.Text = dbm.ShortInfo; } else { Information.Text = dbm.Url; } var model = ExtractorManager.Instance.GetExtractor(dbm.Url); if (model != null) { Type.Text = model.GetType().Name.Replace("Extractor", " 추출기"); } else { Type.Text = "찾을 수 없음"; Type.TextColor = Color.Red; } Date.Text = dbm.StartsTime.ToString(); switch (dbm.State) { case DownloadDBState.Aborted: State.Text = "다운로드 취소됨"; State.TextColor = Color.Orange; break; case DownloadDBState.Downloaded: State.Text = "다운로드됨"; break; case DownloadDBState.ErrorOccured: State.Text = "다운로드 중 오류가 발생함"; State.TextColor = Color.Red; break; case DownloadDBState.Forbidden: State.Text = "다운로드 금지됨"; State.TextColor = Color.Red; break; case DownloadDBState.Downloading: State.Text = "다운로드 도중 중단됨"; State.TextColor = Color.Orange; break; } Capacity.Text = $"{dbm.CountOfFiles}개 항목 [{DownloadElement.convert_bytes2string(dbm.SizeOfContents)}]"; if (!string.IsNullOrWhiteSpace(dbm.Directory)) { Witch.Text = dbm.Directory; } else { Witch.Text = "?"; } if (!string.IsNullOrWhiteSpace(dbm.InfoCache)) { if (CacheManager.Instance.Exists(dbm.InfoCache)) { var ss = CacheManager.Instance.Find(dbm.InfoCache); var info = JToken.Parse(CacheManager.Instance.Find(dbm.InfoCache))["Type"].ToObject <ExtractedInfo.ExtractedType>(); switch (info) { case ExtractedInfo.ExtractedType.WorksComic: Genre.Text = "만화"; break; case ExtractedInfo.ExtractedType.Group: case ExtractedInfo.ExtractedType.UserArtist: Genre.Text = "일러스트 및 사진"; break; case ExtractedInfo.ExtractedType.Community: Genre.Text = "게시글"; break; } } } Thumbnail.Success += (s, e) => { var h = e.ImageInformation.OriginalHeight; var w = e.ImageInformation.OriginalWidth; if (h < 200 && w < 200) { ThumbnailFrame.HeightRequest = h; ThumbnailFrame.WidthRequest = w; } else { ThumbnailFrame.HeightRequest = 300; ThumbnailFrame.WidthRequest = 300; } }; if (!string.IsNullOrWhiteSpace(dbm.ThumbnailCahce)) { Task.Run(() => { Thread.Sleep(100); Device.BeginInvokeOnMainThread(() => { var thumbnail = dbm.ThumbnailCahce; Thumbnail.HeightRequest = Height; Thumbnail.IsVisible = true; Thumbnail.Source = thumbnail; Background.HeightRequest = Height; Background.WidthRequest = Width; Background.IsVisible = true; Background.Source = thumbnail; }); }); } }