Example #1
0
 /// <summary>
 /// Gets the chapter name from a manga.
 /// This is used because chapter names are inconsistent in MangaEdens api.
 /// Some chapters use chapter numbers, some use titles, some use chapter numbers in the title field.
 /// This formats everything to be consistent.
 /// </summary>
 /// <param name="m">The manga</param>
 /// <param name="i">The index of the chapter</param>
 /// <returns>The formated name</returns>
 public string GetChapterName(Manga m, int i)
 {
     if (m.chapters[i][0] != null)
     {
         if (m.chapters[i][2] != null)
         {
             if ((string)m.chapters[i][2] == ((float)m.chapters[i][0]).ToString())
             {
                 return($"Ch.{(string)m.chapters[i][2]}");
             }
             else
             {
                 return($"Ch.{(float)m.chapters[i][0]}: {(string)m.chapters[i][2]} ");
             }
         }
         else
         {
             return($"Ch.{(float)m.chapters[i][0]}");
         }
     }
     else if (m.chapters[i][2] != null)
     {
         return($"{(string)m.chapters[i][2]}");
     }
     else
     {
         return($"?Ch.{i + 1}?");
     }
 }
Example #2
0
 /// <summary>
 /// Fetches the cover of a manga synchronously.
 /// </summary>
 /// <param name="m">The manga</param>
 /// <returns>The downloaded image</returns>
 public BitmapImage FetchCover(Manga m)
 {
     if (m.image == null)
     {
         return(null);
     }
     if (m.isLocal)
     {
         if (m.chapters.Length > 0)
         {
             foreach (var item in Directory.GetFiles((string)m.chapters[0][3]))
             {
                 string p = item.ToLower();
                 if (p.EndsWith(".png") || p.EndsWith(".jpg") || p.EndsWith(".jpeg"))
                 {
                     var img = new BitmapImage(new Uri(item));
                     img.Freeze();
                     return(img);
                 }
             }
             return(null);
         }
         else
         {
             return(null);
         }
     }
     else
     {
         BitmapImage img;
         string      cachePath = $@"{AppDomain.CurrentDomain.BaseDirectory}{COVERS_CACHE_DIR}{(string)m.id}.png";
         lock (fileIOLock) {
             if (File.Exists(cachePath))
             {
                 img = new BitmapImage(new Uri(cachePath));
             }
             else
             {
                 img = DownloadImage(API_IMG + (string)m.image);
                 if (img == null)
                 {
                     return(null);
                 }
                 SaveImage(img, cachePath);
             }
         }
         img.Freeze();
         return(img);
     }
 }
Example #3
0
        /// <summary>
        /// Load a chapter from a local path
        /// </summary>
        /// <param name="path">The path</param>
        /// <returns>The loaded images</returns>
        public BitmapImage[] LoadChapter(Manga m, int index)
        {
            List <BitmapImage> imgs = new List <BitmapImage>();

            string[] files = Directory.GetFiles((string)m.chapters[index][3]);
            Array.Sort(files);
            foreach (var item in files)
            {
                string p = item.ToLower();
                if (p.EndsWith(".png") || p.EndsWith(".jpg") || p.EndsWith(".jpeg"))
                {
                    BitmapImage img = new BitmapImage(new Uri(p));
                    img.Freeze();
                    imgs.Add(img);
                }
            }
            return(imgs.ToArray());
        }
Example #4
0
        public void AsyncFetchChapter(Manga m, int chIndex)
        {
            if (fetchingChapter)//Can only fetch one cahpter at a time
            {
                return;
            }
            fetchingChapter = true;

            //If prefetching, abort it cause were jumping to a new chapter
            if (mangaPrefetchThread != null)
            {
                mangaPrefetchThread.Abort();
            }
            mangaPrefetchThread = null;
            prefetchedData      = null;

            ImagePane.Children.Clear();
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += (s, e) => {//Fetch
                if (m.isLocal)
                {
                    e.Result = api.LoadChapter(m, chIndex);
                }
                else
                {
                    e.Result = api.FetchChapter(e.Argument as string, worker);
                }
            };
            worker.WorkerReportsProgress = true;
            worker.ProgressChanged      += (s, e) => {
                ProgressTip = $"Fetching {e.ProgressPercentage}";
            };
            worker.RunWorkerCompleted += (s, e) => {
                LoadChapterFromData(e.Result as BitmapImage[], m, chIndex);
                loadPrefetchOnComplete = false;
                ProgressTip            = "Idle";
                fetchingChapter        = false;
                AsyncFetchRecents();//Update recents panel
            };
            worker.RunWorkerAsync(m.chapters[chIndex][3] as string);
        }
Example #5
0
 /// <summary>
 /// Fetches more detailed manga info synchronously.
 /// </summary>
 /// <param name="id">id</param>
 /// <returns>The manga</returns>
 public Manga FetchManga(string id)
 {
     using (WebClient client = new WebClient()) {
         try {
             Manga m = JsonConvert.DeserializeObject <Manga>(client.DownloadString(API_BASE + $@"/manga/{id}/"));
             m.title       = System.Net.WebUtility.HtmlDecode(m.title);
             m.alias       = System.Net.WebUtility.HtmlDecode(m.alias);
             m.description = System.Net.WebUtility.HtmlDecode(m.description);
             Array.Reverse(m.chapters);
             for (int i = 0; i < m.chapters.Length; i++)
             {
                 if (m.chapters[i][0] != null)
                 {
                     m.chapters[i][0] = float.Parse(m.chapters[i][0].ToString());
                 }
             }
             m.id = id;
             return(m);
         }
         catch (WebException) { return(null); }
     }
 }
Example #6
0
        /// <summary>
        /// Loads a chapter from the date provided
        /// </summary>
        /// <param name="data">The images</param>
        /// <param name="m">The manga it came from</param>
        /// <param name="chIndex">The chapter it came from</param>
        public void LoadChapterFromData(BitmapImage[] data, Manga m, int chIndex)
        {
            prefetchedData         = null;
            loadPrefetchOnComplete = false;

            if (!m.isLocal)
            {
                if (bookmarks.ContainsKey(m.id))  //Update bookmark buttons
                {
                    if (curManga != m && ChGrid.Children.Count > bookmarks[m.id].lastChapter)
                    {
                        (ChGrid.Children[bookmarks[m.id].lastChapter] as Button).Background = null;
                    }
                    bookmarks[m.id].lastChapter = chIndex;
                    bookmarks[m.id].lastRead    = DateTime.UtcNow;
                }
                else
                {
                    bookmarks.Add(m.id, new MangaBookmark()
                    {
                        id = m.id, lastChapter = chIndex, lastRead = DateTime.UtcNow
                    });
                }
            }

            Binding binding = new Binding();

            binding.Path   = new PropertyPath("ViewportWidth");
            binding.Source = DisplayScroll;
            ImagePane.Children.Clear();
            for (int i = 0; i < data.Length; i++)
            {
                Image img = new Image();
                img.MouseDown          += ZoomStart;
                img.MouseRightButtonUp += ZoomEnd;
                img.MouseEnter         += ZoomEnter;
                img.MouseMove          += ZoomMove;
                img.Source              = data[i];
                BindingOperations.SetBinding(img, Image.MaxWidthProperty, binding);
                ImagePane.Children.Add(img);
            }

            //Update bookmark buttons
            if (ChGrid.Children.Count > chIndex)
            {
                if (curManga == null)
                {
                    (ChGrid.Children[chIndex] as Button).Background = Brushes.DarkGoldenrod;
                }
                else if (curManga == m)
                {
                    (ChGrid.Children[curChIndex] as Button).Background = null;
                    (ChGrid.Children[chIndex] as Button).Background    = Brushes.DarkGoldenrod;
                }
            }
            curManga   = m;
            curChIndex = chIndex;

            //Update top bar
            BarChName.Text = m.title + ", " + api.GetChapterName(m, chIndex);
            hasPrev        = chIndex > 0;
            hasNext        = chIndex < m.chapters.Length - 1;

            if (LeftToRight)  //Makes sure the left and right butts are properly switched when using different read directions
            {
                LeftButt.Visibility  = hasPrev ? Visibility.Visible : Visibility.Hidden;
                RightButt.Visibility = hasNext ? Visibility.Visible : Visibility.Hidden;
                DisplayScroll.ScrollToLeftEnd();
                LeftButt.ToolTip  = "Prev";
                RightButt.ToolTip = "Next (Fetching...)";
            }
            else
            {
                LeftButt.Visibility  = hasNext ? Visibility.Visible : Visibility.Hidden;
                RightButt.Visibility = hasPrev ? Visibility.Visible : Visibility.Hidden;
                DisplayScroll.ScrollToRightEnd();
                RightButt.ToolTip = "Prev";
                LeftButt.ToolTip  = "Next (Fetching...)";
            }

            if (hasNext)//Prefetch next chapter if applicable
            {
                AsyncPrefetchChapter(m, chIndex + 1);
            }
            GC.Collect();
        }
Example #7
0
        /// <summary>
        /// Loads a manga from a path and its subfolders
        /// Chapters are laid out based on discovery order the bfs search and their names
        /// Chapters discovered first will always come first
        /// If the discoervy depth is the same, then they are sorted by name
        /// </summary>
        /// <param name="path">The local path on disk</param>
        /// <returns></returns>
        public Manga LoadManga(string path)
        {
            Manga m = new Manga();

            m.title       = Path.GetFileName(path);
            m.author      = "Meow!";
            m.categories  = new string[] { "Local" };
            m.description = "Local files: \n" + path + "\n";
            m.released    = DateTime.Now.Year;
            m.isLocal     = true;

            var             q        = new Queue <string>();
            List <object[]> chapters = new List <object[]>();

            q.Enqueue(path);
            double time = DateTime.UtcNow.ToUnixTime();

            //Move through file system to find folders with atleast one image file and sort them according to the rule
            while (q.Count > 0)
            {
                string n = q.Dequeue();
                //Checks for image file
                foreach (var item in Directory.GetFiles(n))
                {
                    string p = item.ToLower();
                    if (p.EndsWith(".png") || p.EndsWith(".jpg") || p.EndsWith(".jpeg"))
                    {
                        chapters.Add(new object[] { null, time, Path.GetFileName(n), n });
                        break;
                    }
                }
                string[] paths = Directory.GetDirectories(n);
                Array.Sort(paths, (a, b) => {
                    int ida, idb;
                    int ai = Math.Max(0, a.LastIndexOf(Path.DirectorySeparatorChar));
                    int bi = Math.Max(0, b.LastIndexOf(Path.DirectorySeparatorChar));

                    while ((ida = ParseID(a, ref ai)) != -1 && (idb = ParseID(b, ref bi)) != -1)
                    {
                        if (ida > idb)
                        {
                            return(1);
                        }
                        else if (ida < idb)
                        {
                            return(-1);
                        }
                    }

                    ai = Math.Min(a.Length, b.Length);
                    for (int i = 0; i < ai; i++)
                    {
                        if (a[i] > b[i])
                        {
                            return(1);
                        }
                        else if (a[i] < b[i])
                        {
                            return(-1);
                        }
                    }

                    if (a.Length > b.Length)
                    {
                        return(1);
                    }
                    if (a.Length < b.Length)
                    {
                        return(-1);
                    }

                    return(0);
                });
                foreach (var item in paths)
                {
                    q.Enqueue(item);
                }
            }
            m.chapters = chapters.ToArray();

            return(m);
        }