Async support
This commit is contained in:
		
							parent
							
								
									963d757ee5
								
							
						
					
					
						commit
						99907740ca
					
				| 
						 | 
				
			
			@ -14,15 +14,16 @@ class GeminiMediaHandler : MediaHandler
 | 
			
		|||
        queries = new List<string>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        Title = Content.URL.AbsolutePath;
 | 
			
		||||
        var reader = new StreamReader(Content.Content);
 | 
			
		||||
        string line;
 | 
			
		||||
        while((line = reader.ReadLine()) is not null)
 | 
			
		||||
        while((line = await reader.ReadLineAsync()) is not null)
 | 
			
		||||
        {
 | 
			
		||||
            lines.Add(line);
 | 
			
		||||
        }
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Render()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,15 +14,16 @@ class GopherMediaHandler : MediaHandler
 | 
			
		|||
        queries = new List<string>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        Title = Content.URL.AbsolutePath;
 | 
			
		||||
        var reader = new StreamReader(Content.Content);
 | 
			
		||||
        string line;
 | 
			
		||||
        while((line = reader.ReadLine()) is not null)
 | 
			
		||||
        while((line = await reader.ReadLineAsync()) is not null)
 | 
			
		||||
        {
 | 
			
		||||
            lines.Add(line);
 | 
			
		||||
        }
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Render()
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +68,7 @@ class GopherMediaHandler : MediaHandler
 | 
			
		|||
                                var url = new UriBuilder(Content.URL){
 | 
			
		||||
                                    Host = l[2],
 | 
			
		||||
                                    Port = int.Parse(l[3]),
 | 
			
		||||
                                    Path = type+l[1],
 | 
			
		||||
                                    Path = type.ToString()+l[1],
 | 
			
		||||
                                }.ToString();
 | 
			
		||||
                                Content.CurrentTab.Load(url+"%09"+queries[querynum]);
 | 
			
		||||
                            });
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +82,7 @@ class GopherMediaHandler : MediaHandler
 | 
			
		|||
                                link = new UriBuilder(Content.URL){
 | 
			
		||||
                                    Host = l[2],
 | 
			
		||||
                                    Port = int.Parse(l[3]),
 | 
			
		||||
                                    Path = type+l[1],
 | 
			
		||||
                                    Path = type.ToString()+l[1],
 | 
			
		||||
                                }.ToString();
 | 
			
		||||
                            Gui.Link(info, link, ()=>
 | 
			
		||||
                                Content.CurrentTab.Load(link));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
using System.IO.Compression;
 | 
			
		||||
using HeyRed.Mime;
 | 
			
		||||
 | 
			
		||||
namespace Shoko;
 | 
			
		||||
 | 
			
		||||
[MediaType("application/gzip")]
 | 
			
		||||
class GzipMediaHandler : MediaHandler
 | 
			
		||||
{
 | 
			
		||||
    MediaHandler newHandler;
 | 
			
		||||
    public GzipMediaHandler(ProtoHandler content)
 | 
			
		||||
    {
 | 
			
		||||
        Content = content;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var stream = new GZipStream(Content.Content, CompressionMode.Decompress);
 | 
			
		||||
        var mem = new MemoryStream();
 | 
			
		||||
        await stream.CopyToAsync(mem);
 | 
			
		||||
        mem.Position = 0;
 | 
			
		||||
        Content.MediaType = MimeGuesser.GuessMimeType(mem);
 | 
			
		||||
        Content.Content = mem;
 | 
			
		||||
 | 
			
		||||
        newHandler = GetHandler(Content);
 | 
			
		||||
        await newHandler.Load();
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
        newHandler.Render();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void MenuBar()
 | 
			
		||||
    {
 | 
			
		||||
        newHandler.MenuBar();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -27,16 +27,17 @@ class ImageMediaHandler : MediaHandler
 | 
			
		|||
        Content = content;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        Title = Content.URL.AbsolutePath;
 | 
			
		||||
        using(var memory = new MemoryStream())
 | 
			
		||||
        {
 | 
			
		||||
            Content.Content.CopyTo(memory);
 | 
			
		||||
            await Content.Content.CopyToAsync(memory);
 | 
			
		||||
            var image = Raylib.LoadImageFromMemory(MediaTypes[Content.MediaType], memory.ToArray());
 | 
			
		||||
            Texture = Raylib.LoadTextureFromImage(image);
 | 
			
		||||
            Raylib.UnloadImage(image);
 | 
			
		||||
        }
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Render()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,16 +11,18 @@ class MagickMediaHandler : ImageMediaHandler
 | 
			
		|||
        Content = content;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        Title = Content.URL.AbsolutePath;
 | 
			
		||||
        using(var magic = new MagickImage(Content.Content))
 | 
			
		||||
        using(var magic = new MagickImage())
 | 
			
		||||
        {
 | 
			
		||||
            await magic.ReadAsync(Content.Content);
 | 
			
		||||
            magic.Format = MagickFormat.Png;
 | 
			
		||||
            var image = Raylib.LoadImageFromMemory(".png", magic.ToByteArray());
 | 
			
		||||
            Texture = Raylib.LoadTextureFromImage(image);
 | 
			
		||||
            Raylib.UnloadImage(image);
 | 
			
		||||
        }
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~MagickMediaHandler()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ class MediaHandler
 | 
			
		|||
{
 | 
			
		||||
    public ProtoHandler Content;
 | 
			
		||||
    public string Title;
 | 
			
		||||
    public bool IsLoaded;
 | 
			
		||||
    public MediaHandler()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -26,9 +27,17 @@ class MediaHandler
 | 
			
		|||
    {
 | 
			
		||||
        Content = content;
 | 
			
		||||
    }
 | 
			
		||||
    public virtual void Load()
 | 
			
		||||
    public virtual Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
        return Task.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public virtual void OnLoaded()
 | 
			
		||||
    {
 | 
			
		||||
        IsLoaded = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public virtual void Render()
 | 
			
		||||
    {
 | 
			
		||||
        Title = "Error";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,15 +11,16 @@ class PlainMediaHandler : MediaHandler
 | 
			
		|||
        lines = new List<string>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        Title = Content.URL.AbsolutePath;
 | 
			
		||||
        var reader = new StreamReader(Content.Content);
 | 
			
		||||
        string line;
 | 
			
		||||
        while((line = reader.ReadLine()) is not null)
 | 
			
		||||
        while((line = await reader.ReadLineAsync()) is not null)
 | 
			
		||||
        {
 | 
			
		||||
            lines.Add(line);
 | 
			
		||||
        }
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Render()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ class AboutProtoHandler : ProtoHandler
 | 
			
		|||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var path = new UriBuilder(URL).Path;
 | 
			
		||||
        Content = new MemoryStream(new byte[]{});
 | 
			
		||||
| 
						 | 
				
			
			@ -41,8 +41,10 @@ class AboutProtoHandler : ProtoHandler
 | 
			
		|||
 | 
			
		||||
        MediaType = "text/plain";
 | 
			
		||||
        Status = "OK";
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
        return Task.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
        var path = new UriBuilder(URL).Path;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ class DataProtoHandler : ProtoHandler
 | 
			
		|||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var data = new UriBuilder(URL).Path;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +37,8 @@ class DataProtoHandler : ProtoHandler
 | 
			
		|||
 | 
			
		||||
        MediaTypeParams = dict;
 | 
			
		||||
        Status = "OK";
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
        return Task.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
using System.Text;
 | 
			
		||||
using System.Web;
 | 
			
		||||
using HeyRed.Mime;
 | 
			
		||||
using Microsoft.Win32.SafeHandles;
 | 
			
		||||
 | 
			
		||||
namespace Shoko;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -11,8 +12,10 @@ class FileProtoHandler : ProtoHandler
 | 
			
		|||
    {
 | 
			
		||||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
    long _totalBytes = -1;
 | 
			
		||||
    public override long TotalBytes => _totalBytes;
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var file = HttpUtility.UrlDecode(URL.AbsolutePath);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,9 +27,11 @@ class FileProtoHandler : ProtoHandler
 | 
			
		|||
 | 
			
		||||
        if(File.Exists(file))
 | 
			
		||||
        {
 | 
			
		||||
            var stream = new FileStream(file, FileMode.Open);
 | 
			
		||||
            MediaType = MimeGuesser.GuessMimeType(stream);
 | 
			
		||||
            Content = stream;
 | 
			
		||||
            var fi = new FileInfo(file);
 | 
			
		||||
            _totalBytes = fi.Length;
 | 
			
		||||
            var stream = fi.OpenRead();
 | 
			
		||||
            Content = await Download(stream);
 | 
			
		||||
            MediaType = MimeGuesser.GuessMimeType(Content);
 | 
			
		||||
        }
 | 
			
		||||
        else if(Directory.Exists(file))
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -47,8 +52,7 @@ class FileProtoHandler : ProtoHandler
 | 
			
		|||
            Content = new MemoryStream(Encoding.UTF8.GetBytes("file not found"));
 | 
			
		||||
            Status = "not found";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ class FingerProtoHandler : ProtoHandler
 | 
			
		|||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var file = URL.PathAndQuery;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,12 +24,11 @@ class FingerProtoHandler : ProtoHandler
 | 
			
		|||
 | 
			
		||||
        var stream = tcp.GetStream();
 | 
			
		||||
 | 
			
		||||
        stream.Write(uri);
 | 
			
		||||
        await stream.WriteAsync(uri);
 | 
			
		||||
 | 
			
		||||
        Content = stream;
 | 
			
		||||
        Content = await Download(stream);
 | 
			
		||||
        MediaType = "text/plain";
 | 
			
		||||
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,8 +13,10 @@ class FtpProtoHandler : ProtoHandler
 | 
			
		|||
    {
 | 
			
		||||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
    long _totalBytes = -1;
 | 
			
		||||
    public override long TotalBytes => _totalBytes;
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var file = URL.AbsolutePath;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +47,7 @@ class FtpProtoHandler : ProtoHandler
 | 
			
		|||
 | 
			
		||||
        conn.Connect();
 | 
			
		||||
 | 
			
		||||
        MediaType = "text/plain"; // TODO: magic numbers
 | 
			
		||||
        MediaType = "text/plain";
 | 
			
		||||
        Status = "OK";
 | 
			
		||||
 | 
			
		||||
        var info = conn.GetObjectInfo(file);
 | 
			
		||||
| 
						 | 
				
			
			@ -55,12 +57,10 @@ class FtpProtoHandler : ProtoHandler
 | 
			
		|||
            switch(info.Type)
 | 
			
		||||
            {
 | 
			
		||||
                case FtpObjectType.File:
 | 
			
		||||
                    //Content = conn.OpenRead(file);
 | 
			
		||||
                    if(conn.DownloadBytes(out byte[] bytes, info.FullName))
 | 
			
		||||
                    {
 | 
			
		||||
                        Content = new MemoryStream(bytes);
 | 
			
		||||
                        MediaType = MimeGuesser.GuessMimeType(Content);
 | 
			
		||||
                    }
 | 
			
		||||
                    _totalBytes = info.Size;
 | 
			
		||||
                    var stream = conn.OpenRead(file);
 | 
			
		||||
                    Content = await Download(stream);
 | 
			
		||||
                    MediaType = MimeGuesser.GuessMimeType(Content);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FtpObjectType.Directory:
 | 
			
		||||
                    MediaType = "text/gemini";
 | 
			
		||||
| 
						 | 
				
			
			@ -107,8 +107,7 @@ class FtpProtoHandler : ProtoHandler
 | 
			
		|||
                Status = "not found";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ class GeminiProtoHandler : ProtoHandler
 | 
			
		|||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var gemini = new Gemini(URL);
 | 
			
		||||
        gemini.Connect();
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ class GeminiProtoHandler : ProtoHandler
 | 
			
		|||
 | 
			
		||||
                MediaTypeParams = dict;
 | 
			
		||||
            }
 | 
			
		||||
            Content = gemini.sslStream;
 | 
			
		||||
            Content = await Download(gemini.sslStream);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -54,8 +54,7 @@ class GeminiProtoHandler : ProtoHandler
 | 
			
		|||
            }
 | 
			
		||||
            Content = new MemoryStream(content);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Render()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ class GopherProtoHandler : ProtoHandler
 | 
			
		|||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var type = "0";
 | 
			
		||||
        var file = URL.PathAndQuery;
 | 
			
		||||
| 
						 | 
				
			
			@ -35,15 +35,6 @@ class GopherProtoHandler : ProtoHandler
 | 
			
		|||
        else
 | 
			
		||||
            type = "1";
 | 
			
		||||
        
 | 
			
		||||
        var uri = Encoding.UTF8.GetBytes(HttpUtility.UrlDecode(string.Join("/", paths))+"\r\n");
 | 
			
		||||
 | 
			
		||||
        var tcp = new TcpClient(URL.Host, URL.Port < 0 ? 70 : URL.Port);
 | 
			
		||||
 | 
			
		||||
        var stream = tcp.GetStream();
 | 
			
		||||
 | 
			
		||||
        stream.Write(uri);
 | 
			
		||||
 | 
			
		||||
        Content = stream;
 | 
			
		||||
        switch(type)
 | 
			
		||||
        {
 | 
			
		||||
            case "0":
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +63,16 @@ class GopherProtoHandler : ProtoHandler
 | 
			
		|||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        var uri = Encoding.UTF8.GetBytes(HttpUtility.UrlDecode(string.Join("/", paths))+"\r\n");
 | 
			
		||||
 | 
			
		||||
        var tcp = new TcpClient(URL.Host, URL.Port < 0 ? 70 : URL.Port);
 | 
			
		||||
 | 
			
		||||
        var stream = tcp.GetStream();
 | 
			
		||||
 | 
			
		||||
        stream.Write(uri);
 | 
			
		||||
 | 
			
		||||
        Content = await Download(stream);
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
using System.Reflection;
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Shoko;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -10,22 +11,26 @@ class HttpProtoHandler : ProtoHandler
 | 
			
		|||
    {
 | 
			
		||||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
    long _totalBytes = -1;
 | 
			
		||||
    public override long TotalBytes => _totalBytes;
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        HttpClient client = new(){
 | 
			
		||||
        var client = new HttpClient(){
 | 
			
		||||
            BaseAddress = URL
 | 
			
		||||
        };
 | 
			
		||||
        client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 shoko/" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
 | 
			
		||||
 | 
			
		||||
        var response = client.GetAsync(URL).Result;
 | 
			
		||||
        var response = await client.GetAsync(URL, HttpCompletionOption.ResponseHeadersRead);
 | 
			
		||||
 | 
			
		||||
        Headers = response.Content.Headers;
 | 
			
		||||
        Content = response.Content.ReadAsStream();
 | 
			
		||||
        _totalBytes = response.Content.Headers.ContentLength ?? -1;
 | 
			
		||||
        MediaType = response.Content.Headers.ContentType.MediaType ?? "text/html";
 | 
			
		||||
        MediaTypeParams = response.Content.Headers.ContentType.Parameters.Select(x => new KeyValuePair<string, string>(x.Name, x.Value));
 | 
			
		||||
        Status = string.Format("{0} {1}", (int)response.StatusCode, response.StatusCode.ToString());
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        var download = await response.Content.ReadAsStreamAsync();
 | 
			
		||||
        Content = await Download(download);
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,11 +21,13 @@ class ProtoHandler
 | 
			
		|||
    public string MediaType;
 | 
			
		||||
    public Stream Content;
 | 
			
		||||
    public string Status;
 | 
			
		||||
    public bool Loaded = false;
 | 
			
		||||
    public int LoadedBytes = 0;
 | 
			
		||||
    public int TotalBytes = 0;
 | 
			
		||||
    public bool IsLoaded = false;
 | 
			
		||||
    protected long _loadedBytes = 0;
 | 
			
		||||
    public virtual long LoadedBytes => _loadedBytes;
 | 
			
		||||
    public virtual long TotalBytes => -1;
 | 
			
		||||
    public IEnumerable<KeyValuePair<string,IEnumerable<string>>> Headers;
 | 
			
		||||
    public IEnumerable<KeyValuePair<string,string>> MediaTypeParams;
 | 
			
		||||
    public MediaHandler Media;
 | 
			
		||||
    public ProtoHandler()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,11 +36,40 @@ class ProtoHandler
 | 
			
		|||
    {
 | 
			
		||||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
    public virtual void Load()
 | 
			
		||||
    public virtual Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        Content = new MemoryStream(Encoding.UTF8.GetBytes("error: no handler for this scheme"));
 | 
			
		||||
        MediaType = "text/plain";
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
        return Task.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<MemoryStream> Download(Stream stream, Action<long> progress)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = new MemoryStream();
 | 
			
		||||
        var buf = new byte[81920];
 | 
			
		||||
        long totalBytes = 0;
 | 
			
		||||
        int bytesRead;
 | 
			
		||||
        while ((bytesRead = await stream.ReadAsync(buf, 0, buf.Length)) != 0) {
 | 
			
		||||
            await ret.WriteAsync(buf.AsMemory(0, bytesRead));
 | 
			
		||||
            totalBytes += bytesRead;
 | 
			
		||||
            progress(totalBytes);
 | 
			
		||||
        }
 | 
			
		||||
        ret.Position = 0;
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<MemoryStream> Download(Stream stream)
 | 
			
		||||
    {
 | 
			
		||||
        return await Download(stream, b=>_loadedBytes=b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public virtual void OnLoaded()
 | 
			
		||||
    {
 | 
			
		||||
        Media = MediaHandler.GetHandler(this);
 | 
			
		||||
        IsLoaded = true;
 | 
			
		||||
        Media.Load();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public virtual void Render()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Web;
 | 
			
		||||
using HeyRed.Mime;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -12,21 +13,22 @@ class ResProtoHandler : ProtoHandler
 | 
			
		|||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var path = HttpUtility.HtmlDecode(new UriBuilder(URL).Path);
 | 
			
		||||
        var path = HttpUtility.HtmlDecode(URL.AbsolutePath);
 | 
			
		||||
        Status = "OK";
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            Content = Assembly.GetExecutingAssembly().GetManifestResourceStream(path);
 | 
			
		||||
            Content = await Download(Assembly.GetExecutingAssembly().GetManifestResourceStream(path));
 | 
			
		||||
            MediaType = MimeGuesser.GuessMimeType(Content);
 | 
			
		||||
        }
 | 
			
		||||
        catch
 | 
			
		||||
        {
 | 
			
		||||
            Content = new MemoryStream(Encoding.UTF8.GetBytes("resource not found"));
 | 
			
		||||
            MediaType = "text/plain";
 | 
			
		||||
            Status = "not found";
 | 
			
		||||
            Loaded = false;
 | 
			
		||||
        }
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
    public override void Render()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ class SpartanProtoHandler : ProtoHandler
 | 
			
		|||
        URL = url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Load()
 | 
			
		||||
    public override async Task Load()
 | 
			
		||||
    {
 | 
			
		||||
        var file = URL.AbsolutePath;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,9 +28,9 @@ class SpartanProtoHandler : ProtoHandler
 | 
			
		|||
        var tcp = new TcpClient(URL.Host, URL.Port < 0 ? 300 : URL.Port);
 | 
			
		||||
 | 
			
		||||
        var stream = tcp.GetStream();
 | 
			
		||||
        stream.Write(uri);
 | 
			
		||||
        await stream.WriteAsync(uri);
 | 
			
		||||
        if(query.Length > 0)
 | 
			
		||||
            stream.Write(query);
 | 
			
		||||
            await stream.WriteAsync(query);
 | 
			
		||||
 | 
			
		||||
        var reader = new StreamReader(stream);
 | 
			
		||||
        var header = reader.ReadLine();
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ class SpartanProtoHandler : ProtoHandler
 | 
			
		|||
 | 
			
		||||
                MediaTypeParams = dict;
 | 
			
		||||
            }
 | 
			
		||||
            Content = stream;
 | 
			
		||||
            Content = await Download(stream);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ class SpartanProtoHandler : ProtoHandler
 | 
			
		|||
            }
 | 
			
		||||
            Content = new MemoryStream(content);
 | 
			
		||||
        }
 | 
			
		||||
        Loaded = true;
 | 
			
		||||
        OnLoaded();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public override void Render()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										54
									
								
								Tab.cs
								
								
								
								
							
							
						
						
									
										54
									
								
								Tab.cs
								
								
								
								
							| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
using System.Numerics;
 | 
			
		||||
using FluentFTP.Helpers;
 | 
			
		||||
using ImGuiNET;
 | 
			
		||||
 | 
			
		||||
namespace Shoko;
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +7,6 @@ namespace Shoko;
 | 
			
		|||
class Tab
 | 
			
		||||
{
 | 
			
		||||
    ProtoHandler Handler;
 | 
			
		||||
    MediaHandler Document;
 | 
			
		||||
    public bool IsOpen = true;
 | 
			
		||||
    Exception Error = null;
 | 
			
		||||
    Stack<Uri> History;
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +20,7 @@ class Tab
 | 
			
		|||
        txtURL = url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void Load(string url)
 | 
			
		||||
    public async Task Load(string url)
 | 
			
		||||
    {
 | 
			
		||||
        Error = null;
 | 
			
		||||
        ImGui.SetScrollX(0);
 | 
			
		||||
| 
						 | 
				
			
			@ -28,11 +29,9 @@ class Tab
 | 
			
		|||
        {
 | 
			
		||||
            Handler = ProtoHandler.GetHandler(url);
 | 
			
		||||
            Handler.CurrentTab = this;
 | 
			
		||||
            Handler.Load();
 | 
			
		||||
            txtURL = Handler.URL.ToString();
 | 
			
		||||
            History.Push(Handler.URL);
 | 
			
		||||
            Document = MediaHandler.GetHandler(Handler);
 | 
			
		||||
            Document.Load();
 | 
			
		||||
            await Handler.Load();
 | 
			
		||||
        }
 | 
			
		||||
        catch(Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -52,9 +51,9 @@ class Tab
 | 
			
		|||
    public void Render()
 | 
			
		||||
    {
 | 
			
		||||
        var title = txtURL;
 | 
			
		||||
        if(Document is not null)
 | 
			
		||||
        if(Handler.Media is not null)
 | 
			
		||||
        {
 | 
			
		||||
            title = Document.Title;
 | 
			
		||||
            title = Handler.Media.Title;
 | 
			
		||||
        }
 | 
			
		||||
        Gui.Window(title+"###"+GetHashCode().ToString(), ref IsOpen, ImGuiWindowFlags.MenuBar | ImGuiWindowFlags.HorizontalScrollbar, ()=>
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,9 +64,12 @@ class Tab
 | 
			
		|||
 | 
			
		||||
                if(Error is null)
 | 
			
		||||
                {
 | 
			
		||||
                    Handler.MenuBar();
 | 
			
		||||
                    if(Handler.Loaded)
 | 
			
		||||
                        Document.MenuBar();
 | 
			
		||||
                    if(Handler.IsLoaded)
 | 
			
		||||
                    {
 | 
			
		||||
                        Handler.MenuBar();
 | 
			
		||||
                        if(Handler.Media.IsLoaded)
 | 
			
		||||
                            Handler.Media.MenuBar();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Gui.Button("<<", ()=>{
 | 
			
		||||
| 
						 | 
				
			
			@ -79,19 +81,41 @@ class Tab
 | 
			
		|||
                Gui.Button("Go", ()=>{
 | 
			
		||||
                    Load(txtURL);
 | 
			
		||||
                });
 | 
			
		||||
                if(!Handler.Loaded && Handler.TotalBytes != 0)
 | 
			
		||||
                    ImGui.ProgressBar(Handler.LoadedBytes / Handler.TotalBytes);
 | 
			
		||||
                if(!Handler.IsLoaded)
 | 
			
		||||
                {
 | 
			
		||||
                    ImGui.Text("Loading...");
 | 
			
		||||
                    if(Handler.TotalBytes != 0 && Handler.TotalBytes != Handler.LoadedBytes)
 | 
			
		||||
                        ImGui.ProgressBar(Handler.LoadedBytes / Handler.TotalBytes, new Vector2(200, 20),
 | 
			
		||||
                            Handler.LoadedBytes.FileSizeToString() + "/" + Handler.TotalBytes.FileSizeToString());
 | 
			
		||||
                }
 | 
			
		||||
                else if(!Handler.Media.IsLoaded)
 | 
			
		||||
                {
 | 
			
		||||
                    ImGui.Text("Rendering...");
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            if(Error is not null)
 | 
			
		||||
            {
 | 
			
		||||
                ImGui.Text("error: can't load page");
 | 
			
		||||
                ImGui.Text(Error.Message);
 | 
			
		||||
                ImGui.Text(Error.StackTrace);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if(Handler.Loaded)
 | 
			
		||||
                    Document.Render();
 | 
			
		||||
                Handler.Render();
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if(Handler.IsLoaded)
 | 
			
		||||
                    {
 | 
			
		||||
                        if(Handler.Media.IsLoaded)
 | 
			
		||||
                            Handler.Media.Render();
 | 
			
		||||
                        Handler.Render();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch(Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    ImGui.Text("error: can't render page");
 | 
			
		||||
                    ImGui.Text(ex.Message);
 | 
			
		||||
                    ImGui.Text(ex.StackTrace);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue