diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java index 3202358..b2d3c36 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java @@ -120,7 +120,7 @@ public class GtkMenubar { public static void generateAccountsMenu(Application app) { Objects.requireNonNull(accountsMenu); accountsMenu.clear(); - accountsMenu.button("new", () -> new MicrosoftLoginDialog(GtkEnvBackend.INSTANCE.dialogParent, null).show()); + accountsMenu.button("new", () -> new MicrosoftLoginDialog(GtkEnvBackend.INSTANCE.dialogParent).show()); accountsMenu.button("manage", () -> { var window = new LauncherSettingsWindow(app); window.activePage = "settings.accounts"; diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsTab.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsTab.java index e8c4c75..7b0a584 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsTab.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsTab.java @@ -3,13 +3,14 @@ package io.gitlab.jfronny.inceptum.gtk.control.settings; import io.gitlab.jfronny.commons.StringFormatter; import io.gitlab.jfronny.inceptum.gtk.GtkEnvBackend; import io.gitlab.jfronny.inceptum.gtk.control.ILabel; -import io.gitlab.jfronny.inceptum.gtk.control.settings.IRow; +import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab.SectionBuilder.Section; import io.gitlab.jfronny.inceptum.gtk.util.I18n; -import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance; import org.gtk.gtk.*; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.PropertyKey; +import java.util.concurrent.atomic.AtomicInteger; + public class SettingsTab extends Box { protected final Window window; @@ -25,23 +26,47 @@ public class SettingsTab extends Box { Frame frame = new Frame(null); ListBox listBox = new ListBox(); listBox.selectionMode = SelectionMode.NONE; + listBox.showSeparators = true; frame.child = listBox; - builder.build(new SectionBuilder.Section() { + AtomicInteger count = new AtomicInteger(0); + builder.build(new Section() { @Override public IRow row(String title, @Nullable String subtitle, Object... args) { IRow row = new IRow(title, subtitle, args); - listBox.append(row); + row(row); return row; } + + @Override + public ListBoxRow row(Widget row) { + listBox.append(row); + return listBox.getRowAtIndex(count.getAndIncrement()); + } + + @Override + public void remove(Widget row) { + listBox.remove(row); + count.decrementAndGet(); + } + + @Override + public void clear() { + for (int i = 0, len = count.getAndSet(0); i < len; i++) { + listBox.remove(listBox.getRowAtIndex(0)); + } + } }); append(frame); } - protected interface SectionBuilder { + public interface SectionBuilder { void build(Section section); interface Section { IRow row(@PropertyKey(resourceBundle = I18n.BUNDLE) String title, @PropertyKey(resourceBundle = I18n.BUNDLE) @Nullable String subtitle, Object... args); + ListBoxRow row(Widget row); + void remove(Widget row); + void clear(); } } diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/MicrosoftLoginDialog.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/MicrosoftLoginDialog.java index 78bbc99..71aa869 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/MicrosoftLoginDialog.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/MicrosoftLoginDialog.java @@ -16,7 +16,19 @@ public class MicrosoftLoginDialog extends MessageDialog { return flags; } + public MicrosoftLoginDialog(@Nullable Window parent) { + this(parent, null, null); + } + public MicrosoftLoginDialog(@Nullable Window parent, @Nullable MicrosoftAccount account) { + this(parent, account, null); + } + + public MicrosoftLoginDialog(@Nullable Window parent, @Nullable Runnable onClose) { + this(parent, null, onClose); + } + + public MicrosoftLoginDialog(@Nullable Window parent, @Nullable MicrosoftAccount account, @Nullable Runnable onClose) { super( parent, flags(parent != null), @@ -25,10 +37,29 @@ public class MicrosoftLoginDialog extends MessageDialog { I18n.get("auth.description") ); title = I18n.get("auth.title"); + + var server = new MicrosoftAuthServer(account); + try { + server.start(); + } catch (Exception e) { + Utils.LOGGER.error("Could not start mc login server", e); + } + + Runnable finalize = () -> { + server.close(); + if (onClose != null) onClose.run(); + }; + onResponse(responseId -> { switch (ResponseType.of(responseId)) { - case CLOSE, CANCEL -> this.close(); - case DELETE_EVENT -> this.destroy(); + case CLOSE, CANCEL -> { + finalize.run(); + this.close(); + } + case DELETE_EVENT -> { + finalize.run(); + this.destroy(); + } default -> Utils.LOGGER.error("Unexpected response type: " + responseId); } }); @@ -42,12 +73,9 @@ public class MicrosoftLoginDialog extends MessageDialog { } }); - var server = new MicrosoftAuthServer(account); - try { - server.start(); - } catch (Exception e) { - Utils.LOGGER.error("Could not start mc login server", e); - } - onClose(server::close); + onCloseRequest(() -> { + finalize.run(); + return false; + }); } } diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/AccountsTab.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/AccountsTab.java index 23729b4..0cfee79 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/AccountsTab.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/AccountsTab.java @@ -1,13 +1,58 @@ package io.gitlab.jfronny.inceptum.gtk.window.settings.launcher; +import io.gitlab.jfronny.inceptum.gtk.GtkMenubar; +import io.gitlab.jfronny.inceptum.gtk.control.ILabel; import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab; -import org.gtk.gtk.Label; -import org.gtk.gtk.Window; +import io.gitlab.jfronny.inceptum.gtk.window.dialog.MicrosoftLoginDialog; +import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager; +import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount; +import org.gtk.gtk.*; -public class AccountsTab extends SettingsTab { +public class AccountsTab extends SettingsTab implements SettingsTab.SectionBuilder { public AccountsTab(Window window) { super(window); - append(new Label("Account management is still in development")); - //TODO implement + section(null, this); + } + + @Override + public void build(Section section) { + generateRows(section); + Button row = Button.newFromIconName("list-add-symbolic"); + section.row(row); + row.onClicked(() -> new MicrosoftLoginDialog(window, () -> { + section.clear(); + build(section); + GtkMenubar.generateAccountsMenu(window.application); + }).show()); + } + + private void generateRows(SectionBuilder.Section section) { + for (MicrosoftAccount account : AccountManager.getAccounts()) { + Box row = new Box(Orientation.HORIZONTAL, 40); + var ref = section.row(row); + row.margin = 8; + //TODO profile icon + Box head = new Box(Orientation.VERTICAL, 0); + head.hexpand = true; + head.halign = Align.START; + head.valign = Align.CENTER; + Label title = new Label(account.minecraftUsername); + title.halign = Align.START; + head.append(title); + Label subtitle = new Label(account.uuid); + ILabel.theme(subtitle, ILabel.Mode.SUBTITLE); + subtitle.halign = Align.START; + head.append(subtitle); + row.append(head); + Button remove = Button.newFromIconName("window-close-symbolic"); + remove.valign = Align.CENTER; + remove.halign = Align.END; + remove.onClicked(() -> { + AccountManager.removeAccount(account); + section.remove(ref); + GtkMenubar.generateAccountsMenu(window.application); + }); + row.append(remove); + } } }