2024-04-11 19:42:06 -04:00

328 lines
12 KiB
C#

using System.Diagnostics;
using System.Runtime.CompilerServices;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects;
using Luski.net.Interfaces;
using Luski.net.Structures.Main;
using Luski.net.Structures.Public;
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 Label 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)
{
IUser auth = await message.GetAuthor(CancellationToken.None);
Color c = await auth.GetColor();
Color4 c4 = new(c.R, c.G, c.B, c.A);
return new ChatMessage(p, message, await message.GetParent(CancellationToken.None), auth, await auth.MakeRct(new(40.ScaleInt()), message.IsProfile), c4);
}
private ChatMessage(PublicChat p, SocketMessage message, SocketChannel chan, IUser Author, IRenderObject UserIcon, Color4 UserNameColor)
{
pc = p;
Label label1;
base.Size = new(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(), 0);
Controls.Add(UserIcon);
Controls.Add(label1 = new Label(Globals.DefaultFont) { Color = UserNameColor, Text = Author.DisplayName });
label1.Location = new(
54.ScaleInt(),
//(int)(UserIcon.Location.Y + (UserIcon.Size.Y / 2) - (label1.Font.CurrentFonts[0].Face.Size.Metrics.NominalHeight / 2) - label1.Size.Y + label1.Font.PixelHeight),
UserIcon.Location.Y,
0);
Label label2;
LastObject = label1;
FirstL = label1;
Controls.Add(label2 = new Label(Globals.TopTimeFont) { Location = new(label1.Location.X + label1.Size.X + 8.ScaleInt(), (int)(label1.Location.Y + label1.Font.PixelHeight - Globals.TopTimeFont.PixelHeight), 0), Text = time_str});
if (!string.IsNullOrWhiteSpace(Msg.Context))
{
Label l;
Controls.Add(l = new Label(Globals.MessageFont) { Location = new(LastObject.Location.X, (int)(UserIcon.Location.Y + UserIcon.Size.Y - Globals.MessageFont.PixelHeight), 0), 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))), 0);
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;
Label 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), 0);
}
else
{
newLabel.Location = new(FirstL.Location.X, Size.Y, 0);
}
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.Color = 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))), 0);
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),
0);
Controls.Add(m);
Labels.Add(m);
Window!.TryDraw();
}
}