2024-11-17 22:58:21 -05:00

335 lines
12 KiB
C#

using System.Diagnostics;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects;
using GraphicsManager.Objects.Core;
using Luski.GUI.MainScreen.UI.LuskiControls;
using Luski.net.Structures.Main;
using Luski.net.Structures.Public;
using Luski.Shared.PublicServers.V1.Enums;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common.Input;
using OpenTK.Windowing.GraphicsLibraryFramework;
using Label = GraphicsManager.Objects.Label;
namespace Luski.GUI.MainScreen.UI.PublicServers;
public class ChatMessage : UserControl
{
private SocketMessage Msg { get; }
private SocketChannel ch { get; }
public PublicChat pc;
private IRenderObject LastObject;
public List<IRenderObject> MessageObjs = new();
private LabelBase FirstL;
public readonly double HorPadding = 12.ScaleDouble(),
VerticalPadding = 0.ScaleDouble();
private static Dictionary<MainSocketRemoteUser, List<ChatMessage>> Messages = new();
public static async Task<ChatMessage> MakeChatMessage(PublicChat p, SocketMessage message)
{
SocketUser auth = (SocketUser)(await message.GetAuthor(CancellationToken.None));
ServerProfile prof = await message.GetProfile(CancellationToken.None);
Role r = (await ((SocketUser)await message.GetAuthor(CancellationToken.None)).GetRoles())[0];
return new ChatMessage(p, message, await message.GetParent(CancellationToken.None), prof, await prof.MakeRct(auth, new(40.ScaleInt())), r);
}
private ChatMessage(PublicChat p, SocketMessage message, SocketChannel chan, ServerProfile Author, IRenderObject UserIcon, Role r)
{
pc = p;
LuskiLabel label1;
base.SetSize(723.5.ScaleInt(), 37.ScaleInt());
ch = chan;
base.BackgroundColor = new(40, 40, 40, 255);
Msg = message;
Anchor = ObjectAnchor.Left | ObjectAnchor.Right;
DateTime time = chan.Epoch.AddMilliseconds(Msg.TimeStamp).ToLocalTime();
string time_str;
if (Globals.Settings.DayTime)
{
if (time.Date == DateTime.Now.ToLocalTime().Date)
{
time_str = $"Today at {time:HH:mm}";
}
else if (time.Date == DateTime.Now.ToLocalTime().AddDays(-1).Date)
{
time_str = $"Yesterday at {time:HH:mm}";
}
else
{
time_str = $"{time:M/dd/yyyy HH:mm}";
}
}
else
{
if (time.Date == DateTime.Now.ToLocalTime().Date)
{
time_str = $"Today at {time.ToShortTimeString().Replace('\u202f', ' ')}";
}
else if (time.Date == DateTime.Now.ToLocalTime().AddDays(-1).Date)
{
time_str = $"Yesterday at {time.ToShortTimeString().Replace('\u202f', ' ')}";
}
else
{
time_str = $"{time:M/dd/yyyy h:mm tt}";
}
}
UserIcon.Location = new(10.ScaleInt(), 2.ScaleInt());
Controls.Add(UserIcon);
string name = Author.DisplayName;
if (r.ColorType == ColorType.Full)
{
name = $"[color=\"{r.Colors[0].ToDatabaseStr()}\"]{name}[/color]";
}
else
{
name = $"[gradient colors=\"{r.Colors.ToDB()}\"]{name}[/gradient]";
}
Controls.Add(label1 = new (Globals.DefaultFont) { Text = name });
label1.Location = new(
54.ScaleInt(),
UserIcon.Location.Y);
Label label2;
LastObject = label1;
FirstL = label1;
Controls.Add(label2 = new(Globals.TopTimeFont) { Location = new(label1.Location.X + label1.Size.X + 8.ScaleInt(), (int)(label1.Location.Y + label1.Font.PixelHeight - Globals.TopTimeFont.PixelHeight)), Text = time_str});
if (!string.IsNullOrWhiteSpace(Msg.Context))
{
LuskiLabel l;
Controls.Add(l = new(Globals.MessageFont) { Location = new(LastObject.Location.X, (int)(UserIcon.Location.Y + UserIcon.Size.Y - Globals.MessageFont.PixelHeight)), Text = message.Context});
LastObject = l;
LuskiContextMenu lcm = new();
Label llllll = lcm.AddLabel("Copy Text");
unsafe
{
llllll.Clicked += (o) =>
{
GLFW.SetClipboardString(Globals.ms.WindowPtr, message.Context);
return Task.CompletedTask;
};
}
l.ContextMenu = lcm;
MessageObjs.Add(l);
}
Globals.Settings.DayTimeChanged += () =>
{
if (Globals.Settings.DayTime)
{
if (time.Date == DateTime.Now.ToLocalTime().Date)
{
time_str = $"Today at {time:HH:mm}";
}
else if (time.Date == DateTime.Now.ToLocalTime().AddDays(-1).Date)
{
time_str = $"Yesterday at {time:HH:mm}";
}
else
{
time_str = $"{time:M/dd/yyyy HH:mm}";
}
}
else
{
if (time.Date == DateTime.Now.ToLocalTime().Date)
{
time_str = $"Today at {time.ToShortTimeString().Replace('\u202f', ' ')}";
}
else if (time.Date == DateTime.Now.ToLocalTime().AddDays(-1).Date)
{
time_str = $"Yesterday at {time.ToShortTimeString().Replace('\u202f', ' ')}";
}
else
{
time_str = $"{time:M/dd/yyyy h:mm tt}";
}
}
label2.Text = time_str;
return Task.CompletedTask;
};
if (Msg.Files.Count > 0)
{
int row = 1;
int files_on_row = 0;
for (int i = 0; i < Msg.Files.Count; i++)
{
double lx = (HorPadding * files_on_row) + LastObject.Location.X + (333 * (files_on_row + 1));
if (lx > base.Size.X)
{
row++;
files_on_row = 0;
lx = (HorPadding * files_on_row) + LastObject.Location.X + (333 * (files_on_row + 1));
}
files_on_row++;
IRenderObject cem = ContentEmbed.GetEmbed(this, Msg.Files[i], Msg.ChannelID).Result;
cem.Location = new((int)(lx - 333), (int)(LastObject.Location.Y + 2 + LastObject.Size.Y + (HorPadding * row) + (66 * (row - 1))));
LastObject = cem;
Controls.Add(cem);
}
}
if (LastObject is Label ll) base.Size = new(base.Size.X, (int)(ll.Location.Y + ll.Size.Y + VerticalPadding));
else base.Size = new(base.Size.X ,(int)(LastObject.Location.Y + LastObject.Size.Y + VerticalPadding));
}
public async Task AddMessage(SocketMessage msg)
{
BlockDraw = true;
LuskiLabel newLabel;
if (!string.IsNullOrWhiteSpace(msg.Context))
{
newLabel = new(Globals.MessageFont)
{
Text = msg.Context,
Tag = msg
};
if (LastObject is Label l)
{
newLabel.Location = new(FirstL.Location.X, (int)(l.Location.Y + l.Size.Y + VerticalPadding));
}
else
{
newLabel.Location = new(FirstL.Location.X, Size.Y);
}
bool result = Uri.TryCreate(newLabel.Text, UriKind.Absolute, out Uri? uriResult)
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
if (result)
{
newLabel.HoverMouse = MouseCursor.Hand;
newLabel.DefaultColor = Color4.Aqua;
newLabel.Clicked += NewLabelOnClicked;
}
newLabel.MouseEnter += NewLabel_MouseEnter;
newLabel.MouseLeave += NewLabel_MouseLeave;
Controls.Add(newLabel);
MessageObjs.Add(newLabel);
LastObject = newLabel;
LuskiContextMenu lcm = new();
Label llllll = lcm.AddLabel("Copy Text");
unsafe
{
llllll.Clicked += (o) =>
{
GLFW.SetClipboardString(Globals.ms.WindowPtr, msg.Context);
return Task.CompletedTask;
};
}
newLabel.ContextMenu = lcm;
}
if (msg.Files.Count > 0)
{
int row = 1;
int filesonrow = 0;
for (int i = 0; i < msg.Files.Count; i++)
{
double lx = (HorPadding * filesonrow) + LastObject.Location.X + (333 * (filesonrow + 1));
if (lx > Size.X)
{
row++;
filesonrow = 0;
lx = (HorPadding * filesonrow) + LastObject.Location.X + (333 * (filesonrow + 1));
}
filesonrow++;
IRenderObject cem = await ContentEmbed.GetEmbed(this, msg.Files[i], msg.ChannelID);
cem.Location = new((int)(lx - 333), (int)(LastObject.Location.Y + 2 + LastObject.Size.Y + (HorPadding * row) + (66 * (row - 1))));
LastObject = cem;
Controls.Add(cem);
}
}
if (LastObject is Label ll) Size = new(Size.X, (int)(ll.Location.Y + ll.Size.Y + VerticalPadding));
else Size = new(Size.X ,(int)(LastObject.Location.Y + LastObject.Size.Y + VerticalPadding));
BlockDraw = false;
//if (Parent is not null) Globals.ms.pc.MessageFlow.ReportSizeUpdate(this);
TryDraw();
}
private Task NewLabelOnClicked(IRenderObject arg)
{
try
{
Label m = (arg as Label)!;
if (OperatingSystem.IsWindows())
Process.Start(m.Text);
else if (OperatingSystem.IsLinux())
{
if (m.Tag is string s) Process.Start("xdg-open", s);
else Process.Start("xdg-open", m.Text);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
return Task.CompletedTask;
}
readonly List<Label> Labels = new();
private async Task NewLabel_MouseLeave(IRenderObject sender)
{
if (sender is not Label label) return;
if (label.Tag is not SocketMessage Message) return;
DateTime time = (await Message.GetParent(CancellationToken.None)).Epoch.AddMilliseconds(Message.TimeStamp).ToLocalTime();
string b;
if (!Globals.Settings.DayTime) b = time.ToString("h:mm tt");
else b = time.ToString("HH:mm");
Globals.Settings.DayTimeChanged += () =>
{
if (!Globals.Settings.DayTime) b = time.ToString("h:mm tt");
else b = time.ToString("HH:mm");
return Task.CompletedTask;
};
Label[] l = Labels.Where(s => s.Text == b).ToArray();
if (l.Any())
{
Controls.Remove(l.First());
Labels.Remove(l.First());
}
Window!.TryDraw();
}
private async Task NewLabel_MouseEnter(IRenderObject sender)
{
if (sender is not Label label) return;
if (label.Tag is not SocketMessage Message) return;
DateTime time = (await Message.GetParent(CancellationToken.None)).Epoch.AddMilliseconds(Message.TimeStamp).ToLocalTime();
Label m;
if (!Globals.Settings.DayTime) m = new( Globals.SmallTimeFont)
{
Text = time.ToString("h:mm tt"),
};
else m = new( Globals.SmallTimeFont)
{
Text = time.ToString("HH:mm"),
};
Globals.Settings.DayTimeChanged += () =>
{
if (!Globals.Settings.DayTime) m.Text = time.ToString("h:mm tt");
else m.Text = time.ToString("HH:mm");
return Task.CompletedTask;
};
m.Location = new(
label.Location.X - m.Size.X - 5.ScaleInt(),
(int)(label.Location.Y + label.Font.PixelHeight - Globals.SmallTimeFont.PixelHeight));
Controls.Add(m);
Labels.Add(m);
Window!.TryDraw();
}
}