From 9d21e8bd21ea8b266919924bf5f6c2aea469f9a1 Mon Sep 17 00:00:00 2001 From: N <24514810+tnoctua@users.noreply.github.com> Date: Wed, 25 Jun 2025 18:59:25 -0400 Subject: [PATCH] Add Feature: Mail-To Contacts This commit adds support for contacting authors/contributors by email if they have added their contact information in accordance with the fabric.mod.json specification. If an entry has contact information and if that contact information contains an email address, an email emoticon will be displayed next to their name in the menu. Clicking a line with an email emoticon will prompt to open a mailto:address link. --- .../gui/widget/DescriptionListWidget.java | 42 ++++++++++++++++++- .../terraformersmc/modmenu/util/mod/Mod.java | 3 ++ .../util/mod/fabric/FabricDummyParentMod.java | 6 +++ .../modmenu/util/mod/fabric/FabricMod.java | 15 +++++++ src/main/resources/fabric.mod.json | 3 +- 5 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/terraformersmc/modmenu/gui/widget/DescriptionListWidget.java b/src/main/java/com/terraformersmc/modmenu/gui/widget/DescriptionListWidget.java index 5184e463..444675ad 100644 --- a/src/main/java/com/terraformersmc/modmenu/gui/widget/DescriptionListWidget.java +++ b/src/main/java/com/terraformersmc/modmenu/gui/widget/DescriptionListWidget.java @@ -4,6 +4,7 @@ import com.terraformersmc.modmenu.config.ModMenuConfig; import com.terraformersmc.modmenu.gui.ModsScreen; import com.terraformersmc.modmenu.util.mod.Mod; +import net.fabricmc.loader.api.metadata.ContactInformation; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; @@ -243,7 +244,12 @@ private void rebuildUI() { indent = 16; for (var line : textRenderer.wrapLines(Text.literal(contributor), wrapWidth - 24)) { - children().add(new DescriptionEntry(line, indent)); + ContactInformation contact = mod.getContact(contributor); + if (contact != null && contact.get("email").isPresent()) { + children().add(new MailableContactEntry(line, contact.get("email").get(), indent)); + } else { + children().add(new DescriptionEntry(line, indent)); + } indent = 24; } } @@ -381,4 +387,38 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { return super.mouseClicked(mouseX, mouseY, button); } } + + protected class MailableContactEntry extends DescriptionEntry { + private final String email; + + public MailableContactEntry(OrderedText text, String email, int indent) { + super(text, indent); + this.email = email; + } + + public MailableContactEntry(OrderedText text, String link) { + this(text, link, 0); + } + + @Override + public void render(DrawContext drawContext, int index, int y, int x, int itemWidth, int itemHeight, int mouseX, int mouseY, boolean isSelected, float delta) { + super.render(drawContext, index, y, x, itemWidth, itemHeight, mouseX, mouseY, isSelected, delta); + drawContext.drawTextWithShadow(textRenderer, Text.literal(" ").append(Text.literal("✉")), x + indent + textRenderer.getWidth(text) + 1, y, 0xFFAAAAAA); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (isMouseOver(mouseX, mouseY)) { + client.setScreen(new ConfirmLinkScreen((open) -> { + if (open) { + Util.getOperatingSystem().open("mailto:" + email); + } + client.setScreen(parent); + }, "mailto:" + email, false)); + } + + return super.mouseClicked(mouseX, mouseY, button); + } + } + } diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java b/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java index b5bd8ac9..f2c6a462 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/Mod.java @@ -7,6 +7,7 @@ import com.terraformersmc.modmenu.config.ModMenuConfig; import com.terraformersmc.modmenu.util.mod.fabric.FabricIconHandler; import eu.pb4.placeholders.api.ParserContext; +import net.fabricmc.loader.api.metadata.ContactInformation; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.texture.NativeImageBackedTexture; import net.minecraft.text.Text; @@ -80,6 +81,8 @@ default Text getFormattedDescription() { @NotNull List getAuthors(); + ContactInformation getContact(String author); + /** * @return a mapping of contributors to their roles. */ diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java index 532822c9..c226073d 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricDummyParentMod.java @@ -7,6 +7,7 @@ import com.terraformersmc.modmenu.util.mod.Mod; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.metadata.ContactInformation; import net.minecraft.client.texture.NativeImageBackedTexture; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -94,6 +95,11 @@ public FabricDummyParentMod(FabricMod host, String id) { } @Override + public ContactInformation getContact(String author) { + return null; + } + + @Override public @NotNull Map> getContributors() { return Map.of(); } diff --git a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java index 995b0e87..7799a086 100644 --- a/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java +++ b/src/main/java/com/terraformersmc/modmenu/util/mod/fabric/FabricMod.java @@ -237,6 +237,21 @@ public FabricMod(ModContainer modContainer, Set modpackMods) { return authors; } + @Override + public ContactInformation getContact(String author) { + for (Person person : metadata.getAuthors()) { + if (person.getName().equals(author)) { + return person.getContact(); + } + } + for (Person person : metadata.getContributors()) { + if (person.getName().equals(author)) { + return person.getContact(); + } + } + return null; + } + @Override public @NotNull Map> getContributors() { var contributors = new LinkedHashMap>(); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 644cc877..2b3682b5 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -99,7 +99,8 @@ "Pyrrha", "sakura-ryoko", "gniftygnome", - "lowercasebtw" + "lowercasebtw", + "tnoctua" ], "description": "Adds a mod menu to view the list of mods you have installed.", "mixins": [