Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ private Accounts() {
public static final MicrosoftAccountFactory FACTORY_MICROSOFT = new MicrosoftAccountFactory(new MicrosoftService(OAUTH_CALLBACK));
public static final List<AccountFactory<?>> FACTORIES = immutableListOf(FACTORY_OFFLINE, FACTORY_MICROSOFT, FACTORY_AUTHLIB_INJECTOR);

// FX-Thread
public static boolean skipSelectionCheckFlag = false;

// ==== login type / account factory mapping ====
private static final Map<String, AccountFactory<?>> type2factory = new HashMap<>();
private static final Map<AccountFactory<?>, String> factory2type = new HashMap<>();
Expand Down Expand Up @@ -147,12 +150,15 @@ private static void updateAccountStorages() {
ArrayList<Map<Object, Object>> global = new ArrayList<>();
ArrayList<Map<Object, Object>> portable = new ArrayList<>();

for (Account account : accounts) {
for (int i = 0, accountsSize = accounts.size(); i < accountsSize; i++) {
Account account = accounts.get(i);
Map<Object, Object> storage = getAccountStorage(account);
if (account.isPortable())
if (account.isPortable()) {
storage.put("index", i);
portable.add(storage);
else
} else {
global.add(storage);
}
}

if (!global.equals(globalAccountStorages))
Expand Down Expand Up @@ -210,25 +216,34 @@ static void init() {
loadGlobalAccountStorages();

// load accounts
Account selected = null;
for (Map<Object, Object> storage : config().getAccountStorages()) {
Account account = parseAccount(storage);
if (account != null) {
account.setPortable(true);
accounts.add(account);
if (Boolean.TRUE.equals(storage.get("selected"))) {
selected = account;
}
}
}

for (Map<Object, Object> storage : globalAccountStorages) {
Account account = parseAccount(storage);
if (account != null) {
accounts.add(account);
}
}

List<Account> unordered = new ArrayList<>();
Account[] s = new Account[1];
config().getAccountStorages()
.stream()
.sorted(Comparator.comparingInt(storage -> storage.get("index") instanceof Number n ? n.intValue() : -1))
.forEachOrdered(storage -> {
Account account = parseAccount(storage);
if (account == null) return;
account.setPortable(true);
if (storage.get("index") instanceof Number n) {
accounts.add(n.intValue(), account);
} else {
unordered.add(account);
}
if (Boolean.TRUE.equals(storage.get("selected"))) {
s[0] = account;
}
});
accounts.addAll(0, unordered);
Account selected = s[0];

String selectedAccountIdentifier = config().getSelectedAccount();
if (selected == null && selectedAccountIdentifier != null) {
boolean portable = true;
Expand Down Expand Up @@ -262,7 +277,7 @@ static void init() {
}

if (!globalConfig().isEnableOfflineAccount())
accounts.addListener(new ListChangeListener<Account>() {
accounts.addListener(new ListChangeListener<>() {
@Override
public void onChanged(Change<? extends Account> change) {
while (change.next()) {
Expand All @@ -280,6 +295,7 @@ public void onChanged(Change<? extends Account> change) {
selectedAccount.set(selected);

InvalidationListener listener = o -> {
if (skipSelectionCheckFlag) return;
// this method first checks whether the current selection is valid
// if it's valid, the underlying storage will be updated
// otherwise, the first account will be selected as an alternative(or null if accounts is empty)
Expand Down
12 changes: 8 additions & 4 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,12 @@
import javafx.event.EventType;
import javafx.geometry.Bounds;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.control.skin.VirtualFlow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.*;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.Priority;
Expand Down Expand Up @@ -1704,4 +1702,10 @@ public static void useJFXContextMenu(TextInputControl control) {
e.consume();
});
}

public static WritableImage takeSnapshot(Region node) {
SnapshotParameters snapShotParams = new SnapshotParameters();
snapShotParams.setFill(Color.TRANSPARENT);
return node.snapshot(snapShotParams, new WritableImage((int) node.getWidth() + 10, (int) node.getHeight() + 10));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,14 @@
public class AccountListItem extends RadioButton {

private final Account account;
private final AccountListPage page;

private final StringProperty title = new SimpleStringProperty();
private final StringProperty subtitle = new SimpleStringProperty();

public AccountListItem(Account account) {
public AccountListItem(Account account, AccountListPage page) {
this.account = account;
this.page = page;
getStyleClass().clear();
setUserData(account);

Expand Down Expand Up @@ -188,6 +191,10 @@ public Account getAccount() {
return account;
}

public AccountListPage getPage() {
return page;
}

public String getTitle() {
return title.get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
import javafx.scene.control.Label;
import javafx.scene.control.SkinBase;
import javafx.scene.control.Tooltip;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
Expand Down Expand Up @@ -95,24 +98,11 @@ public AccountListItemSkin(AccountListItem skinnable) {
spinnerMove.getStyleClass().add("small-spinner-pane");
btnMove.setOnAction(e -> {
Account account = skinnable.getAccount();
Accounts.getAccounts().remove(account);
if (account.isPortable()) {
account.setPortable(false);
if (!Accounts.getAccounts().contains(account))
Accounts.getAccounts().add(account);
} else {
account.setPortable(true);
if (!Accounts.getAccounts().contains(account)) {
int idx = 0;
for (int i = Accounts.getAccounts().size() - 1; i >= 0; i--) {
if (Accounts.getAccounts().get(i).isPortable()) {
idx = i + 1;
break;
}
}
Accounts.getAccounts().add(idx, account);
}
}
int index = Accounts.getAccounts().indexOf(account);
if (index < 0) return;
Accounts.getAccounts().remove(index);
account.setPortable(!account.isPortable());
Accounts.getAccounts().add(index, account);
Comment thread
ToobLac marked this conversation as resolved.
});
btnMove.getStyleClass().add("toggle-icon4");
if (skinnable.getAccount().isPortable()) {
Expand Down Expand Up @@ -184,6 +174,17 @@ public AccountListItemSkin(AccountListItem skinnable) {
root.setStyle("-fx-padding: 8 8 8 0;");
JFXDepthManager.setDepth(root, 1);

// Enable drag detection for reordering
root.setOnDragDetected(event -> {
if (skinnable.getPage().isSearching().get()) return;
Dragboard db = root.startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(skinnable.getAccount().getIdentifier());
db.setContent(content);
db.setDragView(FXUtils.takeSnapshot(root));
event.consume();
});

getChildren().setAll(root);
}
}
Loading