kk
This commit is contained in:
parent
4f23083f44
commit
ea4875c297
|
@ -16,6 +16,6 @@ internal class Commands : IDisposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCommand(string command, string arguments) {
|
private void OnCommand(string command, string arguments) {
|
||||||
this.Plugin.Ui.WriterVisible ^= true;
|
this.Plugin.Ui.MainWindow.Visible ^= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
27
client/Helpers/ServerHelper.cs
Normal file
27
client/Helpers/ServerHelper.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
namespace OrangeGuidanceTomestone.Helpers;
|
||||||
|
|
||||||
|
internal static class ServerHelper {
|
||||||
|
internal static HttpRequestMessage GetRequest(string apiKey, HttpMethod method, string tail, string? contentType = null, HttpContent? content = null) {
|
||||||
|
if (!tail.StartsWith('/')) {
|
||||||
|
tail = '/' + tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = $"https://tryfingerbuthole.anna.lgbt{tail}";
|
||||||
|
var req = new HttpRequestMessage(method, url);
|
||||||
|
if (content != null) {
|
||||||
|
req.Content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Headers.Add("X-Api-Key", apiKey);
|
||||||
|
if (contentType != null) {
|
||||||
|
req.Headers.Add("Content-Type", contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task<HttpResponseMessage> SendRequest(string apiKey, HttpMethod method, string tail, string? contentType = null, HttpContent? content = null) {
|
||||||
|
var req = GetRequest(apiKey, method, tail, contentType, content);
|
||||||
|
return await new HttpClient().SendAsync(req, HttpCompletionOption.ResponseHeadersRead);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,3 +20,34 @@ internal class Message {
|
||||||
|
|
||||||
internal Vector3 Position => new(this.X, this.Y, this.Z);
|
internal Vector3 Position => new(this.X, this.Y, this.Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
internal class MessageWithTerritory {
|
||||||
|
public Guid Id { get; init; }
|
||||||
|
public uint Territory { get; init; }
|
||||||
|
public float X { get; init; }
|
||||||
|
public float Y { get; init; }
|
||||||
|
public float Z { get; init; }
|
||||||
|
|
||||||
|
[JsonProperty("message")]
|
||||||
|
public string Text { get; init; }
|
||||||
|
|
||||||
|
public int PositiveVotes { get; init; }
|
||||||
|
public int NegativeVotes { get; init; }
|
||||||
|
|
||||||
|
internal Vector3 Position => new(this.X, this.Y, this.Z);
|
||||||
|
|
||||||
|
internal static MessageWithTerritory From(Message message, uint territory) {
|
||||||
|
return new MessageWithTerritory {
|
||||||
|
Id = message.Id,
|
||||||
|
Territory = territory,
|
||||||
|
X = message.X,
|
||||||
|
Y = message.Y,
|
||||||
|
Z = message.Z,
|
||||||
|
Text = message.Text,
|
||||||
|
PositiveVotes = message.PositiveVotes,
|
||||||
|
NegativeVotes = message.NegativeVotes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System.Numerics;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using OrangeGuidanceTomestone.Helpers;
|
||||||
|
|
||||||
namespace OrangeGuidanceTomestone;
|
namespace OrangeGuidanceTomestone;
|
||||||
|
|
||||||
|
@ -63,10 +64,11 @@ internal class Messages : IDisposable {
|
||||||
this.RemoveVfx(null, null);
|
this.RemoveVfx(null, null);
|
||||||
|
|
||||||
Task.Run(async () => {
|
Task.Run(async () => {
|
||||||
var req = new HttpRequestMessage(HttpMethod.Get, $"https://tryfingerbuthole.anna.lgbt/messages/{territory}");
|
var resp = await ServerHelper.SendRequest(
|
||||||
req.Headers.Add("X-Api-Key", this.Plugin.Config.ApiKey);
|
this.Plugin.Config.ApiKey,
|
||||||
|
HttpMethod.Get,
|
||||||
var resp = await new HttpClient().SendAsync(req);
|
$"/messages/{territory}"
|
||||||
|
);
|
||||||
var json = await resp.Content.ReadAsStringAsync();
|
var json = await resp.Content.ReadAsStringAsync();
|
||||||
var messages = JsonConvert.DeserializeObject<Message[]>(json)!;
|
var messages = JsonConvert.DeserializeObject<Message[]>(json)!;
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,19 @@
|
||||||
using System.Net.Http.Headers;
|
using OrangeGuidanceTomestone.Ui;
|
||||||
using System.Numerics;
|
|
||||||
using System.Text;
|
|
||||||
using Dalamud.Interface;
|
|
||||||
using ImGuiNET;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace OrangeGuidanceTomestone;
|
namespace OrangeGuidanceTomestone;
|
||||||
|
|
||||||
public class PluginUi : IDisposable {
|
public class PluginUi : IDisposable {
|
||||||
private Plugin Plugin { get; }
|
private Plugin Plugin { get; }
|
||||||
|
|
||||||
internal bool WriterVisible;
|
internal MainWindow MainWindow { get; }
|
||||||
internal bool ViewerVisible;
|
internal Viewer Viewer { get; }
|
||||||
|
internal ViewerButton ViewerButton { get; }
|
||||||
private int _pack;
|
|
||||||
|
|
||||||
private int _part1 = -1;
|
|
||||||
private (int, int) _word1 = (-1, -1);
|
|
||||||
|
|
||||||
private int _part2 = -1;
|
|
||||||
private (int, int) _word2 = (-1, -1);
|
|
||||||
|
|
||||||
private int _conj = -1;
|
|
||||||
|
|
||||||
internal PluginUi(Plugin plugin) {
|
internal PluginUi(Plugin plugin) {
|
||||||
this.Plugin = plugin;
|
this.Plugin = plugin;
|
||||||
|
this.MainWindow = new MainWindow(this.Plugin);
|
||||||
|
this.Viewer = new Viewer(this.Plugin);
|
||||||
|
this.ViewerButton = new ViewerButton(this.Plugin);
|
||||||
|
|
||||||
this.Plugin.Interface.UiBuilder.Draw += this.Draw;
|
this.Plugin.Interface.UiBuilder.Draw += this.Draw;
|
||||||
}
|
}
|
||||||
|
@ -34,374 +23,8 @@ public class PluginUi : IDisposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Draw() {
|
private void Draw() {
|
||||||
this.DrawWriter();
|
this.MainWindow.Draw();
|
||||||
this.DrawViewerButton();
|
this.ViewerButton.Draw();
|
||||||
this.DrawViewer();
|
this.Viewer.Draw();
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawWriter() {
|
|
||||||
if (!this.WriterVisible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ImGui.Begin(this.Plugin.Name, ref this.WriterVisible)) {
|
|
||||||
ImGui.End();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var packPrev = Pack.All.Value[this._pack].Name;
|
|
||||||
if (ImGui.BeginCombo("Pack", packPrev)) {
|
|
||||||
for (var i = 0; i < Pack.All.Value.Length; i++) {
|
|
||||||
var selPack = Pack.All.Value[i];
|
|
||||||
if (!ImGui.Selectable(selPack.Name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._pack = i;
|
|
||||||
|
|
||||||
this._part1 = -1;
|
|
||||||
this._word1 = (-1, -1);
|
|
||||||
this._conj = -1;
|
|
||||||
this._part2 = -1;
|
|
||||||
this._word2 = (-1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.EndCombo();
|
|
||||||
}
|
|
||||||
|
|
||||||
const string placeholder = "****";
|
|
||||||
|
|
||||||
void DrawPicker(string id, IReadOnlyList<string> items, ref int x) {
|
|
||||||
var preview = x == -1 ? "" : items[x].Replace("{0}", placeholder);
|
|
||||||
if (!ImGui.BeginCombo(id, preview)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.Selectable("<none>")) {
|
|
||||||
x = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < items.Count; i++) {
|
|
||||||
var template = items[i].Replace("{0}", placeholder);
|
|
||||||
if (ImGui.Selectable(template, i == x)) {
|
|
||||||
x = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.EndCombo();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawWordPicker(string id, IReadOnlyList<WordList> words, ref (int, int) x) {
|
|
||||||
var preview = x == (-1, -1) ? "" : words[x.Item1].Words[x.Item2];
|
|
||||||
if (!ImGui.BeginCombo(id, preview)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var listIdx = 0; listIdx < words.Count; listIdx++) {
|
|
||||||
var list = words[listIdx];
|
|
||||||
if (!ImGui.BeginMenu(list.Name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var wordIdx = 0; wordIdx < list.Words.Length; wordIdx++) {
|
|
||||||
if (ImGui.MenuItem(list.Words[wordIdx])) {
|
|
||||||
x = (listIdx, wordIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.EndCombo();
|
|
||||||
}
|
|
||||||
|
|
||||||
var pack = Pack.All.Value[this._pack];
|
|
||||||
|
|
||||||
var actualText = string.Empty;
|
|
||||||
if (this._part1 == -1) {
|
|
||||||
ImGui.TextUnformatted(placeholder);
|
|
||||||
} else {
|
|
||||||
var preview = new StringBuilder();
|
|
||||||
|
|
||||||
var template1 = pack.Templates[this._part1];
|
|
||||||
var word1 = this._word1 == (-1, -1) ? placeholder : pack.Words[this._word1.Item1].Words[this._word1.Item2];
|
|
||||||
preview.Append(string.Format(template1, word1));
|
|
||||||
|
|
||||||
if (this._conj != -1) {
|
|
||||||
var conj = pack.Conjunctions[this._conj];
|
|
||||||
if (conj.Length != 1 || !char.IsPunctuation(conj[0])) {
|
|
||||||
preview.Append('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
preview.Append(conj);
|
|
||||||
preview.Append(' ');
|
|
||||||
|
|
||||||
if (this._part2 != -1) {
|
|
||||||
var template2 = pack.Templates[this._part2];
|
|
||||||
var word2 = this._word2 == (-1, -1) ? placeholder : pack.Words[this._word2.Item1].Words[this._word2.Item2];
|
|
||||||
preview.Append(string.Format(template2, word2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actualText = preview.ToString();
|
|
||||||
ImGui.TextUnformatted(actualText);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.Separator();
|
|
||||||
|
|
||||||
DrawPicker("Template##part-1", pack.Templates, ref this._part1);
|
|
||||||
if (this._part1 > -1 && pack.Templates[this._part1].Contains("{0}")) {
|
|
||||||
DrawWordPicker("Word##word-1", pack.Words, ref this._word1);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawPicker("Conjunction##conj", pack.Conjunctions, ref this._conj);
|
|
||||||
|
|
||||||
if (this._conj != -1) {
|
|
||||||
DrawPicker("Template##part-2", pack.Templates, ref this._part2);
|
|
||||||
if (this._part2 > -1 && pack.Templates[this._part2].Contains("{0}")) {
|
|
||||||
DrawWordPicker("Word##word-2", pack.Words, ref this._word2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ClearIfNecessary();
|
|
||||||
|
|
||||||
var valid = this.ValidSetup();
|
|
||||||
if (!valid) {
|
|
||||||
ImGui.BeginDisabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.Button("Write") && valid && this.Plugin.ClientState.LocalPlayer is { } player) {
|
|
||||||
var req = new MessageRequest {
|
|
||||||
Territory = this.Plugin.ClientState.TerritoryType,
|
|
||||||
X = player.Position.X,
|
|
||||||
Y = player.Position.Y,
|
|
||||||
Z = player.Position.Z,
|
|
||||||
PackId = pack.Id,
|
|
||||||
Template1 = this._part1,
|
|
||||||
Word1List = this._word1.Item1 == -1 ? null : this._word1.Item1,
|
|
||||||
Word1Word = this._word1.Item2 == -1 ? null : this._word1.Item2,
|
|
||||||
Conjunction = this._conj == -1 ? null : this._conj,
|
|
||||||
Template2 = this._part2 == -1 ? null : this._part2,
|
|
||||||
Word2List = this._word2.Item1 == -1 ? null : this._word2.Item1,
|
|
||||||
Word2Word = this._word2.Item2 == -1 ? null : this._word2.Item2,
|
|
||||||
};
|
|
||||||
|
|
||||||
var json = JsonConvert.SerializeObject(req);
|
|
||||||
Task.Run(async () => {
|
|
||||||
var content = new StringContent(json) {
|
|
||||||
Headers = {
|
|
||||||
ContentType = new MediaTypeHeaderValue("application/json"),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
content.Headers.Add("X-Api-Key", this.Plugin.Config.ApiKey);
|
|
||||||
|
|
||||||
var resp = await new HttpClient().PostAsync("https://tryfingerbuthole.anna.lgbt/messages", content);
|
|
||||||
var id = await resp.Content.ReadAsStringAsync();
|
|
||||||
if (resp.IsSuccessStatusCode) {
|
|
||||||
var newMsg = new Message {
|
|
||||||
Id = Guid.Parse(id),
|
|
||||||
X = player.Position.X,
|
|
||||||
Y = player.Position.Y,
|
|
||||||
Z = player.Position.Z,
|
|
||||||
Text = actualText,
|
|
||||||
NegativeVotes = 0,
|
|
||||||
PositiveVotes = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Plugin.Messages.Add(newMsg);
|
|
||||||
this.ResetWriter();
|
|
||||||
this.WriterVisible = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
ImGui.EndDisabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.Plugin.ClientState.LocalPlayer is { } player2) {
|
|
||||||
foreach (var msg in this.Plugin.Messages.Nearby()) {
|
|
||||||
ImGui.TextUnformatted($"{msg.Text}: {Vector3.Distance(msg.Position, player2.Position):N2}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.End();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetWriter() {
|
|
||||||
this._part1 = this._part2 = this._conj = -1;
|
|
||||||
this._word1 = (-1, -1);
|
|
||||||
this._word2 = (-1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClearIfNecessary() {
|
|
||||||
if (this._pack == -1) {
|
|
||||||
this._part1 = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pack = Pack.All.Value[this._pack];
|
|
||||||
|
|
||||||
if (this._part1 == -1 || !pack.Templates[this._part1].Contains("{0}")) {
|
|
||||||
this._word1 = (-1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._conj == -1) {
|
|
||||||
this._part2 = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._part2 == -1 || !pack.Templates[this._part2].Contains("{0}")) {
|
|
||||||
this._word2 = (-1, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidSetup() {
|
|
||||||
if (this._pack == -1 || this._part1 == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pack = Pack.All.Value[this._pack];
|
|
||||||
var template1 = pack.Templates[this._part1];
|
|
||||||
var temp1Variable = template1.Contains("{0}");
|
|
||||||
|
|
||||||
switch (temp1Variable) {
|
|
||||||
case true when this._word1 == (-1, -1):
|
|
||||||
case false when this._word1 != (-1, -1):
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._conj == -1 && (this._part2 != -1 || this._word2 != (-1, -1))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._conj != -1) {
|
|
||||||
if (this._part2 == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var template2 = pack.Templates[this._part2];
|
|
||||||
var temp2Variable = template2.Contains("{0}");
|
|
||||||
|
|
||||||
switch (temp2Variable) {
|
|
||||||
case true when this._word2 == (-1, -1):
|
|
||||||
case false when this._word2 != (-1, -1):
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawViewerButton() {
|
|
||||||
if (this.ViewerVisible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var nearby = this.Plugin.Messages.Nearby().ToList();
|
|
||||||
if (nearby.Count == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.SetNextWindowBgAlpha(0.5f);
|
|
||||||
if (!ImGui.Begin("##ogt-viewer-button", ImGuiWindowFlags.NoTitleBar)) {
|
|
||||||
ImGui.End();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var label = "View message";
|
|
||||||
if (nearby.Count > 1) {
|
|
||||||
label += "s";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.Button(label)) {
|
|
||||||
this.ViewerVisible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.End();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _viewerIdx;
|
|
||||||
|
|
||||||
private void DrawViewer() {
|
|
||||||
if (!this.ViewerVisible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ImGui.Begin("Messages", ref this.ViewerVisible)) {
|
|
||||||
ImGui.End();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.IsWindowAppearing()) {
|
|
||||||
this._viewerIdx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var nearby = this.Plugin.Messages.Nearby()
|
|
||||||
.OrderBy(msg => msg.Id)
|
|
||||||
.ToList();
|
|
||||||
if (nearby.Count == 0) {
|
|
||||||
ImGui.TextUnformatted("No nearby messages");
|
|
||||||
goto End;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ImGui.BeginTable("##viewer-table", 3)) {
|
|
||||||
goto End;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.TableSetupColumn("##prev-arrow", ImGuiTableColumnFlags.WidthFixed);
|
|
||||||
ImGui.TableSetupColumn("##content", ImGuiTableColumnFlags.WidthStretch);
|
|
||||||
ImGui.TableSetupColumn("##next-arrow", ImGuiTableColumnFlags.WidthFixed);
|
|
||||||
ImGui.TableNextRow();
|
|
||||||
|
|
||||||
if (ImGui.TableSetColumnIndex(0)) {
|
|
||||||
var height = ImGui.GetContentRegionAvail().Y;
|
|
||||||
var buttonHeight = ImGuiHelpers.GetButtonSize("<").Y;
|
|
||||||
ImGui.Dummy(new Vector2(1, height / 2 - buttonHeight / 2 - ImGui.GetStyle().ItemSpacing.Y));
|
|
||||||
if (this._viewerIdx == 0) {
|
|
||||||
ImGui.BeginDisabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.Button("<")) {
|
|
||||||
this._viewerIdx -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._viewerIdx == 0) {
|
|
||||||
ImGui.EndDisabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.TableSetColumnIndex(1) && this._viewerIdx > -1 && this._viewerIdx < nearby.Count) {
|
|
||||||
var message = nearby[this._viewerIdx];
|
|
||||||
var size = ImGui.CalcTextSize(message.Text, ImGui.GetContentRegionAvail().X);
|
|
||||||
var height = ImGui.GetContentRegionAvail().Y;
|
|
||||||
ImGui.Dummy(new Vector2(1, height / 2 - size.Y / 2 - ImGui.GetStyle().ItemSpacing.Y));
|
|
||||||
|
|
||||||
ImGui.PushTextWrapPos();
|
|
||||||
ImGui.TextUnformatted(message.Text);
|
|
||||||
ImGui.PopTextWrapPos();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.TableSetColumnIndex(2)) {
|
|
||||||
var height = ImGui.GetContentRegionAvail().Y;
|
|
||||||
var buttonHeight = ImGuiHelpers.GetButtonSize(">").Y;
|
|
||||||
ImGui.Dummy(new Vector2(1, height / 2 - buttonHeight / 2 - ImGui.GetStyle().ItemSpacing.Y));
|
|
||||||
|
|
||||||
if (this._viewerIdx == nearby.Count - 1) {
|
|
||||||
ImGui.BeginDisabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.Button(">")) {
|
|
||||||
this._viewerIdx += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._viewerIdx == nearby.Count - 1) {
|
|
||||||
ImGui.EndDisabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.EndTable();
|
|
||||||
|
|
||||||
End:
|
|
||||||
ImGui.End();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
client/Ui/MainWindow.cs
Normal file
46
client/Ui/MainWindow.cs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
using ImGuiNET;
|
||||||
|
using OrangeGuidanceTomestone.Ui.MainWindowTabs;
|
||||||
|
|
||||||
|
namespace OrangeGuidanceTomestone.Ui;
|
||||||
|
|
||||||
|
internal class MainWindow {
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
private List<ITab> Tabs { get; }
|
||||||
|
|
||||||
|
internal bool Visible;
|
||||||
|
|
||||||
|
internal MainWindow(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
this.Tabs = new List<ITab> {
|
||||||
|
new Write(this.Plugin),
|
||||||
|
new MessageList(this.Plugin),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Draw() {
|
||||||
|
if (!this.Visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui.Begin(this.Plugin.Name, ref this.Visible)) {
|
||||||
|
ImGui.End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.BeginTabBar("##ogt-main-tabs")) {
|
||||||
|
foreach (var tab in this.Tabs) {
|
||||||
|
if (!ImGui.BeginTabItem(tab.Name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.Draw();
|
||||||
|
|
||||||
|
ImGui.EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndTabBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
}
|
||||||
|
}
|
6
client/Ui/MainWindowTabs/ITab.cs
Normal file
6
client/Ui/MainWindowTabs/ITab.cs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
namespace OrangeGuidanceTomestone.Ui.MainWindowTabs;
|
||||||
|
|
||||||
|
public interface ITab {
|
||||||
|
public string Name { get; }
|
||||||
|
public void Draw();
|
||||||
|
}
|
53
client/Ui/MainWindowTabs/MessageList.cs
Normal file
53
client/Ui/MainWindowTabs/MessageList.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using ImGuiNET;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using OrangeGuidanceTomestone.Helpers;
|
||||||
|
|
||||||
|
namespace OrangeGuidanceTomestone.Ui.MainWindowTabs;
|
||||||
|
|
||||||
|
internal class MessageList : ITab {
|
||||||
|
public string Name => "Your messages";
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
|
||||||
|
private SemaphoreSlim MessagesMutex { get; } = new(1, 1);
|
||||||
|
private List<MessageWithTerritory> Messages { get; } = new();
|
||||||
|
|
||||||
|
internal MessageList(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw() {
|
||||||
|
if (ImGui.Button("Refresh")) {
|
||||||
|
this.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.MessagesMutex.Wait();
|
||||||
|
|
||||||
|
foreach (var message in this.Messages) {
|
||||||
|
ImGui.TextUnformatted(message.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.MessagesMutex.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Refresh() {
|
||||||
|
Task.Run(async () => {
|
||||||
|
var resp = await ServerHelper.SendRequest(
|
||||||
|
this.Plugin.Config.ApiKey,
|
||||||
|
HttpMethod.Get,
|
||||||
|
"/messages"
|
||||||
|
);
|
||||||
|
var json = await resp.Content.ReadAsStringAsync();
|
||||||
|
var messages = JsonConvert.DeserializeObject<MessageWithTerritory[]>(json)!;
|
||||||
|
await this.MessagesMutex.WaitAsync();
|
||||||
|
this.Messages.Clear();
|
||||||
|
this.Messages.AddRange(messages);
|
||||||
|
this.MessagesMutex.Release();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Add(MessageWithTerritory message) {
|
||||||
|
this.Messages.Clear();
|
||||||
|
this.Messages.Add(message);
|
||||||
|
this.MessagesMutex.Release();
|
||||||
|
}
|
||||||
|
}
|
252
client/Ui/MainWindowTabs/Write.cs
Normal file
252
client/Ui/MainWindowTabs/Write.cs
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
using System.Text;
|
||||||
|
using ImGuiNET;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using OrangeGuidanceTomestone.Helpers;
|
||||||
|
|
||||||
|
namespace OrangeGuidanceTomestone.Ui.MainWindowTabs;
|
||||||
|
|
||||||
|
internal class Write : ITab {
|
||||||
|
public string Name => "Write";
|
||||||
|
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
|
||||||
|
private int _pack;
|
||||||
|
private int _part1 = -1;
|
||||||
|
private (int, int) _word1 = (-1, -1);
|
||||||
|
private int _conj = -1;
|
||||||
|
private int _part2 = -1;
|
||||||
|
private (int, int) _word2 = (-1, -1);
|
||||||
|
|
||||||
|
internal Write(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw() {
|
||||||
|
var packPrev = Pack.All.Value[this._pack].Name;
|
||||||
|
if (ImGui.BeginCombo("Pack", packPrev)) {
|
||||||
|
for (var i = 0; i < Pack.All.Value.Length; i++) {
|
||||||
|
var selPack = Pack.All.Value[i];
|
||||||
|
if (!ImGui.Selectable(selPack.Name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._pack = i;
|
||||||
|
this.ResetWriter();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
const string placeholder = "****";
|
||||||
|
|
||||||
|
void DrawPicker(string id, IReadOnlyList<string> items, ref int x) {
|
||||||
|
var preview = x == -1 ? "" : items[x].Replace("{0}", placeholder);
|
||||||
|
if (!ImGui.BeginCombo(id, preview)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.Selectable("<none>")) {
|
||||||
|
x = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < items.Count; i++) {
|
||||||
|
var template = items[i].Replace("{0}", placeholder);
|
||||||
|
if (ImGui.Selectable(template, i == x)) {
|
||||||
|
x = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawWordPicker(string id, IReadOnlyList<WordList> words, ref (int, int) x) {
|
||||||
|
var preview = x == (-1, -1) ? "" : words[x.Item1].Words[x.Item2];
|
||||||
|
if (!ImGui.BeginCombo(id, preview)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var listIdx = 0; listIdx < words.Count; listIdx++) {
|
||||||
|
var list = words[listIdx];
|
||||||
|
if (!ImGui.BeginMenu(list.Name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var wordIdx = 0; wordIdx < list.Words.Length; wordIdx++) {
|
||||||
|
if (ImGui.MenuItem(list.Words[wordIdx])) {
|
||||||
|
x = (listIdx, wordIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
var pack = Pack.All.Value[this._pack];
|
||||||
|
|
||||||
|
var actualText = string.Empty;
|
||||||
|
if (this._part1 == -1) {
|
||||||
|
ImGui.TextUnformatted(placeholder);
|
||||||
|
} else {
|
||||||
|
var preview = new StringBuilder();
|
||||||
|
|
||||||
|
var template1 = pack.Templates[this._part1];
|
||||||
|
var word1 = this._word1 == (-1, -1) ? placeholder : pack.Words[this._word1.Item1].Words[this._word1.Item2];
|
||||||
|
preview.Append(string.Format(template1, word1));
|
||||||
|
|
||||||
|
if (this._conj != -1) {
|
||||||
|
var conj = pack.Conjunctions[this._conj];
|
||||||
|
if (conj.Length != 1 || !char.IsPunctuation(conj[0])) {
|
||||||
|
preview.Append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
preview.Append(conj);
|
||||||
|
preview.Append(' ');
|
||||||
|
|
||||||
|
if (this._part2 != -1) {
|
||||||
|
var template2 = pack.Templates[this._part2];
|
||||||
|
var word2 = this._word2 == (-1, -1) ? placeholder : pack.Words[this._word2.Item1].Words[this._word2.Item2];
|
||||||
|
preview.Append(string.Format(template2, word2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actualText = preview.ToString();
|
||||||
|
ImGui.TextUnformatted(actualText);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
DrawPicker("Template##part-1", pack.Templates, ref this._part1);
|
||||||
|
if (this._part1 > -1 && pack.Templates[this._part1].Contains("{0}")) {
|
||||||
|
DrawWordPicker("Word##word-1", pack.Words, ref this._word1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawPicker("Conjunction##conj", pack.Conjunctions, ref this._conj);
|
||||||
|
|
||||||
|
if (this._conj != -1) {
|
||||||
|
DrawPicker("Template##part-2", pack.Templates, ref this._part2);
|
||||||
|
if (this._part2 > -1 && pack.Templates[this._part2].Contains("{0}")) {
|
||||||
|
DrawWordPicker("Word##word-2", pack.Words, ref this._word2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ClearIfNecessary();
|
||||||
|
|
||||||
|
var valid = this.ValidSetup();
|
||||||
|
if (!valid) {
|
||||||
|
ImGui.BeginDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.Button("Write") && valid && this.Plugin.ClientState.LocalPlayer is { } player) {
|
||||||
|
var req = new MessageRequest {
|
||||||
|
Territory = this.Plugin.ClientState.TerritoryType,
|
||||||
|
X = player.Position.X,
|
||||||
|
Y = player.Position.Y,
|
||||||
|
Z = player.Position.Z,
|
||||||
|
PackId = pack.Id,
|
||||||
|
Template1 = this._part1,
|
||||||
|
Word1List = this._word1.Item1 == -1 ? null : this._word1.Item1,
|
||||||
|
Word1Word = this._word1.Item2 == -1 ? null : this._word1.Item2,
|
||||||
|
Conjunction = this._conj == -1 ? null : this._conj,
|
||||||
|
Template2 = this._part2 == -1 ? null : this._part2,
|
||||||
|
Word2List = this._word2.Item1 == -1 ? null : this._word2.Item1,
|
||||||
|
Word2Word = this._word2.Item2 == -1 ? null : this._word2.Item2,
|
||||||
|
};
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(req);
|
||||||
|
Task.Run(async () => {
|
||||||
|
var resp = await ServerHelper.SendRequest(
|
||||||
|
this.Plugin.Config.ApiKey,
|
||||||
|
HttpMethod.Post,
|
||||||
|
"/messages",
|
||||||
|
"application/json",
|
||||||
|
new StringContent(json)
|
||||||
|
);
|
||||||
|
var id = await resp.Content.ReadAsStringAsync();
|
||||||
|
if (resp.IsSuccessStatusCode) {
|
||||||
|
var newMsg = new Message {
|
||||||
|
Id = Guid.Parse(id),
|
||||||
|
X = player.Position.X,
|
||||||
|
Y = player.Position.Y,
|
||||||
|
Z = player.Position.Z,
|
||||||
|
Text = actualText,
|
||||||
|
NegativeVotes = 0,
|
||||||
|
PositiveVotes = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Plugin.Messages.Add(newMsg);
|
||||||
|
this.ResetWriter();
|
||||||
|
this.Plugin.Ui.MainWindow.Visible = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetWriter() {
|
||||||
|
this._part1 = this._part2 = this._conj = -1;
|
||||||
|
this._word1 = (-1, -1);
|
||||||
|
this._word2 = (-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearIfNecessary() {
|
||||||
|
if (this._pack == -1) {
|
||||||
|
this._part1 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pack = Pack.All.Value[this._pack];
|
||||||
|
|
||||||
|
if (this._part1 == -1 || !pack.Templates[this._part1].Contains("{0}")) {
|
||||||
|
this._word1 = (-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._conj == -1) {
|
||||||
|
this._part2 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._part2 == -1 || !pack.Templates[this._part2].Contains("{0}")) {
|
||||||
|
this._word2 = (-1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidSetup() {
|
||||||
|
if (this._pack == -1 || this._part1 == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pack = Pack.All.Value[this._pack];
|
||||||
|
var template1 = pack.Templates[this._part1];
|
||||||
|
var temp1Variable = template1.Contains("{0}");
|
||||||
|
|
||||||
|
switch (temp1Variable) {
|
||||||
|
case true when this._word1 == (-1, -1):
|
||||||
|
case false when this._word1 != (-1, -1):
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._conj == -1 && (this._part2 != -1 || this._word2 != (-1, -1))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._conj != -1) {
|
||||||
|
if (this._part2 == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var template2 = pack.Templates[this._part2];
|
||||||
|
var temp2Variable = template2.Contains("{0}");
|
||||||
|
|
||||||
|
switch (temp2Variable) {
|
||||||
|
case true when this._word2 == (-1, -1):
|
||||||
|
case false when this._word2 != (-1, -1):
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
100
client/Ui/Viewer.cs
Normal file
100
client/Ui/Viewer.cs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using ImGuiNET;
|
||||||
|
|
||||||
|
namespace OrangeGuidanceTomestone.Ui;
|
||||||
|
|
||||||
|
internal class Viewer {
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
|
||||||
|
internal bool Visible;
|
||||||
|
|
||||||
|
private int _idx;
|
||||||
|
|
||||||
|
internal Viewer(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Draw() {
|
||||||
|
if (!this.Visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui.Begin("Messages", ref this.Visible)) {
|
||||||
|
ImGui.End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.IsWindowAppearing()) {
|
||||||
|
this._idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nearby = this.Plugin.Messages.Nearby()
|
||||||
|
.OrderBy(msg => msg.Id)
|
||||||
|
.ToList();
|
||||||
|
if (nearby.Count == 0) {
|
||||||
|
ImGui.TextUnformatted("No nearby messages");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui.BeginTable("##viewer-table", 3)) {
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.TableSetupColumn("##prev-arrow", ImGuiTableColumnFlags.WidthFixed);
|
||||||
|
ImGui.TableSetupColumn("##content", ImGuiTableColumnFlags.WidthStretch);
|
||||||
|
ImGui.TableSetupColumn("##next-arrow", ImGuiTableColumnFlags.WidthFixed);
|
||||||
|
ImGui.TableNextRow();
|
||||||
|
|
||||||
|
if (ImGui.TableSetColumnIndex(0)) {
|
||||||
|
var height = ImGui.GetContentRegionAvail().Y;
|
||||||
|
var buttonHeight = ImGuiHelpers.GetButtonSize("<").Y;
|
||||||
|
ImGui.Dummy(new Vector2(1, height / 2 - buttonHeight / 2 - ImGui.GetStyle().ItemSpacing.Y));
|
||||||
|
if (this._idx == 0) {
|
||||||
|
ImGui.BeginDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.Button("<")) {
|
||||||
|
this._idx -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._idx == 0) {
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.TableSetColumnIndex(1) && this._idx > -1 && this._idx < nearby.Count) {
|
||||||
|
var message = nearby[this._idx];
|
||||||
|
var size = ImGui.CalcTextSize(message.Text, ImGui.GetContentRegionAvail().X);
|
||||||
|
var height = ImGui.GetContentRegionAvail().Y;
|
||||||
|
ImGui.Dummy(new Vector2(1, height / 2 - size.Y / 2 - ImGui.GetStyle().ItemSpacing.Y));
|
||||||
|
|
||||||
|
ImGui.PushTextWrapPos();
|
||||||
|
ImGui.TextUnformatted(message.Text);
|
||||||
|
ImGui.PopTextWrapPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.TableSetColumnIndex(2)) {
|
||||||
|
var height = ImGui.GetContentRegionAvail().Y;
|
||||||
|
var buttonHeight = ImGuiHelpers.GetButtonSize(">").Y;
|
||||||
|
ImGui.Dummy(new Vector2(1, height / 2 - buttonHeight / 2 - ImGui.GetStyle().ItemSpacing.Y));
|
||||||
|
|
||||||
|
if (this._idx == nearby.Count - 1) {
|
||||||
|
ImGui.BeginDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.Button(">")) {
|
||||||
|
this._idx += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._idx == nearby.Count - 1) {
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndTable();
|
||||||
|
|
||||||
|
End:
|
||||||
|
ImGui.End();
|
||||||
|
}
|
||||||
|
}
|
39
client/Ui/ViewerButton.cs
Normal file
39
client/Ui/ViewerButton.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
using ImGuiNET;
|
||||||
|
|
||||||
|
namespace OrangeGuidanceTomestone.Ui;
|
||||||
|
|
||||||
|
internal class ViewerButton {
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
|
||||||
|
internal ViewerButton(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Draw() {
|
||||||
|
if (this.Plugin.Ui.Viewer.Visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nearby = this.Plugin.Messages.Nearby().ToList();
|
||||||
|
if (nearby.Count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SetNextWindowBgAlpha(0.5f);
|
||||||
|
if (!ImGui.Begin("##ogt-viewer-button", ImGuiWindowFlags.NoTitleBar)) {
|
||||||
|
ImGui.End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var label = "View message";
|
||||||
|
if (nearby.Count > 1) {
|
||||||
|
label += "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.Button(label)) {
|
||||||
|
this.Plugin.Ui.Viewer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ pub struct RetrievedMessage {
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct RetrievedMessageTerritory {
|
pub struct RetrievedMessageTerritory {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
puv territory: i64,
|
pub territory: i64,
|
||||||
pub x: f64,
|
pub x: f64,
|
||||||
pub y: f64,
|
pub y: f64,
|
||||||
pub z: f64,
|
pub z: f64,
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl Pack {
|
||||||
if let Some(template_2_idx) = template_2_idx {
|
if let Some(template_2_idx) = template_2_idx {
|
||||||
let conj = self.conjunctions.get(conj_idx)?;
|
let conj = self.conjunctions.get(conj_idx)?;
|
||||||
let is_punc = conj.len() == 1 && conj.chars().next().map(|x| x.is_ascii_punctuation()).unwrap_or(false);
|
let is_punc = conj.len() == 1 && conj.chars().next().map(|x| x.is_ascii_punctuation()).unwrap_or(false);
|
||||||
if is_punch {
|
if is_punc {
|
||||||
formatted.push_str(conj);
|
formatted.push_str(conj);
|
||||||
formatted.push('\n');
|
formatted.push('\n');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -77,6 +77,7 @@ async fn handle_rejection(err: Rejection) -> Result<impl Reply, Infallible> {
|
||||||
WebError::InvalidAuthToken => StatusCode::BAD_REQUEST,
|
WebError::InvalidAuthToken => StatusCode::BAD_REQUEST,
|
||||||
WebError::InvalidPackId => StatusCode::NOT_FOUND,
|
WebError::InvalidPackId => StatusCode::NOT_FOUND,
|
||||||
WebError::InvalidIndex => StatusCode::NOT_FOUND,
|
WebError::InvalidIndex => StatusCode::NOT_FOUND,
|
||||||
|
WebError::TooManyMessages => StatusCode::BAD_REQUEST,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("{:#?}", err);
|
eprintln!("{:#?}", err);
|
||||||
|
|
|
@ -28,7 +28,7 @@ async fn logic(state: Arc<State>, id: i64, message: Message) -> Result<impl Repl
|
||||||
pack.format(
|
pack.format(
|
||||||
message.template_1,
|
message.template_1,
|
||||||
message.word_1_list.and_then(|list| message.word_1_word.map(|word| (list, word))),
|
message.word_1_list.and_then(|list| message.word_1_word.map(|word| (list, word))),
|
||||||
message.conjugation,
|
message.conjunction,
|
||||||
message.template_2,
|
message.template_2,
|
||||||
message.word_2_list.and_then(|list| message.word_2_word.map(|word| (list, word))),
|
message.word_2_list.and_then(|list| message.word_2_word.map(|word| (list, word))),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user