Various android fixes

This commit is contained in:
crschnick
2025-12-21 05:56:31 +00:00
parent 937ef6f2fb
commit 9d63af0a14
21 changed files with 86 additions and 47 deletions
@@ -8,7 +8,7 @@ import io.xpipe.app.comp.base.StackComp;
import io.xpipe.app.core.App;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.platform.ContextMenuHelper;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
@@ -295,10 +295,10 @@ public class BrowserSessionTabsComp extends SimpleComp {
}
private ContextMenu createContextMenu(TabPane tabs, Tab tab, BrowserSessionTab tabModel) {
var cm = ContextMenuHelper.create();
var cm = MenuHelper.createContextMenu();
if (tabModel.isCloseable()) {
var unpin = ContextMenuHelper.item(LabelGraphic.none(), "unpinTab");
var unpin = MenuHelper.createMenuItem(LabelGraphic.none(), "unpinTab");
unpin.visibleProperty()
.bind(PlatformThread.sync(Bindings.createBooleanBinding(
() -> {
@@ -312,7 +312,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
});
cm.getItems().add(unpin);
var pin = ContextMenuHelper.item(LabelGraphic.none(), "pinTab");
var pin = MenuHelper.createMenuItem(LabelGraphic.none(), "pinTab");
pin.visibleProperty()
.bind(PlatformThread.sync(Bindings.createBooleanBinding(
() -> {
@@ -326,7 +326,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
cm.getItems().add(pin);
}
var select = ContextMenuHelper.item(LabelGraphic.none(), "selectTab");
var select = MenuHelper.createMenuItem(LabelGraphic.none(), "selectTab");
select.acceleratorProperty()
.bind(Bindings.createObjectBinding(
() -> {
@@ -347,7 +347,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
cm.getItems().add(new SeparatorMenuItem());
var close = ContextMenuHelper.item(LabelGraphic.none(), "closeTab");
var close = MenuHelper.createMenuItem(LabelGraphic.none(), "closeTab");
close.setAccelerator(new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN));
close.setOnAction(event -> {
if (tab.isClosable()) {
@@ -357,7 +357,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
});
cm.getItems().add(close);
var closeOthers = ContextMenuHelper.item(LabelGraphic.none(), "closeOtherTabs");
var closeOthers = MenuHelper.createMenuItem(LabelGraphic.none(), "closeOtherTabs");
closeOthers.setOnAction(event -> {
tabs.getTabs()
.removeAll(tabs.getTabs().stream()
@@ -367,7 +367,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
});
cm.getItems().add(closeOthers);
var closeLeft = ContextMenuHelper.item(LabelGraphic.none(), "closeLeftTabs");
var closeLeft = MenuHelper.createMenuItem(LabelGraphic.none(), "closeLeftTabs");
closeLeft.setOnAction(event -> {
var index = tabs.getTabs().indexOf(tab);
tabs.getTabs()
@@ -378,7 +378,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
});
cm.getItems().add(closeLeft);
var closeRight = ContextMenuHelper.item(LabelGraphic.none(), "closeRightTabs");
var closeRight = MenuHelper.createMenuItem(LabelGraphic.none(), "closeRightTabs");
closeRight.setOnAction(event -> {
var index = tabs.getTabs().indexOf(tab);
tabs.getTabs()
@@ -389,7 +389,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
});
cm.getItems().add(closeRight);
var closeAll = ContextMenuHelper.item(LabelGraphic.none(), "closeAllTabs");
var closeAll = MenuHelper.createMenuItem(LabelGraphic.none(), "closeAllTabs");
closeAll.setAccelerator(
new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN));
closeAll.setOnAction(event -> {
@@ -13,7 +13,7 @@ public class BrowserDialogs {
public static FileConflictChoice showFileConflictDialog(FilePath file, boolean multiple) {
var choice = new SimpleObjectProperty<FileConflictChoice>();
var key = multiple ? "fileConflictAlertContentMultiple" : "fileConflictAlertContent";
var w = multiple ? 1050 : 400;
var w = multiple ? 900 : 400;
var modal = ModalOverlay.of(
"fileConflictAlertTitle",
AppDialog.dialogText(AppI18n.observable(key, file)).prefWidth(w));
@@ -3,7 +3,7 @@ package io.xpipe.app.browser.file;
import io.xpipe.app.comp.base.LazyTextFieldComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.platform.ContextMenuHelper;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.InputHelper;
import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.util.BooleanScope;
@@ -132,7 +132,7 @@ class BrowserFileListNameCell extends TableCell<BrowserEntry, String> {
if (selected.size() > 0 && selected.getLast() == getTableRow().getItem()) {
var cm = new BrowserContextMenu(
fileList.getFileSystemModel(), getTableRow().getItem(), false);
ContextMenuHelper.toggleShow(cm, this, Side.RIGHT);
MenuHelper.toggleMenuShow(cm, this, Side.RIGHT);
event.consume();
}
});
@@ -3,16 +3,12 @@ package io.xpipe.app.browser.file;
import io.xpipe.app.browser.icon.BrowserIconManager;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.comp.augment.ContextMenuAugment;
import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.comp.base.TextFieldComp;
import io.xpipe.app.comp.base.TooltipHelper;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.platform.ContextMenuHelper;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.util.BooleanScope;
@@ -34,7 +30,6 @@ import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import atlantafx.base.theme.Styles;
import org.kordamp.ikonli.javafx.FontIcon;
public class BrowserNavBarComp extends Comp<BrowserNavBarComp.Structure> {
@@ -194,7 +189,7 @@ public class BrowserNavBarComp extends Comp<BrowserNavBarComp.Structure> {
}
private ContextMenu createContextMenu() {
var cm = ContextMenuHelper.create();
var cm = MenuHelper.createContextMenu();
var f = model.getHistory().getForwardHistory(8).stream().toList();
for (int i = f.size() - 1; i >= 0; i--) {
@@ -7,6 +7,7 @@ import io.xpipe.app.ext.FileEntry;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.platform.BooleanAnimationTimer;
import io.xpipe.app.platform.InputHelper;
import io.xpipe.app.update.AppDistributionType;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;
@@ -61,7 +62,7 @@ public class BrowserQuickAccessContextMenu extends ContextMenu {
hide();
e.consume();
});
setAutoHide(true);
setAutoHide(AppDistributionType.get() != AppDistributionType.ANDROID_LINUX_TERMINAL);
getStyleClass().add("condensed");
}
@@ -4,6 +4,7 @@ import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.util.Translatable;
@@ -12,6 +13,7 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.scene.control.ComboBox;
import javafx.scene.control.skin.ComboBoxListViewSkin;
import javafx.util.StringConverter;
import lombok.AccessLevel;
@@ -45,7 +47,7 @@ public class ChoiceComp<T> extends Comp<CompStructure<ComboBox<T>>> {
@Override
public CompStructure<ComboBox<T>> createBase() {
var cb = new ComboBox<T>();
var cb = MenuHelper.<T>createComboBox();
cb.setConverter(new StringConverter<>() {
@Override
public String toString(T object) {
@@ -3,6 +3,7 @@ package io.xpipe.app.comp.base;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.PlatformThread;
import javafx.beans.property.Property;
@@ -35,7 +36,8 @@ public class ChoicePaneComp extends Comp<CompStructure<VBox>> {
@Override
public CompStructure<VBox> createBase() {
var list = FXCollections.observableArrayList(entries);
var cb = new ComboBox<>(list);
var cb = MenuHelper.<Entry>createComboBox();
cb.setItems(list);
cb.setOnKeyPressed(event -> {
if (!cb.isShowing() && event.getCode().equals(KeyCode.ENTER)) {
cb.show();
@@ -3,6 +3,7 @@ package io.xpipe.app.comp.base;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.PlatformThread;
import javafx.beans.property.Property;
@@ -32,14 +33,13 @@ public class IntComboFieldComp extends Comp<CompStructure<ComboBox<String>>> {
@Override
public CompStructure<ComboBox<String>> createBase() {
var text = new ComboBox<String>();
var text = MenuHelper.<String>createComboBox();
text.setEditable(true);
text.setValue(value.getValue() != null ? value.getValue().toString() : null);
text.setItems(FXCollections.observableList(
predefined.stream().map(integer -> "" + integer).toList()));
text.setMaxWidth(20000);
text.getStyleClass().add("int-combo-field-comp");
text.setSkin(new ComboBoxListViewSkin<>(text));
text.setVisibleRowCount(Math.min(10, predefined.size()));
value.addListener((ChangeListener<Number>) (observableValue, oldValue, newValue) -> {
@@ -3,6 +3,7 @@ package io.xpipe.app.ext;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.process.ShellDialect;
import io.xpipe.app.process.ShellDialects;
@@ -76,7 +77,7 @@ public class ShellDialectChoiceComp extends SimpleComp {
.createRegion());
}
};
var cb = new ComboBox<ShellDialect>();
var cb = MenuHelper.<ShellDialect>createComboBox();
cb.setCellFactory(param -> supplier.get());
cb.setButtonCell(supplier.get());
cb.setValue(selected.getValue());
@@ -1,14 +1,13 @@
package io.xpipe.app.hub.comp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompDescriptor;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.augment.ContextMenuAugment;
import io.xpipe.app.comp.base.*;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.platform.ClipboardHelper;
import io.xpipe.app.platform.ContextMenuHelper;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.storage.DataStorage;
@@ -199,7 +198,7 @@ public class StoreCategoryComp extends SimpleComp {
}
private ContextMenu createContextMenu(Region text) {
var contextMenu = ContextMenuHelper.create();
var contextMenu = MenuHelper.createContextMenu();
if (AppPrefs.get().enableHttpApi().get()) {
var copyId = new MenuItem(AppI18n.get("copyId"), new FontIcon("mdi2c-content-copy"));
@@ -3,6 +3,7 @@ package io.xpipe.app.hub.comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.ext.DataStore;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.storage.DataStoreEntryRef;
@@ -119,6 +120,7 @@ public class StoreComboChoiceComp<T extends DataStore> extends SimpleComp {
}
};
combo.setSkin(skin);
MenuHelper.fixComboBoxSkin(skin);
combo.setMaxWidth(20000);
combo.setEditable(true);
@@ -353,7 +353,7 @@ public abstract class StoreEntryComp extends SimpleComp {
if (branch != null) {
button.apply(new ContextMenuAugment<>(
mouseEvent -> mouseEvent.getButton() == MouseButton.PRIMARY, keyEvent -> false, () -> {
var cm = ContextMenuHelper.create();
var cm = MenuHelper.createContextMenu();
var children =
branch.getChildren(getWrapper().getEntry().ref());
var cats = Arrays.stream(StoreActionCategory.values())
@@ -416,7 +416,7 @@ public abstract class StoreEntryComp extends SimpleComp {
}
protected ContextMenu createContextMenu(Region name) {
var contextMenu = ContextMenuHelper.create();
var contextMenu = MenuHelper.createContextMenu();
handleContextMenuCount(contextMenu);
var cats = Arrays.stream(StoreActionCategory.values()).collect(Collectors.toCollection(ArrayList::new));
@@ -537,7 +537,7 @@ public abstract class StoreEntryComp extends SimpleComp {
}
var index =
ContextMenuHelper.item(new LabelGraphic.IconGraphic("mdi2t-tag-plus-outline"), "createTag");
MenuHelper.createMenuItem(new LabelGraphic.IconGraphic("mdi2t-tag-plus-outline"), "createTag");
index.setOnAction(event -> {
var tagName = new SimpleStringProperty();
var modal = ModalOverlay.of(
@@ -8,7 +8,7 @@ import io.xpipe.app.comp.base.*;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.DataStore;
import io.xpipe.app.hub.action.BatchHubProvider;
import io.xpipe.app.platform.ContextMenuHelper;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.DerivedObservableList;
import io.xpipe.app.storage.DataStoreEntryRef;
@@ -145,7 +145,7 @@ public class StoreEntryListBatchBarComp extends SimpleComp {
if (batchActions.size() > 0) {
button.apply(new ContextMenuAugment<>(
mouseEvent -> mouseEvent.getButton() == MouseButton.PRIMARY, keyEvent -> false, () -> {
var cm = ContextMenuHelper.create();
var cm = MenuHelper.createContextMenu();
s.getChildren(childrenRefs.getList()).forEach(childProvider -> {
var menu = buildMenuItemForAction(childrenRefs.getList(), childProvider);
cm.getItems().add(menu);
@@ -8,6 +8,8 @@ import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.platform.JfxHelper;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.process.ShellDialect;
import javafx.beans.property.Property;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
@@ -60,7 +62,7 @@ public class StoreProviderChoiceComp extends Comp<CompStructure<ComboBox<DataSto
}
}
};
var cb = new ComboBox<DataStoreProvider>();
var cb = MenuHelper.<DataStoreProvider>createComboBox();
cb.setCellFactory(param -> {
return cellFactory.get();
});
@@ -4,7 +4,7 @@ import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.base.IconButtonComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.platform.ContextMenuHelper;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.LabelGraphic;
import javafx.geometry.Side;
@@ -32,7 +32,7 @@ public class StoreQuickAccessButtonComp extends Comp<CompStructure<Button>> {
return null;
}
var cm = ContextMenuHelper.create();
var cm = MenuHelper.createContextMenu();
cm.getStyleClass().add("condensed");
Menu menu = (Menu) recurse(cm, section);
cm.getItems().addAll(menu.getItems());
@@ -94,7 +94,7 @@ public class StoreQuickAccessButtonComp extends Comp<CompStructure<Button>> {
return;
}
ContextMenuHelper.toggleShow(menu.get(), struc.get(), Side.RIGHT);
MenuHelper.toggleMenuShow(menu.get(), struc.get(), Side.RIGHT);
event.consume();
});
});
@@ -3,19 +3,41 @@ package io.xpipe.app.platform;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.update.AppDistributionType;
import javafx.application.Platform;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.*;
import javafx.scene.control.skin.ComboBoxListViewSkin;
import javafx.scene.control.skin.ComboBoxPopupControl;
import javafx.scene.layout.Region;
import lombok.SneakyThrows;
public class ContextMenuHelper {
import java.util.function.Function;
public static ContextMenu create() {
public class MenuHelper {
@SneakyThrows
public static <T> ComboBoxListViewSkin<T> fixComboBoxSkin(ComboBoxListViewSkin<T> skin) {
var m = ComboBoxPopupControl.class.getDeclaredMethod("getPopup");
m.setAccessible(true);
var popup = (PopupControl) m.invoke(skin);
popup.setAutoHide(AppDistributionType.get() != AppDistributionType.ANDROID_LINUX_TERMINAL);
return skin;
}
@SneakyThrows
public static <T> ComboBox<T> createComboBox() {
var cb = new ComboBox<T>();
var skin = new ComboBoxListViewSkin<>(cb);
fixComboBoxSkin(skin);
cb.setSkin(skin);
return cb;
}
public static ContextMenu createContextMenu() {
ContextMenu contextMenu = new ContextMenu();
contextMenu.setAutoHide(true);
contextMenu.setAutoHide(AppDistributionType.get() != AppDistributionType.ANDROID_LINUX_TERMINAL);
InputHelper.onLeft(contextMenu, false, e -> {
contextMenu.hide();
e.consume();
@@ -41,14 +63,14 @@ public class ContextMenuHelper {
return contextMenu;
}
public static MenuItem item(LabelGraphic graphic, String nameKey) {
public static MenuItem createMenuItem(LabelGraphic graphic, String nameKey) {
var i = new MenuItem();
i.textProperty().bind(AppI18n.observable(nameKey));
i.setGraphic(graphic.createGraphicNode());
return i;
}
public static void toggleShow(ContextMenu contextMenu, Node ref, Side side) {
public static void toggleMenuShow(ContextMenu contextMenu, Node ref, Side side) {
if (!contextMenu.isShowing()) {
// Prevent NPE in show()
if (contextMenu.getScene() == null || ref == null || ref.getScene() == null) {
@@ -56,7 +56,7 @@ public enum AppDistributionType implements Translatable {
CHOCO("choco", true, () -> new ChocoUpdater()),
WINGET("winget", true, () -> new WingetUpdater()),
SCOOP("scoop", false, () -> new PortableUpdater(true)),
;
ANDROID_LINUX_TERMINAL("androidLinuxTerminal", false, () -> new PortableUpdater(true));
private static AppDistributionType type;
@@ -152,6 +152,13 @@ public enum AppDistributionType implements Translatable {
return PORTABLE;
}
} else {
if (OsType.ofLocal() == OsType.LINUX) {
var uname = LocalExec.readStdoutIfPossible("uname", "-a");
if (uname.isPresent() && uname.get().contains("android") && uname.get().contains("aarch64")) {
return ANDROID_LINUX_TERMINAL;
}
}
var file = base.resolve("installation");
if (!Files.exists(file)) {
if (OsType.ofLocal() == OsType.LINUX && Files.exists(base.resolve("aur"))) {
+1
View File
@@ -141,6 +141,7 @@ def getJvmArgs() {
"--add-exports", "jdk.zipfs/jdk.nio.zipfs=io.xpipe.modulefs",
"--add-opens", "javafx.graphics/com.sun.glass.ui=$appPackage",
"--add-opens", "javafx.graphics/javafx.stage=$appPackage",
"--add-opens", "javafx.controls/javafx.scene.control.skin=$appPackage",
"--add-opens", "javafx.graphics/com.sun.javafx.tk=$appPackage",
"--add-opens", "javafx.graphics/com.sun.javafx.tk.quantum=$appPackage"
]
@@ -5,6 +5,7 @@ import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.comp.base.*;
import io.xpipe.app.platform.MenuHelper;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
@@ -131,6 +132,7 @@ public class HostAddressChoiceComp extends Comp<CompStructure<HBox>> {
});
combo.apply(struc -> {
var skin = new ComboBoxListViewSkin<>(struc.get());
MenuHelper.fixComboBoxSkin(skin);
struc.get().setSkin(skin);
skin.setHideOnClick(false);
@@ -9,6 +9,7 @@ import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.DataStoreCreationCategory;
import io.xpipe.app.hub.comp.*;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.secret.EncryptedValue;
@@ -324,6 +325,7 @@ public class IdentitySelectComp extends Comp<CompStructure<HBox>> {
popover.hide();
}
};
MenuHelper.fixComboBoxSkin(skin);
struc.get().setSkin(skin);
});
+1
View File
@@ -154,3 +154,4 @@ rsa=RSA
ed25519=ED25519
ed25519Sk=ED25519 (FIDO2)
westonEditor=Weston Editor
androidLinuxTerminalDist=Android Linux Terminal