77import com.cope.meteoraddons.util.IconCache;
88import meteordevelopment.meteorclient.gui.GuiTheme;
99import meteordevelopment.meteorclient.gui.WindowScreen;
10- import meteordevelopment.meteorclient.gui.widgets.containers.WTable;
10+ import meteordevelopment.meteorclient.gui.widgets.containers.WHorizontalList;
11+ import meteordevelopment.meteorclient.gui.widgets.containers.WSection;
1112import meteordevelopment.meteorclient.gui.widgets.containers.WVerticalList;
1213import meteordevelopment.meteorclient.gui.widgets.pressable.WButton;
1314import meteordevelopment.meteorclient.renderer.Texture;
1415import meteordevelopment.meteorclient.utils.network.MeteorExecutor;
1516import net.minecraft.client.gui.screen.Screen;
1617import net.minecraft.util.Util;
1718
19+ import com.cope.meteoraddons.util.TimeUtil;
20+
1821import java.util.List;
1922
2023import static meteordevelopment.meteorclient.MeteorClient.mc;
24+ import static meteordevelopment.meteorclient.utils.Utils.getWindowWidth;
2125
2226/**
2327 * Detail screen for viewing and downloading an addon.
@@ -34,132 +38,116 @@ public AddonDetailScreen(GuiTheme theme, Addon addon, Screen parent) {
3438
3539 @Override
3640 public void initWidgets() {
41+ // Header Section (Icon + Details)
42+ WHorizontalList header = add(theme.horizontalList()).expandX().widget();
43+
3744 // Icon
3845 Texture iconTexture = IconCache.get(addon);
39- add(theme.texture(96, 96, 0, iconTexture)).centerX();
40-
41- // Name
42- WTable header = add(theme.table()).expandX().widget();
43- header.add(theme.label(addon.getName(), true)).expandCellX();
46+ header.add(theme.texture(64, 64, 0, iconTexture)).widget();
47+
48+ // Details (Name, Authors, Version, Verified)
49+ WVerticalList details = header.add(theme.verticalList()).expandX().widget();
50+
51+ WHorizontalList titleRow = details.add(theme.horizontalList()).widget();
52+ titleRow.add(theme.label(addon.getName(), true)); // Title
53+
54+ if (addon.isInstalled()) {
55+ Texture installedIcon = IconCache.getInstalledIndicator();
56+ if (installedIcon != null) {
57+ double size = theme.textHeight(true);
58+ titleRow.add(theme.texture(size, size, 0, installedIcon)).padLeft(4);
59+ }
60+ titleRow.add(theme.label("(Installed)", true).color(theme.textSecondaryColor())).padLeft(4);
61+ }
4462
45- // Show verified badge for online addons
4663 if (addon instanceof OnlineAddon) {
4764 AddonMetadata metadata = ((OnlineAddon) addon).getMetadata();
4865 if (metadata.verified) {
49- header .add(theme.label("✓ Verified"));
66+ details .add(theme.label("Verified").color(theme.textSecondaryColor() ));
5067 }
5168 }
69+
70+ String version = addon.getVersion();
71+ if (version != null && !version.isEmpty()) {
72+ details.add(theme.label("Version: " + version).color(theme.textSecondaryColor()));
73+ }
5274
53- // Description
54- addon.getDescription().ifPresent(desc -> {
55- add(theme.label(desc)).expandX();
56- });
57-
58- // Authors
5975 List<String> authors = addon.getAuthors();
6076 if (!authors.isEmpty()) {
61- WVerticalList authorsList = add(theme.verticalList()).expandX().widget();
62- authorsList.add(theme.label("Authors:"));
63- for (String author : authors) {
64- authorsList.add(theme.label(" • " + author));
65- }
66- }
67-
68- // Version
69- String version = addon.getVersion();
70- if (version != null && !version.isEmpty()) {
71- add(theme.label("Version: " + version)).expandX();
77+ details.add(theme.label("By: " + String.join(", ", authors)).color(theme.textSecondaryColor()));
7278 }
7379
7480 add(theme.horizontalSeparator()).expandX();
7581
76- // Stats (only for online addons)
82+ // Description
83+ addon.getDescription().ifPresent(desc -> {
84+ add(theme.label(desc, getWindowWidth() / 2.0));
85+ });
86+
87+ // Stats (Online Addons only)
7788 if (addon instanceof OnlineAddon) {
78- AddonMetadata metadata = ((OnlineAddon) addon).getMetadata();
79- if (metadata.repo != null) {
80- WTable stats = add(theme.table()).expandX().widget();
81- stats.add(theme.label("Stars: "));
82- stats.add(theme.label(String.valueOf(metadata.repo.stars)));
83- stats.row();
84- stats.add(theme.label("Downloads: "));
85- stats.add(theme.label(String.valueOf(metadata.repo.downloads)));
86- stats.row();
87- stats.add(theme.label("Last Update: "));
88- stats.add(theme.label(metadata.repo.last_update));
89-
90- add(theme.horizontalSeparator()).expandX();
91- }
92-
93- // Features
94- if (metadata.features != null) {
95- WVerticalList featuresList = add(theme.verticalList()).expandX().widget();
96-
97- if (metadata.features.modules != null && !metadata.features.modules.isEmpty()) {
98- featuresList.add(theme.label("Modules (" + metadata.features.modules.size() + ")"));
99- int count = 0;
100- for (String module : metadata.features.modules) {
101- if (count++ >= 10) {
102- featuresList.add(theme.label(" ... and " + (metadata.features.modules.size() - 10) + " more"));
103- break;
104- }
105- featuresList.add(theme.label(" • " + module));
106- }
107- }
108-
109- if (metadata.features.commands != null && !metadata.features.commands.isEmpty()) {
110- featuresList.add(theme.label("Commands (" + metadata.features.commands.size() + ")"));
111- for (String command : metadata.features.commands) {
112- featuresList.add(theme.label(" • " + command));
113- }
114- }
115-
116- if (metadata.features.hud_elements != null && !metadata.features.hud_elements.isEmpty()) {
117- featuresList.add(theme.label("HUD Elements (" + metadata.features.hud_elements.size() + ")"));
118- for (String hud : metadata.features.hud_elements) {
119- featuresList.add(theme.label(" • " + hud));
120- }
121- }
122-
123- add(theme.horizontalSeparator()).expandX();
124- }
125- }
126-
127- // Links
128- WTable links = add(theme.table()).expandX().widget();
129- boolean hasLinks = false;
130-
131- if (addon.getGithubUrl().isPresent()) {
132- WButton githubButton = links.add(theme.button("GitHub")).expandCellX().widget();
133- final String githubUrl = addon.getGithubUrl().get();
134- githubButton.action = () -> Util.getOperatingSystem().open(githubUrl);
135- hasLinks = true;
136- }
137-
138- if (addon.getDiscordUrl().isPresent()) {
139- WButton discordButton = links.add(theme.button("Discord")).expandCellX().widget();
140- final String discordUrl = addon.getDiscordUrl().get();
141- discordButton.action = () -> Util.getOperatingSystem().open(discordUrl);
142- hasLinks = true;
143- }
144-
145- if (addon.getHomepageUrl().isPresent()) {
146- WButton homepageButton = links.add(theme.button("Homepage")).expandCellX().widget();
147- final String homepageUrl = addon.getHomepageUrl().get();
148- homepageButton.action = () -> Util.getOperatingSystem().open(homepageUrl);
149- hasLinks = true;
89+ AddonMetadata metadata = ((OnlineAddon) addon).getMetadata();
90+ if (metadata.repo != null) {
91+ WHorizontalList stats = add(theme.horizontalList()).centerX().widget();
92+ stats.add(theme.label("Stars: " + metadata.repo.stars));
93+ stats.add(theme.label("Downloads: " + metadata.repo.downloads)).padHorizontal(10);
94+ stats.add(theme.label("Updated: " + TimeUtil.getRelativeTime(metadata.repo.last_update)));
95+ }
96+
97+ // Features Section
98+ if (metadata.features != null) {
99+ boolean hasFeatures = (metadata.features.modules != null && !metadata.features.modules.isEmpty()) ||
100+ (metadata.features.commands != null && !metadata.features.commands.isEmpty()) ||
101+ (metadata.features.hud_elements != null && !metadata.features.hud_elements.isEmpty()) ||
102+ (metadata.features.custom_screens != null && !metadata.features.custom_screens.isEmpty());
103+
104+ if (hasFeatures) {
105+ WSection featuresSection = add(theme.section("Features", true)).expandX().widget();
106+
107+ boolean first = true;
108+
109+ if (metadata.features.modules != null && !metadata.features.modules.isEmpty()) {
110+ featuresSection.add(theme.label("Modules (" + metadata.features.modules.size() + "):"));
111+ String modulesStr = String.join(", ", metadata.features.modules);
112+ featuresSection.add(theme.label(modulesStr, getWindowWidth() / 2.0).color(theme.textSecondaryColor()));
113+ first = false;
114+ }
115+
116+ if (metadata.features.commands != null && !metadata.features.commands.isEmpty()) {
117+ if (!first) featuresSection.add(theme.horizontalSeparator()).expandX();
118+ featuresSection.add(theme.label("Commands (" + metadata.features.commands.size() + "):"));
119+ String cmdStr = String.join(", ", metadata.features.commands);
120+ featuresSection.add(theme.label(cmdStr, getWindowWidth() / 2.0).color(theme.textSecondaryColor()));
121+ first = false;
122+ }
123+
124+ if (metadata.features.hud_elements != null && !metadata.features.hud_elements.isEmpty()) {
125+ if (!first) featuresSection.add(theme.horizontalSeparator()).expandX();
126+ featuresSection.add(theme.label("HUD (" + metadata.features.hud_elements.size() + "):"));
127+ String hudStr = String.join(", ", metadata.features.hud_elements);
128+ featuresSection.add(theme.label(hudStr, getWindowWidth() / 2.0).color(theme.textSecondaryColor()));
129+ first = false;
130+ }
131+
132+ if (metadata.features.custom_screens != null && !metadata.features.custom_screens.isEmpty()) {
133+ if (!first) featuresSection.add(theme.horizontalSeparator()).expandX();
134+ featuresSection.add(theme.label("Screens (" + metadata.features.custom_screens.size() + "):"));
135+ String screensStr = String.join(", ", metadata.features.custom_screens);
136+ featuresSection.add(theme.label(screensStr, getWindowWidth() / 2.0).color(theme.textSecondaryColor()));
137+ first = false;
138+ }
139+ }
140+ }
150141 }
151142
152- if (hasLinks) {
153- add(theme.horizontalSeparator()).expandX();
154- }
143+ add(theme.horizontalSeparator()).expandX();
155144
156- // Download button (only for online addons )
157- WTable actions = add(theme.table ()).expandX ().widget();
145+ // Actions (Buttons )
146+ WHorizontalList actions = add(theme.horizontalList ()).right ().widget();
158147
159- if (addon.isInstalled()) {
160- actions.add(theme.label("✓ Installed")).expandCellX();
161- } else if (addon instanceof OnlineAddon) {
162- WButton downloadButton = actions.add(theme.button("Download")).expandCellX().widget();
148+ // Download/Install Button
149+ if (!addon.isInstalled() && addon instanceof OnlineAddon) {
150+ WButton downloadButton = actions.add(theme.button("Download")).widget();
163151 downloadButton.action = () -> {
164152 downloadButton.set("Downloading...");
165153 MeteorExecutor.execute(() -> {
@@ -175,7 +163,25 @@ public void initWidgets() {
175163 };
176164 }
177165
178- WButton backButton = actions.add(theme.button("Back")).expandCellX().widget();
166+ // Link Buttons
167+ if (addon.getGithubUrl().isPresent()) {
168+ WButton btn = actions.add(theme.button("GitHub")).widget();
169+ final String url = addon.getGithubUrl().get();
170+ btn.action = () -> Util.getOperatingSystem().open(url);
171+ }
172+ if (addon.getDiscordUrl().isPresent()) {
173+ WButton btn = actions.add(theme.button("Discord")).widget();
174+ final String url = addon.getDiscordUrl().get();
175+ btn.action = () -> Util.getOperatingSystem().open(url);
176+ }
177+ if (addon.getHomepageUrl().isPresent()) {
178+ WButton btn = actions.add(theme.button("Homepage")).widget();
179+ final String url = addon.getHomepageUrl().get();
180+ btn.action = () -> Util.getOperatingSystem().open(url);
181+ }
182+
183+ // Back Button
184+ WButton backButton = actions.add(theme.button("Back")).widget();
179185 backButton.action = () -> mc.setScreen(parent);
180186 }
181187}
0 commit comments