Luski/Luski/GUI/MainScreen.cs

432 lines
16 KiB
C#

using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using GraphicsManager;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects;
using GraphicsManager.Objects.Core;
using Luski.GUI.MainScreen.Interfaces;
using Luski.GUI.MainScreen.UI;
using Luski.GUI.StartPage.UI;
using Luski.net;
using Luski.net.Enums;
using Luski.net.Interfaces;
using Luski.net.JsonTypes;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.Common;
using Window = GraphicsManager.Window;
namespace Luski.GUI.MainScreen;
public class MainScreen : Window
{
private static readonly NativeWindowSettings Settings = new()
{
Title = "Luski Login",
WindowBorder = WindowBorder.Fixed,
APIVersion = new Version(3, 2),
API = ContextAPI.OpenGL,
StartFocused = true,
Size = new Vector2i((int)(312 * Globals.Settings.Scale), (int)(545 * Globals.Settings.Scale)),
Icon = Globals.Icon,
SharedContext = null
};
public TabControl? tc;
private FlowLayout? channelpicker, friends, friend_request;
private RoundedButton? FriendManagerBtn;
public Chat? chat;
Login login;
CreateAccount ca;
private static DebugProc DebugMessageDelegate = OnDebugMessage;
private static void OnDebugMessage(
DebugSource source, // Source of the debugging message.
DebugType type, // Type of the debugging message.
int id, // ID associated with the message.
DebugSeverity severity, // Severity of the message.
int length, // Length of the string in pMessage.
IntPtr pMessage, // Pointer to message string.
IntPtr pUserParam) // The pointer you gave to OpenGL, explained later.
{
// In order to access the string pointed to by pMessage, you can use Marshal
// class to copy its contents to a C# string without unsafe code. You can
// also use the new function Marshal.PtrToStringUTF8 since .NET Core 1.1.
string message = Marshal.PtrToStringAnsi(pMessage, length);
// The rest of the function is up to you to implement, however a debug output
// is always useful.
switch (severity)
{
case DebugSeverity.DebugSeverityHigh:
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine("[{0} source={1} type={2} id={3}] {4}", severity, source, type, id, message);
Console.ResetColor();
break;
case DebugSeverity.DebugSeverityMedium:
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("[{0} source={1} type={2} id={3}] {4}", severity, source, type, id, message);
Console.ResetColor();
break;
default:
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(message);
Console.ResetColor();
break;
}
}
public MainScreen() : base(Settings)
{
VSync = VSyncMode.On;
GL.DebugMessageCallback(DebugMessageDelegate, IntPtr.Zero);
GL.Enable(EnableCap.DebugOutput);
Globals.DefaultFont =
Font.MakeEmbeddedFont("Luski.Resources.Fonts.OpenSans-Regular.ttf", Assembly.GetExecutingAssembly());
//Globals.DefaultFont = Font.MakeFontFromFile(@"C:\Users\techn\Downloads\tahoma.ttf");
Globals.DefaultFont.PixelHeight = (uint)(20 * Globals.Settings.Scale);
Globals.LuskiTexture = TextureManager.AddTexture(Tools.GetResourceBytes(Assembly.GetExecutingAssembly(),
"Luski.Resources.Textures.Luski.png"));
CenterWindow(0);
Controls.Add(ca = new CreateAccount());
ca.Visible = false;
ca.ChangeToApp += LoginOnChangeToApp;
Controls.Add(login = new Login());
login.ChangeToApp += LoginOnChangeToApp;
login.ChangeToCa += LoginOnChangeToCa;
Thread t = new(_ =>
{
Encryption.GenerateKeys();
});
t.Start();
WindowLoaded += OnWindowLoadedd;
}
private Task OnWindowLoadedd(Window arg)
{
return Task.CompletedTask;
}
private Task OnWindowLoaded(Window arg)
{
if (Globals.UpdaterSettings.AutoUpdateCheck && new HttpClient().GetAsync($"https://www.jacobtech.com/Updater/GetProgramVersion?directory=Luski&branch={Globals.UpdaterSettings.Branch}&selfcontained={Globals.UpdaterSettings.SelfContained.ToString().ToLower()}&platform={Globals.UpdaterSettings.Platform}").Result.Content.ReadAsStringAsync().Result != FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion)
{
var update = new UpdateWindow();
var result = update.ShowDialogue(this);
if (result == UpdateWindow.DialogueResult.Yes)
{
Globals.Download = true;
Close();
}
}
return Task.CompletedTask;
}
private Task LoginOnChangeToCa()
{
Title = "Create Account";
ca.Visible = true;
login.Visible = false;
return Task.CompletedTask;
}
public void AddGroup(SocketGroupChannel group)
{
Group friend = new(group);
friend.ClickCon += ChannelOnClickCon;
channelpicker!.Controls.Add(friend);
chans.Add(friend);
}
private readonly List<Friend> fr = new();
private List<IChannelPick> chans = new();
private Dictionary<long, int> FR_Index = new();
public void AddFriendRequest(SocketRemoteUser user)
{
FriendRequest frui = new(this, user);
FR_Index.Add(user.Id, friend_request!.Controls.Length);
friend_request.Controls.Add(frui);
}
public void RemoveFriendRequest(SocketRemoteUser user)
{
if (!FR_Index.ContainsKey(user.Id)) return;
friend_request!.Controls.Remove(friend_request!.Controls[FR_Index[user.Id]]);
}
public void AddFriend(SocketRemoteUser user)
{
Friend friend2 = new(user);
friend2.ClickCon += ChannelOnClickCon;
friends!.Controls.Add(friend2);
if (user.Channel is not null)
{
Friend friend = new(user);
friend.ClickCon += ChannelOnClickCon;
fr.Add(friend);
channelpicker!.Controls.Add(friend);
chans.Add(friend);
}
}
private CancellationTokenSource? channelCancellationToken = null;
private Task ChannelOnClickCon(IChannelPick arg)
{
try
{
BlockDraw = true;
Thread t = new(a => cc(a!));
t.Start(arg);
}
catch (Exception e)
{
Console.WriteLine(e);
}
return Task.CompletedTask;
}
private void cc(object argg)
{
try
{
IChannelPick arg = (IChannelPick)argg;
Invoke(new Action(() =>
{
chat!.UpdateTitle(arg);
}));
if (channelCancellationToken is not null)
{
channelCancellationToken.Cancel(false);
}
channelCancellationToken = new CancellationTokenSource();
Globals.Luski.ChangeChannel(arg.Channel.Id, channelCancellationToken.Token).Wait();
Invoke(new Action(() =>
{
chat!.Clear();
}));
IReadOnlyList<SocketMessage> messages = arg.Channel.GetMessages(channelCancellationToken.Token, Globals.Settings.LoadPerChannel).Result;
foreach (SocketMessage message in messages.Reverse())
{
if (channelCancellationToken is null || channelCancellationToken.Token.IsCancellationRequested) return;
Invoke(new Action(() =>
{
chat!.AddMessage(TextureManager, message);
}));
}
if (channelCancellationToken is null || channelCancellationToken.Token.IsCancellationRequested) return;
channelCancellationToken = null;
Invoke(new Action(() =>
{
BlockDraw = false;
chat!.MessageFlow.ScrollToBottom();
DrawFrame();
}));
}
catch (Exception e)
{
if (e.Message.Contains("A task was canceled")) return;
Console.WriteLine(e);
}
}
private Task LoginOnChangeToApp()
{
Controls.Clear();
BlockDraw = true;
Title = "Luski";
// string Public, Private;
// using (RSACryptoServiceProvider cryptoServiceProvider = new RSACryptoServiceProvider(Encryption.NewKeySize))
//{
// Private = cryptoServiceProvider.ToXmlString(true);
// Public = cryptoServiceProvider.ToXmlString(false);
//}
// Luski.net.Encryption.File.Channels.AddKey(69, Private);
//Clip
// Console.WriteLine(Public);
Globals.Luski.SetMultiThreadPercent(Globals.Settings.MultiThreadPercent);
Size = new((int)(1332 * Globals.Settings.Scale), (int)(866 * Globals.Settings.Scale));
DateTime start = DateTime.Now;
CenterWindow(0);
DateTime start1 = DateTime.Now;
WindowBorder = WindowBorder.Resizable;
BackgroundColor = new Color4(34, 34, 34, 255);
Rectangle u=new Rectangle(TextureManager.AddTexture(Tools.GetResourceBytes(Assembly.GetExecutingAssembly(),
"Luski.Resources.Textures.Status.png"))) { Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left, Size = new((int)(46 * Globals.Settings.Scale)), Location = new((int)(62 * Globals.Settings.Scale), (int)(812 * Globals.Settings.Scale))};
Texture uut = TextureManager.AddTexture(Globals.Luski.CurrentUser.GetAvatar(CancellationToken.None).Result);
uut.Unit = TextureUnit.Texture1;
u.Shader = Rectangle.DefaultAlphaTextureShader[Context];
u.Textures.Add(uut);
Controls.Add(u);
Label ul = new Label(){ Font = Globals.DefaultFont, Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left, Location = new(0, (int)(826 * Globals.Settings.Scale)), Text = Globals.Luski.CurrentUser.Username};
FlowLayout ser;
ul.Location = new((int)(112 * Globals.Settings.Scale),
(u.Location.Y + (u.Size.Y/2) - (ul.PostiveTrueHeight/2) - ul.Size.Y + ul.TrueHeight));
Controls.Add(ul);
Controls.Add(chat = new() {Location = new((int)(352 * Globals.Settings.Scale),0)});
Controls.Add(ser = new FlowLayout()
{
BackgroundColor = new(26, 26, 26, 255),
Size = new((int)(52 * Globals.Settings.Scale),(int)(868 * Globals.Settings.Scale)),
Anchor = ObjectAnchor.Top | ObjectAnchor.Left | ObjectAnchor.Bottom,
});
Controls.Add(tc = new()// this is here to showcase my good friend TCLL
{
Location = chat.Location,
Size = chat.Size,
BackgroundColor = chat.BackgroundColor,
Anchor = ObjectAnchor.All,
Visible = false,
TitleFont = Globals.DefaultFont,
Border = (int)( 10 * Globals.Settings.Scale),
TabSpace = (int)(5 * Globals.Settings.Scale),
});
tc.AddPage("Friends", friends = new FlowLayout()
{
BackgroundColor = new(45,45,45,255)
});
tc.AddPage("Friend Request", friend_request = new FlowLayout()
{
BackgroundColor = new(45,45,45,255)
});
tc.AddPage("Add Friend", new AddFriendPage(this));
ser.Controls.Add(new Rectangle(Globals.LuskiTexture)
{
Size = new((int)(52 * Globals.Settings.Scale)),
});
Controls.Add(channelpicker = new FlowLayout()
{
BackgroundColor = new(34,34,34,255),
Size = new((int)(300 * Globals.Settings.Scale), (int)(800 * Globals.Settings.Scale)),
Location = new((int)(52 * Globals.Settings.Scale), 0),
Anchor = ObjectAnchor.Top | ObjectAnchor.Left | ObjectAnchor.Bottom
});
channelpicker.Controls.Add(FriendManagerBtn = new RoundedButton() { Font = Globals.DefaultFont, Text = "Friends", Size = new((int)(52* Globals.Settings.Scale)), InsideColor = new(28, 28, 28, 255), BorderColor = Color4.DarkCyan});
FriendManagerBtn.Clicked += FriendManagerBtnOnClicked;
Console.WriteLine("Templates loaded in " + (DateTime.Now - start).TotalSeconds + " seconds");
foreach (SocketGroupChannel ch in Globals.Luski.CurrentUser.Channels.Where(s => s is SocketGroupChannel).Cast<SocketGroupChannel>())
{
AddGroup(ch);
}
foreach (SocketRemoteUser item in Globals.Luski.CurrentUser.Friends)
{
if (item.Channel is not null) AddFriend(item);
}
Console.WriteLine("Channels done in " + (DateTime.Now - start).TotalSeconds + " seconds");
SocketTextChannel chan = Globals.Luski.GetChannel<SocketTextChannel>(Globals.Luski.CurrentUser.SelectedChannel, CancellationToken.None).Result;
chat.UpdateTitle(chans.First(s => s.Channel.Id == chan.Id));
chat.MessageFlow.BlockDraw = true;
try
{
IReadOnlyList<SocketMessage> messages = chan.GetMessages(CancellationToken.None, Globals.Settings.LoadPerChannel).Result;
Console.WriteLine("Messages done in " + (DateTime.Now - start).TotalSeconds + " seconds");
foreach (SocketMessage message in messages.Reverse())
{
chat.AddMessage(TextureManager, message);
}
chat.MessageFlow.ScrollToBottom();
}
catch (Exception e)
{
Console.WriteLine(e);
ChannelOnClickCon(chans.Where(s => s.Channel.Id == 0).First());
}
chat.MessageFlow.BlockDraw = false;
Console.WriteLine("Messages Fonts done in " + (DateTime.Now - start).TotalSeconds + " seconds");
foreach (SocketRemoteUser cufr in Globals.Luski.CurrentUser.FriendRequests)
{
AddFriendRequest(cufr);
}
Console.WriteLine("FR done in " + (DateTime.Now - start).TotalSeconds + " seconds");
BlockDraw = false;
DrawFrame();
Console.WriteLine("GUI done in " + (DateTime.Now - start1).TotalSeconds + " seconds");
MainShow += OnMainShow;
MainShow.Invoke();
return Task.CompletedTask;
}
private Task OnMainShow()
{
Globals.Luski.OnError += LuskiOnOnError;
Globals.Luski.UserStatusUpdate += LuskiOnUserStatusUpdate;
Globals.Luski.ReceivedFriendRequest += LuskiOnReceivedFriendRequest;
Globals.Luski.FriendRequestResult += LuskiOnFriendRequestResult;
return Task.CompletedTask;
}
public event Func<Task>? MainShow;
private Task LuskiOnOnError(Exception arg)
{
Console.WriteLine(arg);
return Task.CompletedTask;
}
private Task LuskiOnFriendRequestResult(SocketRemoteUser arg1, bool arg2)
{
Console.WriteLine("new result");
Invoke(new Action(() =>
{
RemoveFriendRequest(arg1);
if (arg2) AddFriend(arg1);
}));
return Task.CompletedTask;
}
private Task LuskiOnReceivedFriendRequest(SocketRemoteUser arg)
{
Invoke(new Action(() =>
{
AddFriendRequest(arg);
}));
return Task.CompletedTask;
}
private Task LuskiOnUserStatusUpdate(IUser before, IUser After)
{
Console.WriteLine(before);
Console.WriteLine(After);
if (before is not SocketRemoteUser Before || Before.FriendStatus != FriendStatus.Friends || Before.Id == 0) return Task.CompletedTask;
Friend per = fr.Where(s => s.User.Id == before.Id).First()!;
Label stat = per.Status;
Invoke(new Action(() =>
{
per.rr.BackgroundColor = After.Status switch
{
UserStatus.Online => new(115, 255, 111, 255),
UserStatus.Idle => new(255, 229, 84, 255),
UserStatus.DoNotDisturb => new(255, 51, 79, 255),
UserStatus.Offline or UserStatus.Invisible or _ => Color4.LightGray
};
stat.Text = After.Status.ToString();
}));
return Task.CompletedTask;
}
private Task FriendManagerBtnOnClicked(IRenderObject arg)
{
if (chat!.Visible)
{
chat.Visible = false;
tc!.Visible = true;
}
else
{
chat.Visible = true;
tc!.Visible = false;
}
return Task.CompletedTask;
}
}