mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
[stage]
This commit is contained in:
parent
9f232aa7d1
commit
4c64eb5ae5
22 changed files with 166 additions and 183 deletions
|
@ -7,6 +7,7 @@ import io.xpipe.app.core.window.AppWindowHelper;
|
||||||
import io.xpipe.app.fxcomps.Comp;
|
import io.xpipe.app.fxcomps.Comp;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
|
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
|
||||||
|
import io.xpipe.app.fxcomps.util.BindingsHelper;
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
|
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
|
@ -58,9 +59,15 @@ public class BrowserSelectionListComp extends SimpleComp {
|
||||||
return Comp.of(() -> {
|
return Comp.of(() -> {
|
||||||
var image = PrettyImageHelper.ofFixedSizeSquare(entry.getIcon(), 24)
|
var image = PrettyImageHelper.ofFixedSizeSquare(entry.getIcon(), 24)
|
||||||
.createRegion();
|
.createRegion();
|
||||||
var l = new Label(null, image);
|
var t = nameTransformation.apply(entry);
|
||||||
|
var l = new Label(t.getValue(), image);
|
||||||
l.setTextOverrun(OverrunStyle.CENTER_ELLIPSIS);
|
l.setTextOverrun(OverrunStyle.CENTER_ELLIPSIS);
|
||||||
l.textProperty().bind(PlatformThread.sync(nameTransformation.apply(entry)));
|
t.addListener((observable, oldValue, newValue) -> {
|
||||||
|
PlatformThread.runLaterIfNeeded(() -> {
|
||||||
|
l.setText(newValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
BindingsHelper.preserve(l, t);
|
||||||
return l;
|
return l;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package io.xpipe.app.browser;
|
package io.xpipe.app.browser;
|
||||||
|
|
||||||
import io.xpipe.app.browser.file.BrowserFileTransferMode;
|
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
import io.xpipe.app.comp.base.LoadingOverlayComp;
|
|
||||||
import io.xpipe.app.core.AppFont;
|
import io.xpipe.app.core.AppFont;
|
||||||
import io.xpipe.app.core.AppI18n;
|
import io.xpipe.app.core.AppI18n;
|
||||||
import io.xpipe.app.fxcomps.Comp;
|
import io.xpipe.app.fxcomps.Comp;
|
||||||
|
@ -11,11 +9,14 @@ import io.xpipe.app.fxcomps.augment.DragOverPseudoClassAugment;
|
||||||
import io.xpipe.app.fxcomps.impl.*;
|
import io.xpipe.app.fxcomps.impl.*;
|
||||||
import io.xpipe.app.fxcomps.util.DerivedObservableList;
|
import io.xpipe.app.fxcomps.util.DerivedObservableList;
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
|
import io.xpipe.app.util.ThreadHelper;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.input.ClipboardContent;
|
||||||
import javafx.scene.input.Dragboard;
|
import javafx.scene.input.Dragboard;
|
||||||
import javafx.scene.input.TransferMode;
|
import javafx.scene.input.TransferMode;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
|
@ -38,8 +39,6 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
@Override
|
@Override
|
||||||
protected Region createSimple() {
|
protected Region createSimple() {
|
||||||
var syncItems = PlatformThread.sync(model.getItems());
|
var syncItems = PlatformThread.sync(model.getItems());
|
||||||
var syncDownloaded = PlatformThread.sync(model.getDownloading());
|
|
||||||
var syncAllDownloaded = PlatformThread.sync(model.getAllDownloaded());
|
|
||||||
|
|
||||||
var background = new LabelComp(AppI18n.observable("transferDescription"))
|
var background = new LabelComp(AppI18n.observable("transferDescription"))
|
||||||
.apply(struc -> struc.get().setGraphic(new FontIcon("mdi2d-download-outline")))
|
.apply(struc -> struc.get().setGraphic(new FontIcon("mdi2d-download-outline")))
|
||||||
|
@ -53,46 +52,42 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
.getList();
|
.getList();
|
||||||
var list = new BrowserSelectionListComp(
|
var list = new BrowserSelectionListComp(
|
||||||
binding,
|
binding,
|
||||||
entry -> Bindings.createStringBinding(
|
entry -> {
|
||||||
() -> {
|
var sourceItem = syncItems.stream()
|
||||||
var sourceItem = syncItems.stream()
|
.filter(item -> item.getBrowserEntry() == entry)
|
||||||
.filter(item -> item.getBrowserEntry() == entry)
|
.findAny();
|
||||||
.findAny();
|
if (sourceItem.isEmpty()) {
|
||||||
if (sourceItem.isEmpty()) {
|
return new SimpleStringProperty("?");
|
||||||
return "?";
|
}
|
||||||
}
|
return Bindings.createStringBinding(() -> {
|
||||||
var name = entry.getModel() == null
|
var p = sourceItem.get().getProgress().getValue();
|
||||||
|| sourceItem
|
var progressSuffix = sourceItem.get().downloadFinished().get() ? "" : " " + (p.getTransferred() * 100 / p.getTotal()) + "%";
|
||||||
.get()
|
return entry.getFileName() + progressSuffix;
|
||||||
.downloadFinished()
|
}, sourceItem.get().getProgress());
|
||||||
.get()
|
})
|
||||||
? "Local"
|
|
||||||
: entry.getModel()
|
|
||||||
.getFileSystemModel()
|
|
||||||
.getName();
|
|
||||||
return entry.getFileName() + " (" + name + ")";
|
|
||||||
},
|
|
||||||
syncAllDownloaded))
|
|
||||||
.grow(false, true);
|
.grow(false, true);
|
||||||
var dragNotice = new LabelComp(syncAllDownloaded.flatMap(
|
var dragNotice = new LabelComp(AppI18n.observable("dragLocalFiles"))
|
||||||
aBoolean -> aBoolean ? AppI18n.observable("dragLocalFiles") : AppI18n.observable("dragFiles")))
|
|
||||||
.apply(struc -> struc.get().setGraphic(new FontIcon("mdi2h-hand-left")))
|
.apply(struc -> struc.get().setGraphic(new FontIcon("mdi2h-hand-left")))
|
||||||
.apply(struc -> AppFont.medium(struc.get()))
|
.apply(struc -> AppFont.medium(struc.get()))
|
||||||
.apply(struc -> struc.get().setWrapText(true))
|
.apply(struc -> struc.get().setWrapText(true))
|
||||||
.hide(Bindings.isEmpty(syncItems));
|
.hide(Bindings.isEmpty(syncItems));
|
||||||
|
|
||||||
var downloadButton = new IconButtonComp("mdi2d-download", () -> {
|
|
||||||
model.download();
|
|
||||||
})
|
|
||||||
.hide(Bindings.isEmpty(syncItems))
|
|
||||||
.disable(syncAllDownloaded)
|
|
||||||
.tooltipKey("downloadStageDescription");
|
|
||||||
var clearButton = new IconButtonComp("mdi2c-close", () -> {
|
var clearButton = new IconButtonComp("mdi2c-close", () -> {
|
||||||
model.clear(true);
|
ThreadHelper.runAsync(() -> {
|
||||||
|
model.clear(true);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.hide(Bindings.isEmpty(syncItems))
|
.hide(Bindings.isEmpty(syncItems))
|
||||||
.tooltipKey("clearTransferDescription");
|
.tooltipKey("clearTransferDescription");
|
||||||
|
|
||||||
|
var downloadButton = new IconButtonComp("mdi2f-folder-move-outline", () -> {
|
||||||
|
ThreadHelper.runFailableAsync(() -> {
|
||||||
|
model.transferToDownloads();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.hide(Bindings.isEmpty(syncItems))
|
||||||
|
.tooltipKey("downloadStageDescription");
|
||||||
|
|
||||||
var bottom =
|
var bottom =
|
||||||
new HorizontalComp(List.of(Comp.hspacer(), dragNotice, Comp.hspacer(), downloadButton, Comp.hspacer(4), clearButton));
|
new HorizontalComp(List.of(Comp.hspacer(), dragNotice, Comp.hspacer(), downloadButton, Comp.hspacer(4), clearButton));
|
||||||
var listBox = new VerticalComp(List.of(list, bottom))
|
var listBox = new VerticalComp(List.of(list, bottom))
|
||||||
|
@ -100,8 +95,7 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
.padding(new Insets(10, 10, 5, 10))
|
.padding(new Insets(10, 10, 5, 10))
|
||||||
.apply(struc -> struc.get().setMinHeight(200))
|
.apply(struc -> struc.get().setMinHeight(200))
|
||||||
.apply(struc -> struc.get().setMaxHeight(200));
|
.apply(struc -> struc.get().setMaxHeight(200));
|
||||||
var stack = LoadingOverlayComp.noProgress(
|
var stack = new StackComp(List.of(backgroundStack, listBox))
|
||||||
new StackComp(List.of(backgroundStack, listBox))
|
|
||||||
.apply(DragOverPseudoClassAugment.create())
|
.apply(DragOverPseudoClassAugment.create())
|
||||||
.apply(struc -> {
|
.apply(struc -> {
|
||||||
struc.get().setOnDragOver(event -> {
|
struc.get().setOnDragOver(event -> {
|
||||||
|
@ -110,13 +104,6 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
event.acceptTransferModes(TransferMode.ANY);
|
event.acceptTransferModes(TransferMode.ANY);
|
||||||
event.consume();
|
event.consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept drops from outside the app window
|
|
||||||
if (event.getGestureSource() == null
|
|
||||||
&& !event.getDragboard().getFiles().isEmpty()) {
|
|
||||||
event.acceptTransferModes(TransferMode.ANY);
|
|
||||||
event.consume();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
struc.get().setOnDragDropped(event -> {
|
struc.get().setOnDragDropped(event -> {
|
||||||
// Accept drops from inside the app window
|
// Accept drops from inside the app window
|
||||||
|
@ -138,29 +125,14 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
event.setDropCompleted(true);
|
event.setDropCompleted(true);
|
||||||
event.consume();
|
event.consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept drops from outside the app window
|
|
||||||
if (event.getGestureSource() == null) {
|
|
||||||
model.dropLocal(event.getDragboard().getFiles());
|
|
||||||
event.setDropCompleted(true);
|
|
||||||
event.consume();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
struc.get().setOnDragDetected(event -> {
|
struc.get().setOnDragDetected(event -> {
|
||||||
if (syncDownloaded.getValue()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var selected = syncItems.stream()
|
var selected = syncItems.stream()
|
||||||
.map(item -> item.getBrowserEntry())
|
.map(item -> item.getBrowserEntry())
|
||||||
.toList();
|
.toList();
|
||||||
Dragboard db = struc.get().startDragAndDrop(TransferMode.COPY);
|
Dragboard db = struc.get().startDragAndDrop(TransferMode.COPY);
|
||||||
|
|
||||||
var cc = BrowserClipboard.startDrag(null, selected, BrowserFileTransferMode.NORMAL);
|
var cc = new ClipboardContent();
|
||||||
if (cc == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var files = syncItems.stream()
|
var files = syncItems.stream()
|
||||||
.filter(item -> item.downloadFinished().get())
|
.filter(item -> item.downloadFinished().get())
|
||||||
.map(item -> {
|
.map(item -> {
|
||||||
|
@ -197,8 +169,7 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
model.clear(false);
|
model.clear(false);
|
||||||
event.consume();
|
event.consume();
|
||||||
});
|
});
|
||||||
}),
|
});
|
||||||
syncDownloaded);
|
|
||||||
|
|
||||||
stack.apply(struc -> {
|
stack.apply(struc -> {
|
||||||
model.getBrowserSessionModel().getDraggingFiles().addListener((observable, oldValue, newValue) -> {
|
model.getBrowserSessionModel().getDraggingFiles().addListener((observable, oldValue, newValue) -> {
|
||||||
|
|
|
@ -7,45 +7,49 @@ import io.xpipe.app.browser.file.LocalFileSystem;
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
import io.xpipe.app.browser.session.BrowserSessionModel;
|
import io.xpipe.app.browser.session.BrowserSessionModel;
|
||||||
import io.xpipe.app.issue.ErrorEvent;
|
import io.xpipe.app.issue.ErrorEvent;
|
||||||
import io.xpipe.app.util.BooleanScope;
|
import io.xpipe.app.util.DesktopHelper;
|
||||||
import io.xpipe.app.util.ShellTemp;
|
import io.xpipe.app.util.ShellTemp;
|
||||||
|
import io.xpipe.app.util.ThreadHelper;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.BooleanProperty;
|
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.value.ObservableBooleanValue;
|
import javafx.beans.value.ObservableBooleanValue;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
public class BrowserTransferModel {
|
public class BrowserTransferModel {
|
||||||
|
|
||||||
private static final Path TEMP = ShellTemp.getLocalTempDataDirectory("download");
|
private static final Path TEMP = ShellTemp.getLocalTempDataDirectory("download");
|
||||||
|
|
||||||
ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
|
|
||||||
Thread t = Executors.defaultThreadFactory().newThread(r);
|
|
||||||
t.setDaemon(true);
|
|
||||||
t.setName("file downloader");
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
BrowserSessionModel browserSessionModel;
|
BrowserSessionModel browserSessionModel;
|
||||||
ObservableList<Item> items = FXCollections.observableArrayList();
|
ObservableList<Item> items = FXCollections.observableArrayList();
|
||||||
BooleanProperty downloading = new SimpleBooleanProperty();
|
|
||||||
BooleanProperty allDownloaded = new SimpleBooleanProperty();
|
public BrowserTransferModel(BrowserSessionModel browserSessionModel) {
|
||||||
|
this.browserSessionModel = browserSessionModel;
|
||||||
|
var thread = ThreadHelper.createPlatformThread("file downloader", true,() -> {
|
||||||
|
while (true) {
|
||||||
|
Optional<Item> toDownload;
|
||||||
|
synchronized (items) {
|
||||||
|
toDownload = items.stream().filter(item -> !item.downloadFinished().get()).findFirst();
|
||||||
|
}
|
||||||
|
if (toDownload.isPresent()) {
|
||||||
|
downloadSingle(toDownload.get());
|
||||||
|
}
|
||||||
|
ThreadHelper.sleep(20);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
private void cleanDirectory() {
|
private void cleanDirectory() {
|
||||||
if (!Files.isDirectory(TEMP)) {
|
if (!Files.isDirectory(TEMP)) {
|
||||||
|
@ -63,95 +67,77 @@ public class BrowserTransferModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear(boolean delete) {
|
public void clear(boolean delete) {
|
||||||
items.clear();
|
synchronized (items) {
|
||||||
|
items.clear();
|
||||||
|
}
|
||||||
if (delete) {
|
if (delete) {
|
||||||
executor.submit(() -> {
|
cleanDirectory();
|
||||||
cleanDirectory();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drop(OpenFileSystemModel model, List<BrowserEntry> entries) {
|
public void drop(OpenFileSystemModel model, List<BrowserEntry> entries) {
|
||||||
entries.forEach(entry -> {
|
synchronized (items) {
|
||||||
var name = entry.getFileName();
|
entries.forEach(entry -> {
|
||||||
if (items.stream().anyMatch(item -> item.getName().equals(name))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Path file = TEMP.resolve(name);
|
|
||||||
var item = new Item(model, name, entry, file);
|
|
||||||
items.add(item);
|
|
||||||
allDownloaded.set(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dropLocal(List<File> entries) {
|
|
||||||
if (entries.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var empty = items.isEmpty();
|
|
||||||
try {
|
|
||||||
var paths = entries.stream().map(File::toPath).filter(Files::exists).toList();
|
|
||||||
for (Path path : paths) {
|
|
||||||
var entry = LocalFileSystem.getLocalBrowserEntry(path);
|
|
||||||
var name = entry.getFileName();
|
var name = entry.getFileName();
|
||||||
if (items.stream().anyMatch(item -> item.getName().equals(name))) {
|
if (items.stream().anyMatch(item -> item.getName().equals(name))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = new Item(null, name, entry, path);
|
Path file = TEMP.resolve(name);
|
||||||
item.progress.setValue(BrowserTransferProgress.finished(
|
var item = new Item(model, name, entry, file);
|
||||||
entry.getFileName(), entry.getRawFileEntry().getSize()));
|
|
||||||
items.add(item);
|
items.add(item);
|
||||||
}
|
});
|
||||||
} catch (Exception ex) {
|
|
||||||
ErrorEvent.fromThrowable(ex).handle();
|
|
||||||
}
|
|
||||||
if (empty) {
|
|
||||||
allDownloaded.set(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void download() {
|
public void downloadSingle(Item item) {
|
||||||
executor.submit(() -> {
|
try {
|
||||||
try {
|
FileUtils.forceMkdir(TEMP.toFile());
|
||||||
FileUtils.forceMkdir(TEMP.toFile());
|
} catch (IOException e) {
|
||||||
} catch (IOException e) {
|
ErrorEvent.fromThrowable(e).handle();
|
||||||
ErrorEvent.fromThrowable(e).handle();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.downloadFinished().get()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Item item : new ArrayList<>(items)) {
|
if (item.getOpenFileSystemModel() != null
|
||||||
if (item.downloadFinished().get()) {
|
&& item.getOpenFileSystemModel().isClosed()) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.getOpenFileSystemModel() != null
|
try {
|
||||||
&& item.getOpenFileSystemModel().isClosed()) {
|
var op = new BrowserFileTransferOperation(
|
||||||
continue;
|
LocalFileSystem.getLocalFileEntry(TEMP),
|
||||||
}
|
List.of(item.getBrowserEntry().getRawFileEntry()),
|
||||||
|
BrowserFileTransferMode.COPY,
|
||||||
try {
|
false,
|
||||||
try (var ignored = new BooleanScope(downloading).start()) {
|
progress -> {
|
||||||
var op = new BrowserFileTransferOperation(
|
item.getProgress().setValue(progress);
|
||||||
LocalFileSystem.getLocalFileEntry(TEMP),
|
item.getOpenFileSystemModel().getProgress().setValue(progress);
|
||||||
List.of(item.getBrowserEntry().getRawFileEntry()),
|
});
|
||||||
BrowserFileTransferMode.COPY,
|
op.execute();
|
||||||
false,
|
} catch (Throwable t) {
|
||||||
progress -> {
|
ErrorEvent.fromThrowable(t).handle();
|
||||||
item.getProgress().setValue(progress);
|
synchronized (items) {
|
||||||
item.getOpenFileSystemModel().getProgress().setValue(progress);
|
|
||||||
});
|
|
||||||
op.execute();
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
ErrorEvent.fromThrowable(t).handle();
|
|
||||||
items.remove(item);
|
items.remove(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allDownloaded.set(true);
|
}
|
||||||
});
|
|
||||||
|
public void transferToDownloads() throws Exception {
|
||||||
|
if (items.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = items.stream().map(item -> item.getLocalFile()).toList();
|
||||||
|
var downloads = DesktopHelper.getDownloadsDirectory();
|
||||||
|
for (Path file : files) {
|
||||||
|
Files.move(file, downloads.resolve(file.getFileName()), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
clear(true);
|
||||||
|
DesktopHelper.browseFileInDirectory(downloads.resolve(files.getFirst().getFileName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
|
|
|
@ -41,6 +41,7 @@ public class BrowserTransferProgress {
|
||||||
var share = (double) transferred / total;
|
var share = (double) transferred / total;
|
||||||
var rest = (1.0 - share) / share;
|
var rest = (1.0 - share) / share;
|
||||||
var restMillis = (long) (elapsed.toMillis() * rest);
|
var restMillis = (long) (elapsed.toMillis() * rest);
|
||||||
return Duration.of(restMillis, ChronoUnit.MILLIS);
|
var startupAdjustment = (long) (restMillis / (1.0 + Math.max(10000 - elapsed.toMillis(), 0) / 10000.0));
|
||||||
|
return Duration.of(restMillis + startupAdjustment, ChronoUnit.MILLIS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,9 @@ public class BrowserFileTransferOperation {
|
||||||
OutputStream outputStream = null;
|
OutputStream outputStream = null;
|
||||||
try {
|
try {
|
||||||
var fileSize = sourceFile.getFileSystem().getFileSize(sourceFile.getPath());
|
var fileSize = sourceFile.getFileSystem().getFileSize(sourceFile.getPath());
|
||||||
|
|
||||||
|
// Read the first few bytes to figure out possible command failure early
|
||||||
|
// before creating the output stream
|
||||||
inputStream = new BufferedInputStream(sourceFile.getFileSystem().openInput(sourceFile.getPath()), 1024);
|
inputStream = new BufferedInputStream(sourceFile.getFileSystem().openInput(sourceFile.getPath()), 1024);
|
||||||
inputStream.mark(1024);
|
inputStream.mark(1024);
|
||||||
var streamStart = new byte[1024];
|
var streamStart = new byte[1024];
|
||||||
|
|
|
@ -9,7 +9,6 @@ import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.input.MouseButton;
|
import javafx.scene.input.MouseButton;
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
@ -36,14 +35,12 @@ public class FilterComp extends Comp<CompStructure<CustomTextField>> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var filter = new CustomTextField();
|
var filter = new CustomTextField();
|
||||||
filter.alignmentProperty().bind(Bindings.createObjectBinding(() -> {
|
|
||||||
return filter.isFocused() || (filter.getText() != null && !filter.getText().isEmpty()) ? Pos.CENTER_LEFT : Pos.CENTER;
|
|
||||||
}, filter.textProperty(), filter.focusedProperty()));
|
|
||||||
filter.setMaxHeight(2000);
|
filter.setMaxHeight(2000);
|
||||||
filter.getStyleClass().add("filter-comp");
|
filter.getStyleClass().add("filter-comp");
|
||||||
filter.promptTextProperty().bind(AppI18n.observable("searchFilter"));
|
filter.promptTextProperty().bind(AppI18n.observable("searchFilter"));
|
||||||
filter.setLeft(fi);
|
filter.rightProperty().bind(Bindings.createObjectBinding(() -> {
|
||||||
filter.setRight(clear);
|
return filter.isFocused() ? clear : fi;
|
||||||
|
}, filter.focusedProperty()));
|
||||||
filter.setAccessibleText("Filter");
|
filter.setAccessibleText("Filter");
|
||||||
|
|
||||||
filterText.subscribe(val -> {
|
filterText.subscribe(val -> {
|
||||||
|
|
|
@ -28,6 +28,23 @@ public class DesktopHelper {
|
||||||
return Path.of(System.getProperty("user.home") + "/Desktop");
|
return Path.of(System.getProperty("user.home") + "/Desktop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Path getDownloadsDirectory() throws Exception {
|
||||||
|
if (OsType.getLocal() == OsType.WINDOWS) {
|
||||||
|
return Path.of(LocalShell.getLocalPowershell()
|
||||||
|
.executeSimpleStringCommand("(New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path"));
|
||||||
|
} else if (OsType.getLocal() == OsType.LINUX) {
|
||||||
|
try (var cmd = LocalShell.getShell().command("xdg-user-dir DOWNLOAD").start()) {
|
||||||
|
var read = cmd.readStdoutDiscardErr();
|
||||||
|
var exit = cmd.getExitCode();
|
||||||
|
if (exit == 0) {
|
||||||
|
return Path.of(read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path.of(System.getProperty("user.home") + "/Downloads");
|
||||||
|
}
|
||||||
|
|
||||||
public static void browsePathRemote(ShellControl sc, String path, FileKind kind) throws Exception {
|
public static void browsePathRemote(ShellControl sc, String path, FileKind kind) throws Exception {
|
||||||
var d = sc.getShellDialect();
|
var d = sc.getShellDialect();
|
||||||
switch (sc.getOsType()) {
|
switch (sc.getOsType()) {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
-fx-padding: 0 6 8 8;
|
-fx-padding: 0 6 8 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transfer > * {
|
.transfer > .download-background {
|
||||||
-fx-border-radius: 4;
|
-fx-border-radius: 4;
|
||||||
-fx-background-radius: 4;
|
-fx-background-radius: 4;
|
||||||
-fx-border-color: -color-border-default;
|
-fx-border-color: -color-border-default;
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
-fx-background-color: -color-bg-subtle;
|
-fx-background-color: -color-bg-subtle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transfer:highlighted > * {
|
.transfer:highlighted > .download-background {
|
||||||
-fx-border-color: -color-accent-emphasis;
|
-fx-border-color: -color-accent-emphasis;
|
||||||
-fx-background-color: derive(-color-bg-subtle, 5%);
|
-fx-background-color: derive(-color-bg-subtle, 5%);
|
||||||
}
|
}
|
||||||
|
@ -228,8 +228,8 @@
|
||||||
|
|
||||||
.browser .browser-content {
|
.browser .browser-content {
|
||||||
-fx-padding: 6 0 0 0;
|
-fx-padding: 6 0 0 0;
|
||||||
-fx-border-radius: 10 10 4 4;
|
-fx-border-radius: 4;
|
||||||
-fx-background-radius: 10 10 4 4;
|
-fx-background-radius: 4;
|
||||||
-fx-background-color: -color-bg-subtle, -color-bg-default;
|
-fx-background-color: -color-bg-subtle, -color-bg-default;
|
||||||
-fx-background-insets: 0, 7 0 0 0;
|
-fx-background-insets: 0, 7 0 0 0;
|
||||||
-fx-border-width: 1;
|
-fx-border-width: 1;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.filter-comp {
|
.filter-comp {
|
||||||
-fx-padding: 0.15em 0.3em 0.15em 0.3em;
|
-fx-padding: 0.15em 0.3em 0.15em 0.7em;
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ lockCreationAlertHeader=Indstil din nye master-adgangssætning
|
||||||
#custom
|
#custom
|
||||||
finish=Afslut
|
finish=Afslut
|
||||||
error=Der opstod en fejl
|
error=Der opstod en fejl
|
||||||
downloadStageDescription=Downloader filer til din lokale maskine, så du kan trække og slippe dem i dit oprindelige skrivebordsmiljø.
|
downloadStageDescription=Flytter downloadede filer til dit systems download-bibliotek og åbner det.
|
||||||
ok=Ok
|
ok=Ok
|
||||||
search=Søg efter
|
search=Søg efter
|
||||||
newFile=Ny fil
|
newFile=Ny fil
|
||||||
|
@ -108,7 +108,7 @@ deleteAlertHeader=Vil du slette de ($COUNT$) valgte elementer?
|
||||||
selectedElements=Udvalgte elementer:
|
selectedElements=Udvalgte elementer:
|
||||||
mustNotBeEmpty=$VALUE$ må ikke være tom
|
mustNotBeEmpty=$VALUE$ må ikke være tom
|
||||||
valueMustNotBeEmpty=Værdien må ikke være tom
|
valueMustNotBeEmpty=Værdien må ikke være tom
|
||||||
transferDescription=Drop filer til overførsel
|
transferDescription=Drop filer til download
|
||||||
dragFiles=Træk filer i browseren
|
dragFiles=Træk filer i browseren
|
||||||
dragLocalFiles=Træk lokale filer herfra
|
dragLocalFiles=Træk lokale filer herfra
|
||||||
null=$VALUE$ må ikke være nul
|
null=$VALUE$ må ikke være nul
|
||||||
|
|
|
@ -82,7 +82,7 @@ lockCreationAlertHeader=Lege deine neue Master-Passphrase fest
|
||||||
#custom
|
#custom
|
||||||
finish=Fertigstellen
|
finish=Fertigstellen
|
||||||
error=Ein Fehler ist aufgetreten
|
error=Ein Fehler ist aufgetreten
|
||||||
downloadStageDescription=Lädt Dateien auf deinen lokalen Rechner herunter, damit du sie per Drag & Drop in deine native Desktopumgebung ziehen kannst.
|
downloadStageDescription=Verschiebt heruntergeladene Dateien in das Download-Verzeichnis deines Systems und öffnet sie.
|
||||||
ok=Ok
|
ok=Ok
|
||||||
search=Suche
|
search=Suche
|
||||||
newFile=Neue Datei
|
newFile=Neue Datei
|
||||||
|
@ -107,7 +107,7 @@ deleteAlertHeader=Willst du die ($COUNT$) ausgewählten Elemente löschen?
|
||||||
selectedElements=Ausgewählte Elemente:
|
selectedElements=Ausgewählte Elemente:
|
||||||
mustNotBeEmpty=$VALUE$ darf nicht leer sein
|
mustNotBeEmpty=$VALUE$ darf nicht leer sein
|
||||||
valueMustNotBeEmpty=Der Wert darf nicht leer sein
|
valueMustNotBeEmpty=Der Wert darf nicht leer sein
|
||||||
transferDescription=Dateien zum Übertragen ablegen
|
transferDescription=Dateien zum Herunterladen ablegen
|
||||||
dragFiles=Dateien im Browser ziehen
|
dragFiles=Dateien im Browser ziehen
|
||||||
dragLocalFiles=Lokale Dateien von hier ziehen
|
dragLocalFiles=Lokale Dateien von hier ziehen
|
||||||
null=$VALUE$ muss nicht null sein
|
null=$VALUE$ muss nicht null sein
|
||||||
|
|
|
@ -80,7 +80,8 @@ lockCreationAlertHeader=Set your new master passphrase
|
||||||
#context: verb, exit
|
#context: verb, exit
|
||||||
finish=Finish
|
finish=Finish
|
||||||
error=An error occurred
|
error=An error occurred
|
||||||
downloadStageDescription=Downloads files to your local machine, so you can drag and drop them into your native desktop environment.
|
#force
|
||||||
|
downloadStageDescription=Moves downloaded files into your system downloads directory and opens it.
|
||||||
ok=Ok
|
ok=Ok
|
||||||
search=Search
|
search=Search
|
||||||
newFile=New file
|
newFile=New file
|
||||||
|
@ -105,7 +106,7 @@ deleteAlertHeader=Do you want to delete the ($COUNT$) selected elements?
|
||||||
selectedElements=Selected elements:
|
selectedElements=Selected elements:
|
||||||
mustNotBeEmpty=$VALUE$ must not be empty
|
mustNotBeEmpty=$VALUE$ must not be empty
|
||||||
valueMustNotBeEmpty=Value must not be empty
|
valueMustNotBeEmpty=Value must not be empty
|
||||||
transferDescription=Drop files to transfer
|
transferDescription=Drop files to download
|
||||||
dragFiles=Drag files within browser
|
dragFiles=Drag files within browser
|
||||||
dragLocalFiles=Drag local files from here
|
dragLocalFiles=Drag local files from here
|
||||||
null=$VALUE$ must be not null
|
null=$VALUE$ must be not null
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=Establecer frase de contraseña
|
||||||
lockCreationAlertHeader=Establece tu nueva frase de contraseña maestra
|
lockCreationAlertHeader=Establece tu nueva frase de contraseña maestra
|
||||||
finish=Terminar
|
finish=Terminar
|
||||||
error=Se ha producido un error
|
error=Se ha producido un error
|
||||||
downloadStageDescription=Descarga archivos a tu máquina local, para que puedas arrastrarlos y soltarlos en tu entorno de escritorio nativo.
|
downloadStageDescription=Mueve los archivos descargados al directorio de descargas de tu sistema y ábrelo.
|
||||||
ok=Ok
|
ok=Ok
|
||||||
search=Busca en
|
search=Busca en
|
||||||
newFile=Nuevo archivo
|
newFile=Nuevo archivo
|
||||||
|
@ -102,7 +102,7 @@ deleteAlertHeader=¿Quieres borrar los ($COUNT$) elementos seleccionados?
|
||||||
selectedElements=Elementos seleccionados:
|
selectedElements=Elementos seleccionados:
|
||||||
mustNotBeEmpty=$VALUE$ no debe estar vacío
|
mustNotBeEmpty=$VALUE$ no debe estar vacío
|
||||||
valueMustNotBeEmpty=El valor no debe estar vacío
|
valueMustNotBeEmpty=El valor no debe estar vacío
|
||||||
transferDescription=Soltar archivos para transferir
|
transferDescription=Soltar archivos para descargar
|
||||||
dragFiles=Arrastrar archivos dentro del navegador
|
dragFiles=Arrastrar archivos dentro del navegador
|
||||||
dragLocalFiles=Arrastra archivos locales desde aquí
|
dragLocalFiles=Arrastra archivos locales desde aquí
|
||||||
null=$VALUE$ debe ser no nulo
|
null=$VALUE$ debe ser no nulo
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=Définir une phrase de passe
|
||||||
lockCreationAlertHeader=Définis ta nouvelle phrase de passe principale
|
lockCreationAlertHeader=Définis ta nouvelle phrase de passe principale
|
||||||
finish=Finir
|
finish=Finir
|
||||||
error=Une erreur s'est produite
|
error=Une erreur s'est produite
|
||||||
downloadStageDescription=Télécharge les fichiers sur ta machine locale, afin que tu puisses les faire glisser et les déposer dans ton environnement de bureau natif.
|
downloadStageDescription=Déplace les fichiers téléchargés dans le répertoire des téléchargements de ton système et l'ouvre.
|
||||||
ok=Ok
|
ok=Ok
|
||||||
search=Rechercher
|
search=Rechercher
|
||||||
newFile=Nouveau fichier
|
newFile=Nouveau fichier
|
||||||
|
@ -102,7 +102,7 @@ deleteAlertHeader=Veux-tu supprimer les ($COUNT$) éléments sélectionnés ?
|
||||||
selectedElements=Éléments sélectionnés :
|
selectedElements=Éléments sélectionnés :
|
||||||
mustNotBeEmpty=$VALUE$ ne doit pas être vide
|
mustNotBeEmpty=$VALUE$ ne doit pas être vide
|
||||||
valueMustNotBeEmpty=La valeur ne doit pas être vide
|
valueMustNotBeEmpty=La valeur ne doit pas être vide
|
||||||
transferDescription=Dépose des fichiers à transférer
|
transferDescription=Dépose des fichiers à télécharger
|
||||||
dragFiles=Faire glisser des fichiers dans le navigateur
|
dragFiles=Faire glisser des fichiers dans le navigateur
|
||||||
dragLocalFiles=Fais glisser des fichiers locaux à partir d'ici
|
dragLocalFiles=Fais glisser des fichiers locaux à partir d'ici
|
||||||
null=$VALUE$ doit être non nul
|
null=$VALUE$ doit être non nul
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=Imposta una passphrase
|
||||||
lockCreationAlertHeader=Imposta la tua nuova passphrase principale
|
lockCreationAlertHeader=Imposta la tua nuova passphrase principale
|
||||||
finish=Terminare
|
finish=Terminare
|
||||||
error=Si è verificato un errore
|
error=Si è verificato un errore
|
||||||
downloadStageDescription=Scarica i file sul tuo computer locale, in modo che tu possa trascinarli e rilasciarli nel tuo ambiente desktop nativo.
|
downloadStageDescription=Sposta i file scaricati nella directory dei download del sistema e li apre.
|
||||||
ok=Ok
|
ok=Ok
|
||||||
search=Ricerca
|
search=Ricerca
|
||||||
newFile=Nuovo file
|
newFile=Nuovo file
|
||||||
|
@ -102,7 +102,7 @@ deleteAlertHeader=Vuoi cancellare gli elementi ($COUNT$) selezionati?
|
||||||
selectedElements=Elementi selezionati:
|
selectedElements=Elementi selezionati:
|
||||||
mustNotBeEmpty=$VALUE$ non deve essere vuoto
|
mustNotBeEmpty=$VALUE$ non deve essere vuoto
|
||||||
valueMustNotBeEmpty=Il valore non deve essere vuoto
|
valueMustNotBeEmpty=Il valore non deve essere vuoto
|
||||||
transferDescription=Rilasciare i file da trasferire
|
transferDescription=Scaricare i file
|
||||||
dragFiles=Trascinare i file nel browser
|
dragFiles=Trascinare i file nel browser
|
||||||
dragLocalFiles=Trascina i file locali da qui
|
dragLocalFiles=Trascina i file locali da qui
|
||||||
null=$VALUE$ deve essere non nullo
|
null=$VALUE$ deve essere non nullo
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=パスフレーズを設定する
|
||||||
lockCreationAlertHeader=新しいマスターパスフレーズを設定する
|
lockCreationAlertHeader=新しいマスターパスフレーズを設定する
|
||||||
finish=終了する
|
finish=終了する
|
||||||
error=エラーが発生した
|
error=エラーが発生した
|
||||||
downloadStageDescription=ファイルをローカルマシンにダウンロードし、ネイティブのデスクトップ環境にドラッグ&ドロップできるようにする。
|
downloadStageDescription=ダウンロードしたファイルをシステムのダウンロード・ディレクトリに移動し、開く。
|
||||||
ok=OK
|
ok=OK
|
||||||
search=検索
|
search=検索
|
||||||
newFile=新規ファイル
|
newFile=新規ファイル
|
||||||
|
@ -102,7 +102,7 @@ deleteAlertHeader=選択した ($COUNT$) 要素を削除するか?
|
||||||
selectedElements=選択された要素:
|
selectedElements=選択された要素:
|
||||||
mustNotBeEmpty=$VALUE$ は空であってはならない
|
mustNotBeEmpty=$VALUE$ は空であってはならない
|
||||||
valueMustNotBeEmpty=値は空であってはならない
|
valueMustNotBeEmpty=値は空であってはならない
|
||||||
transferDescription=ファイルをドロップして転送する
|
transferDescription=ファイルをドロップしてダウンロードする
|
||||||
dragFiles=ブラウザ内でファイルをドラッグする
|
dragFiles=ブラウザ内でファイルをドラッグする
|
||||||
dragLocalFiles=ここからローカルファイルをドラッグする
|
dragLocalFiles=ここからローカルファイルをドラッグする
|
||||||
null=$VALUE$ はnullであってはならない。
|
null=$VALUE$ はnullであってはならない。
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=Passphrase instellen
|
||||||
lockCreationAlertHeader=Stel je nieuwe hoofdwachtzin in
|
lockCreationAlertHeader=Stel je nieuwe hoofdwachtzin in
|
||||||
finish=Beëindigen
|
finish=Beëindigen
|
||||||
error=Er is een fout opgetreden
|
error=Er is een fout opgetreden
|
||||||
downloadStageDescription=Downloadt bestanden naar je lokale computer, zodat je ze naar je eigen desktopomgeving kunt slepen.
|
downloadStageDescription=Verplaatst gedownloade bestanden naar de downloadmap van je systeem en opent deze.
|
||||||
ok=Ok
|
ok=Ok
|
||||||
search=Zoeken
|
search=Zoeken
|
||||||
newFile=Nieuw bestand
|
newFile=Nieuw bestand
|
||||||
|
@ -102,7 +102,7 @@ deleteAlertHeader=Wil je de ($COUNT$) geselecteerde elementen verwijderen?
|
||||||
selectedElements=Geselecteerde elementen:
|
selectedElements=Geselecteerde elementen:
|
||||||
mustNotBeEmpty=$VALUE$ mag niet leeg zijn
|
mustNotBeEmpty=$VALUE$ mag niet leeg zijn
|
||||||
valueMustNotBeEmpty=Waarde mag niet leeg zijn
|
valueMustNotBeEmpty=Waarde mag niet leeg zijn
|
||||||
transferDescription=Bestanden laten vallen om over te dragen
|
transferDescription=Bestanden laten vallen om te downloaden
|
||||||
dragFiles=Bestanden slepen binnen browser
|
dragFiles=Bestanden slepen binnen browser
|
||||||
dragLocalFiles=Lokale bestanden van hier slepen
|
dragLocalFiles=Lokale bestanden van hier slepen
|
||||||
null=$VALUE$ moet not null zijn
|
null=$VALUE$ moet not null zijn
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=Define a frase-chave
|
||||||
lockCreationAlertHeader=Define a tua nova frase-chave principal
|
lockCreationAlertHeader=Define a tua nova frase-chave principal
|
||||||
finish=Termina
|
finish=Termina
|
||||||
error=Ocorreu um erro
|
error=Ocorreu um erro
|
||||||
downloadStageDescription=Descarrega ficheiros para a sua máquina local, para que possa arrastá-los e largá-los no seu ambiente de trabalho nativo.
|
downloadStageDescription=Move os ficheiros transferidos para o diretório de transferências do sistema e abre-o.
|
||||||
ok=Ok
|
ok=Ok
|
||||||
search=Procura
|
search=Procura
|
||||||
newFile=Novo ficheiro
|
newFile=Novo ficheiro
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=Установите парольную фразу
|
||||||
lockCreationAlertHeader=Установите новую главную кодовую фразу
|
lockCreationAlertHeader=Установите новую главную кодовую фразу
|
||||||
finish=Закончи
|
finish=Закончи
|
||||||
error=Произошла ошибка
|
error=Произошла ошибка
|
||||||
downloadStageDescription=Загрузи файлы на локальную машину, чтобы ты мог перетащить их в родное окружение рабочего стола.
|
downloadStageDescription=Перемести скачанные файлы в системный каталог загрузок и открой его.
|
||||||
ok=Ок
|
ok=Ок
|
||||||
search=Поиск
|
search=Поиск
|
||||||
newFile=Новый файл
|
newFile=Новый файл
|
||||||
|
@ -102,7 +102,7 @@ deleteAlertHeader=Хочешь удалить ($COUNT$) выбранные эл
|
||||||
selectedElements=Выбранные элементы:
|
selectedElements=Выбранные элементы:
|
||||||
mustNotBeEmpty=$VALUE$ не должен быть пустым
|
mustNotBeEmpty=$VALUE$ не должен быть пустым
|
||||||
valueMustNotBeEmpty=Значение не должно быть пустым
|
valueMustNotBeEmpty=Значение не должно быть пустым
|
||||||
transferDescription=Сбрасывать файлы для передачи
|
transferDescription=Сбрасывать файлы для загрузки
|
||||||
dragFiles=Перетаскивание файлов в браузере
|
dragFiles=Перетаскивание файлов в браузере
|
||||||
dragLocalFiles=Перетащите локальные файлы отсюда
|
dragLocalFiles=Перетащите локальные файлы отсюда
|
||||||
null=$VALUE$ должен быть не нулевым
|
null=$VALUE$ должен быть не нулевым
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=Parolayı ayarla
|
||||||
lockCreationAlertHeader=Yeni ana parolanızı ayarlayın
|
lockCreationAlertHeader=Yeni ana parolanızı ayarlayın
|
||||||
finish=Bitirmek
|
finish=Bitirmek
|
||||||
error=Bir hata oluştu
|
error=Bir hata oluştu
|
||||||
downloadStageDescription=Dosyaları yerel makinenize indirir, böylece bunları yerel masaüstü ortamınıza sürükleyip bırakabilirsiniz.
|
downloadStageDescription=İndirilen dosyaları sisteminizin indirilenler dizinine taşır ve açar.
|
||||||
ok=Tamam
|
ok=Tamam
|
||||||
search=Arama
|
search=Arama
|
||||||
newFile=Yeni dosya
|
newFile=Yeni dosya
|
||||||
|
@ -102,7 +102,7 @@ deleteAlertHeader=($COUNT$) seçili öğeleri silmek istiyor musunuz?
|
||||||
selectedElements=Seçilen unsurlar:
|
selectedElements=Seçilen unsurlar:
|
||||||
mustNotBeEmpty=$VALUE$ boş olmamalıdır
|
mustNotBeEmpty=$VALUE$ boş olmamalıdır
|
||||||
valueMustNotBeEmpty=Değer boş olmamalıdır
|
valueMustNotBeEmpty=Değer boş olmamalıdır
|
||||||
transferDescription=Aktarılacak dosyaları bırakın
|
transferDescription=İndirilecek dosyaları bırakın
|
||||||
dragFiles=Dosyaları tarayıcı içinde sürükleyin
|
dragFiles=Dosyaları tarayıcı içinde sürükleyin
|
||||||
dragLocalFiles=Yerel dosyaları buradan sürükleyin
|
dragLocalFiles=Yerel dosyaları buradan sürükleyin
|
||||||
null=$VALUE$ null olmamalıdır
|
null=$VALUE$ null olmamalıdır
|
||||||
|
|
|
@ -77,7 +77,7 @@ lockCreationAlertTitle=设置口令
|
||||||
lockCreationAlertHeader=设置新的主密码
|
lockCreationAlertHeader=设置新的主密码
|
||||||
finish=完成
|
finish=完成
|
||||||
error=发生错误
|
error=发生错误
|
||||||
downloadStageDescription=将文件下载到本地计算机,以便拖放到本地桌面环境中。
|
downloadStageDescription=将下载的文件移动到系统下载目录并打开。
|
||||||
ok=好的
|
ok=好的
|
||||||
search=搜索
|
search=搜索
|
||||||
newFile=新文件
|
newFile=新文件
|
||||||
|
@ -102,7 +102,7 @@ deleteAlertHeader=您想删除 ($COUNT$) 选定的元素吗?
|
||||||
selectedElements=选定要素:
|
selectedElements=选定要素:
|
||||||
mustNotBeEmpty=$VALUE$ 不得为空
|
mustNotBeEmpty=$VALUE$ 不得为空
|
||||||
valueMustNotBeEmpty=值不得为空
|
valueMustNotBeEmpty=值不得为空
|
||||||
transferDescription=下拉传输文件
|
transferDescription=下载文件
|
||||||
dragFiles=在浏览器中拖动文件
|
dragFiles=在浏览器中拖动文件
|
||||||
dragLocalFiles=从此处拖动本地文件
|
dragLocalFiles=从此处拖动本地文件
|
||||||
null=$VALUE$ 必须为非空
|
null=$VALUE$ 必须为非空
|
||||||
|
|
2
version
2
version
|
@ -1 +1 @@
|
||||||
10.1-6
|
10.1-7
|
||||||
|
|
Loading…
Reference in a new issue