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 fr = new(); private List chans = new(); private Dictionary 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 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()) { 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(Globals.Luski.CurrentUser.SelectedChannel, CancellationToken.None).Result; chat.UpdateTitle(chans.First(s => s.Channel.Id == chan.Id)); chat.MessageFlow.BlockDraw = true; try { IReadOnlyList 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? 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; } }