mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Many small fixes
This commit is contained in:
parent
40f3945e92
commit
6d586b3045
17 changed files with 77 additions and 31 deletions
|
@ -4,12 +4,16 @@ import io.xpipe.app.comp.storage.store.StoreEntryTree;
|
|||
import io.xpipe.app.comp.storage.store.StoreEntryWrapper;
|
||||
import io.xpipe.app.comp.storage.store.StoreViewState;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
import io.xpipe.app.fxcomps.impl.IconButtonComp;
|
||||
import io.xpipe.app.fxcomps.impl.PrettyImageComp;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.collections.SetChangeListener;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.TreeCell;
|
||||
|
@ -110,9 +114,26 @@ final class BrowserBookmarkList extends SimpleComp {
|
|||
}
|
||||
|
||||
var fileSystem = ((ShellStore) getItem().getEntry().getStore());
|
||||
model.openFileSystemAsync(fileSystem, null);
|
||||
model.openFileSystemAsync(null, fileSystem, null);
|
||||
event.consume();
|
||||
});
|
||||
var icon = new SimpleObjectProperty<String>("mdal-keyboard_arrow_right");
|
||||
getPseudoClassStates().addListener((SetChangeListener<? super PseudoClass>) change -> {
|
||||
if (change.getSet().contains(PseudoClass.getPseudoClass("expanded"))) {
|
||||
icon.set("mdal-keyboard_arrow_down");
|
||||
} else {
|
||||
icon.set("mdal-keyboard_arrow_right");
|
||||
}
|
||||
});
|
||||
var button = new IconButtonComp(icon,
|
||||
() -> {
|
||||
getTreeItem().setExpanded(!getTreeItem().isExpanded());
|
||||
})
|
||||
.apply(struc -> struc.get().setPrefWidth(25))
|
||||
.grow(false, true)
|
||||
.styleClass("expand-button");
|
||||
|
||||
setDisclosureNode(button.createRegion());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -147,7 +168,7 @@ final class BrowserBookmarkList extends SimpleComp {
|
|||
return;
|
||||
}
|
||||
|
||||
Platform.runLater(() -> model.openExistingFileSystemIfPresent(store.asNeeded()));
|
||||
Platform.runLater(() -> model.openExistingFileSystemIfPresent(null, store.asNeeded()));
|
||||
}
|
||||
};
|
||||
DROP_TIMER.schedule(activeTask, 500);
|
||||
|
|
|
@ -6,12 +6,13 @@ import atlantafx.base.theme.Styles;
|
|||
import io.xpipe.app.browser.icon.DirectoryType;
|
||||
import io.xpipe.app.browser.icon.FileIconManager;
|
||||
import io.xpipe.app.browser.icon.FileType;
|
||||
import io.xpipe.app.ext.DataStoreProviders;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
import io.xpipe.app.fxcomps.augment.GrowAugment;
|
||||
import io.xpipe.app.fxcomps.impl.FancyTooltipAugment;
|
||||
import io.xpipe.app.fxcomps.impl.PrettyImageComp;
|
||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.util.BusyProperty;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import javafx.application.Platform;
|
||||
|
@ -231,14 +232,12 @@ public class BrowserComp extends SimpleComp {
|
|||
.bind(Bindings.createDoubleBinding(
|
||||
() -> model.getBusy().get() ? -1d : 0, PlatformThread.sync(model.getBusy())));
|
||||
|
||||
var name = DataStorage.get().getStoreEntry(model.getStore()).getName();
|
||||
var image = DataStorage.get()
|
||||
.getStoreEntry(model.getStore())
|
||||
.getProvider()
|
||||
var image = DataStoreProviders.byStore(model.getStore())
|
||||
.getDisplayIconFileName(model.getStore());
|
||||
var logo = new PrettyImageComp(new SimpleStringProperty(image), 20, 20).createRegion();
|
||||
|
||||
var label = new Label(name);
|
||||
var label = new Label(model.getName());
|
||||
label.setTextOverrun(OverrunStyle.CENTER_ELLIPSIS);
|
||||
label.addEventHandler(DragEvent.DRAG_ENTERED, new EventHandler<DragEvent>() {
|
||||
@Override
|
||||
public void handle(DragEvent mouseEvent) {
|
||||
|
@ -254,6 +253,7 @@ public class BrowserComp extends SimpleComp {
|
|||
PlatformThread.sync(model.getBusy())));
|
||||
|
||||
tab.setGraphic(label);
|
||||
new FancyTooltipAugment<>(new SimpleStringProperty(model.getName())).augment(label);
|
||||
GrowAugment.create(true, false).augment(new SimpleCompStructure<>(label));
|
||||
tab.setContent(new OpenFileSystemComp(model).createSimple());
|
||||
return tab;
|
||||
|
|
|
@ -97,18 +97,18 @@ public class BrowserModel {
|
|||
});
|
||||
}
|
||||
|
||||
public void openExistingFileSystemIfPresent(ShellStore store) {
|
||||
public void openExistingFileSystemIfPresent(String name, ShellStore store) {
|
||||
var found = openFileSystems.stream()
|
||||
.filter(model -> Objects.equals(model.getStore(), store))
|
||||
.findFirst();
|
||||
if (found.isPresent()) {
|
||||
selected.setValue(found.get());
|
||||
} else {
|
||||
openFileSystemAsync(store, null);
|
||||
openFileSystemAsync(name, store, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void openFileSystemAsync(ShellStore store, String path) {
|
||||
public void openFileSystemAsync(String name, ShellStore store, String path) {
|
||||
// // Prevent multiple tabs in non browser modes
|
||||
// if (!mode.equals(Mode.BROWSER)) {
|
||||
// ThreadHelper.runFailableAsync(() -> {
|
||||
|
@ -127,7 +127,7 @@ public class BrowserModel {
|
|||
// }
|
||||
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
var model = new OpenFileSystemModel(this, store);
|
||||
var model = new OpenFileSystemModel(name, this, store);
|
||||
model.initFileSystem();
|
||||
openFileSystems.add(model);
|
||||
selected.setValue(model);
|
||||
|
|
|
@ -38,7 +38,8 @@ public class BrowserNavBar extends SimpleComp {
|
|||
pathBar.pseudoClassStateChanged(INVISIBLE, !val);
|
||||
if (val) {
|
||||
Platform.runLater(() -> {
|
||||
pathBar.selectAll();
|
||||
pathBar.end();
|
||||
pathBar.selectBackward();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package io.xpipe.app.browser;
|
||||
|
||||
import io.xpipe.app.util.ApplicationHelper;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
import io.xpipe.core.process.ShellDialect;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -9,11 +11,22 @@ public class OpenFileSystemCache {
|
|||
|
||||
private final OpenFileSystemModel model;
|
||||
private final Map<String, Boolean> installedApplications = new HashMap<>();
|
||||
private String username;
|
||||
|
||||
public OpenFileSystemCache(OpenFileSystemModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public void init() throws Exception {
|
||||
ShellControl sc = model.getFileSystem().getShell().get();
|
||||
ShellDialect d = sc.getShellDialect();
|
||||
username = sc.executeSimpleStringCommand(d.getPrintVariableCommand(d.getUsernameVariableName()));
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return username.equals("root");
|
||||
}
|
||||
|
||||
public boolean isApplicationInPath(String app) {
|
||||
if (!installedApplications.containsKey(app)) {
|
||||
try {
|
||||
|
|
|
@ -44,11 +44,13 @@ public final class OpenFileSystemModel {
|
|||
private final Property<OpenFileSystemSavedState> savedState = new SimpleObjectProperty<>();
|
||||
private final OpenFileSystemCache cache = new OpenFileSystemCache(this);
|
||||
private final Property<ModalOverlayComp.OverlayContent> overlay = new SimpleObjectProperty<>();
|
||||
private final String name;
|
||||
private boolean local;
|
||||
|
||||
public OpenFileSystemModel(BrowserModel browserModel, FileSystemStore store) {
|
||||
public OpenFileSystemModel(String name, BrowserModel browserModel, FileSystemStore store) {
|
||||
this.browserModel = browserModel;
|
||||
this.store = store;
|
||||
this.name = name != null ? name : DataStorage.get().getStoreEntry(store).getName();
|
||||
fileList = new BrowserFileListModel(this);
|
||||
addListeners();
|
||||
}
|
||||
|
@ -336,6 +338,7 @@ public final class OpenFileSystemModel {
|
|||
fs.open();
|
||||
this.fileSystem = fs;
|
||||
this.local = fs.getShell().map(shellControl -> shellControl.isLocal()).orElse(false);
|
||||
this.cache.init();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
|
|||
show(null, null, null, filter, e -> {
|
||||
try {
|
||||
DataStorage.get().addStoreEntry(e);
|
||||
ScanAlert.showAsync(e.getStore(), true);
|
||||
// ScanAlert.showAsync(e.getStore(), true);
|
||||
} catch (Exception ex) {
|
||||
ErrorEvent.fromThrowable(ex).handle();
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ public class BaseMode extends OperationMode {
|
|||
SourceCollectionViewState.reset();
|
||||
StoreViewState.reset();
|
||||
DataStorage.reset();
|
||||
AppPrefs.reset();
|
||||
AppExtensionManager.reset();
|
||||
TrackEvent.info("mode", "Background mode shutdown finished");
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ public abstract class LauncherInput {
|
|||
}
|
||||
|
||||
var dir = Files.isDirectory(file) ? file : file.getParent();
|
||||
BrowserModel.DEFAULT.openFileSystemAsync(ShellStore.createLocal(), dir.toString());
|
||||
BrowserModel.DEFAULT.openFileSystemAsync(null, ShellStore.createLocal(), dir.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -374,6 +374,11 @@ public class AppPrefs {
|
|||
PrefsProvider.getAll().forEach(prov -> prov.init());
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
INSTANCE.save();
|
||||
INSTANCE = null;
|
||||
}
|
||||
|
||||
public static AppPrefs get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
|
|
@ -171,13 +171,13 @@ public class AppInstaller {
|
|||
public void installRemote(ShellControl shellControl, String file) throws Exception {
|
||||
try (var pc = shellControl.subShell(ShellDialects.BASH).start()) {
|
||||
try (CommandControl c = pc.command("DEBIAN_FRONTEND=noninteractive apt-get remove -qy xpipe")
|
||||
.elevated()
|
||||
.elevated("xpipe")
|
||||
.start()) {
|
||||
c.discardOrThrow();
|
||||
}
|
||||
try (CommandControl c = pc.command(
|
||||
"DEBIAN_FRONTEND=noninteractive apt-get install -qy \"" + file + "\"")
|
||||
.elevated()
|
||||
.elevated("xpipe")
|
||||
.start()) {
|
||||
c.discardOrThrow();
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ public class AppInstaller {
|
|||
public void installRemote(ShellControl shellControl, String file) throws Exception {
|
||||
try (var pc = shellControl.subShell(ShellDialects.BASH).start()) {
|
||||
try (CommandControl c = pc.command("rpm -U -v --force \"" + file + "\"")
|
||||
.elevated()
|
||||
.elevated("xpipe")
|
||||
.start()) {
|
||||
c.discardOrThrow();
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ public class AppInstaller {
|
|||
try (var pc = shellControl.subShell(ShellDialects.BASH).start()) {
|
||||
try (CommandControl c = pc.command(
|
||||
"installer -verboseR -allowUntrusted -pkg \"" + file + "\" -target /")
|
||||
.elevated()
|
||||
.elevated("xpipe")
|
||||
.start()) {
|
||||
c.discardOrThrow();
|
||||
}
|
||||
|
|
|
@ -57,12 +57,12 @@ public class ScriptHelper {
|
|||
content = content + "\n" + applyRcCommand + "\n";
|
||||
}
|
||||
|
||||
if (login) {
|
||||
// We just apply the profile files always, as we can't be sure that they definitely have been applied.
|
||||
// Especially if we launch something that is not the system default shell
|
||||
var applyProfilesCommand = t.applyProfileFilesCommand();
|
||||
if (applyProfilesCommand != null) {
|
||||
content = content + "\n" + applyProfilesCommand + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (toExecuteInShell != null) {
|
||||
// Normalize line endings
|
||||
|
|
|
@ -60,11 +60,11 @@ public interface CommandControl extends ProcessControl {
|
|||
|
||||
int getExitCode();
|
||||
|
||||
default CommandControl elevated() {
|
||||
return elevated((v) -> true);
|
||||
default CommandControl elevated(String message) {
|
||||
return elevated(message, (v) -> true);
|
||||
}
|
||||
|
||||
CommandControl elevated(FailableFunction<ShellControl, Boolean, Exception> elevationFunction);
|
||||
CommandControl elevated(String message, FailableFunction<ShellControl, Boolean, Exception> elevationFunction);
|
||||
|
||||
@Override
|
||||
CommandControl start() throws Exception;
|
||||
|
|
|
@ -84,7 +84,7 @@ public interface ShellControl extends ProcessControl {
|
|||
|
||||
OsType getOsType();
|
||||
|
||||
ShellControl elevated(FailableFunction<ShellControl, Boolean, Exception> elevationFunction);
|
||||
ShellControl elevated(String message, FailableFunction<ShellControl, Boolean, Exception> elevationFunction);
|
||||
|
||||
ShellControl elevationPassword(SecretValue value);
|
||||
|
||||
|
|
|
@ -100,6 +100,8 @@ public interface ShellDialect {
|
|||
|
||||
String getPrintVariableCommand(String name);
|
||||
|
||||
String getUsernameVariableName();
|
||||
|
||||
String getPrintExitCodeCommand(String prefix);
|
||||
|
||||
default String getPrintEnvironmentVariableCommand(String name) {
|
||||
|
|
|
@ -80,7 +80,7 @@ public class SampleAction implements ActionProvider {
|
|||
// sudo and the optional sudo password automatically provided by XPipe
|
||||
// by using the information from the connection store.
|
||||
// You can also set a custom working directory.
|
||||
try (CommandControl cc = sc.command("kill <pid>").elevated().workingDirectory("/").start()) {
|
||||
try (CommandControl cc = sc.command("kill <pid>").elevated("kill").workingDirectory("/").start()) {
|
||||
// Discard any output but throw an exception with the stderr contents if the exit code is not 0
|
||||
cc.discardOrThrow();
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ public class OpenDirectoryInNewTabAction implements LeafAction {
|
|||
|
||||
@Override
|
||||
public void execute(OpenFileSystemModel model, List<BrowserEntry> entries) throws Exception {
|
||||
model.getBrowserModel().openFileSystemAsync(model.getStore().asNeeded(), entries.get(0).getRawFileEntry().getPath());
|
||||
model.getBrowserModel().openFileSystemAsync(model.getName(), model.getStore().asNeeded(), entries.get(0).getRawFileEntry().getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue