335 lines
12 KiB
C#
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();
|
|
}
|
|
} |