mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-04-26 04:27:02 -04:00
Merge branch 'master' of https://github.com/totalvoidness/cryptomator
This commit is contained in:
@@ -16,12 +16,15 @@ import java.util.ResourceBundle;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.layout.HBox;
|
||||
@@ -44,6 +47,9 @@ public class MainController implements Initializable, InitializationListener, Un
|
||||
|
||||
private Stage stage;
|
||||
|
||||
@FXML
|
||||
private ContextMenu directoryContextMenu;
|
||||
|
||||
@FXML
|
||||
private HBox rootPane;
|
||||
|
||||
@@ -58,9 +64,11 @@ public class MainController implements Initializable, InitializationListener, Un
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
this.rb = rb;
|
||||
|
||||
final ObservableList<Directory> items = FXCollections.observableList(Settings.load().getDirectories());
|
||||
directoryList.setItems(items);
|
||||
directoryList.setCellFactory(this::createDirecoryListCell);
|
||||
directoryList.getSelectionModel().getSelectedItems().addListener(this::selectedDirectoryDidChange);
|
||||
directoryList.getItems().addAll(Settings.load().getDirectories());
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -70,22 +78,38 @@ public class MainController implements Initializable, InitializationListener, Un
|
||||
if (file != null && file.canWrite()) {
|
||||
final Directory dir = new Directory(file.toPath());
|
||||
directoryList.getItems().add(dir);
|
||||
Settings.load().getDirectories().clear();
|
||||
Settings.load().getDirectories().addAll(directoryList.getItems());
|
||||
directoryList.getSelectionModel().selectLast();
|
||||
}
|
||||
}
|
||||
|
||||
private ListCell<Directory> createDirecoryListCell(ListView<Directory> param) {
|
||||
return new DirectoryListCell();
|
||||
final DirectoryListCell cell = new DirectoryListCell();
|
||||
cell.setContextMenu(directoryContextMenu);
|
||||
return cell;
|
||||
}
|
||||
|
||||
private void selectedDirectoryDidChange(ListChangeListener.Change<? extends Directory> change) {
|
||||
final Directory selectedDir = directoryList.getSelectionModel().getSelectedItem();
|
||||
stage.setTitle(selectedDir.getName());
|
||||
showDirectory(selectedDir);
|
||||
if (selectedDir == null) {
|
||||
stage.setTitle(rb.getString("app.name"));
|
||||
showWelcomeView();
|
||||
} else {
|
||||
stage.setTitle(selectedDir.getName());
|
||||
showDirectory(selectedDir);
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void didClickRemoveSelectedEntry(ActionEvent e) {
|
||||
final Directory selectedDir = directoryList.getSelectionModel().getSelectedItem();
|
||||
directoryList.getItems().remove(selectedDir);
|
||||
directoryList.getSelectionModel().clearSelection();
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
// Subcontroller for right panel
|
||||
// ****************************************
|
||||
|
||||
private void showDirectory(Directory directory) {
|
||||
try {
|
||||
if (directory.isUnlocked()) {
|
||||
@@ -100,10 +124,6 @@ public class MainController implements Initializable, InitializationListener, Un
|
||||
}
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
// Subcontroller for right panel
|
||||
// ****************************************
|
||||
|
||||
private <T> T showView(String fxml) {
|
||||
try {
|
||||
final FXMLLoader loader = new FXMLLoader(getClass().getResource(fxml), rb);
|
||||
@@ -116,6 +136,10 @@ public class MainController implements Initializable, InitializationListener, Un
|
||||
}
|
||||
}
|
||||
|
||||
private void showWelcomeView() {
|
||||
this.showView("/welcome.fxml");
|
||||
}
|
||||
|
||||
private void showInitializeView(Directory directory) {
|
||||
final InitializeController ctrl = showView("/initialize.fxml");
|
||||
ctrl.setDirectory(directory);
|
||||
|
||||
@@ -77,7 +77,7 @@ public class UnlockController implements Initializable {
|
||||
// ****************************************
|
||||
|
||||
@FXML
|
||||
protected void didClickUnlockButton(ActionEvent event) {
|
||||
private void didClickUnlockButton(ActionEvent event) {
|
||||
final String masterKeyFileName = usernameBox.getValue() + Aes256Cryptor.MASTERKEY_FILE_EXT;
|
||||
final Path masterKeyPath = directory.getPath().resolve(masterKeyFileName);
|
||||
final CharSequence password = passwordField.getCharacters();
|
||||
|
||||
@@ -52,7 +52,7 @@ public class UnlockedController implements Initializable {
|
||||
}
|
||||
|
||||
@FXML
|
||||
protected void closeVault(ActionEvent event) {
|
||||
private void didClickCloseVault(ActionEvent event) {
|
||||
directory.unmount();
|
||||
directory.stopServer();
|
||||
directory.setUnlocked(false);
|
||||
@@ -82,7 +82,7 @@ public class UnlockedController implements Initializable {
|
||||
|
||||
private class IoSamplingAnimationHandler implements EventHandler<ActionEvent> {
|
||||
|
||||
private static final double BYTES_TO_MEGABYTES_FACTOR = IO_SAMPLING_INTERVAL / 1024.0 / 1024.0;
|
||||
private static final double BYTES_TO_MEGABYTES_FACTOR = 1.0 / IO_SAMPLING_INTERVAL / 1024.0 / 1024.0;
|
||||
private final CryptorIOSampling sampler;
|
||||
private final Series<Number, Number> decryptedBytes;
|
||||
private final Series<Number, Number> encryptedBytes;
|
||||
|
||||
@@ -1,19 +1,55 @@
|
||||
package org.cryptomator.ui.controls;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.shape.Circle;
|
||||
|
||||
import org.cryptomator.ui.model.Directory;
|
||||
|
||||
public class DirectoryListCell extends ListCell<Directory> {
|
||||
public class DirectoryListCell extends ListCell<Directory> implements ChangeListener<Boolean> {
|
||||
|
||||
// TODO: fancy graphics instead of circles ;-)
|
||||
private final Circle statusIndicator = new Circle(3.0);
|
||||
|
||||
public DirectoryListCell() {
|
||||
setGraphic(statusIndicator);
|
||||
setGraphicTextGap(12.0);
|
||||
setContentDisplay(ContentDisplay.LEFT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(Directory item, boolean empty) {
|
||||
final Directory oldItem = super.getItem();
|
||||
if (oldItem != null) {
|
||||
oldItem.unlockedProperty().removeListener(this);
|
||||
}
|
||||
super.updateItem(item, empty);
|
||||
if (item == null) {
|
||||
setText(null);
|
||||
setTooltip(null);
|
||||
statusIndicator.setVisible(false);
|
||||
} else {
|
||||
setText(item.getName());
|
||||
setTooltip(new Tooltip(item.getPath().toString()));
|
||||
statusIndicator.setVisible(true);
|
||||
item.unlockedProperty().addListener(this);
|
||||
updateStatusIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
|
||||
updateStatusIndicator();
|
||||
}
|
||||
|
||||
private void updateStatusIndicator() {
|
||||
final Paint statusColor = getItem().isUnlocked() ? Color.LIME : Color.RED;
|
||||
statusIndicator.setFill(statusColor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import java.io.Serializable;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.crypto.SamplingDecorator;
|
||||
@@ -29,8 +32,9 @@ public class Directory implements Serializable {
|
||||
|
||||
private final WebDAVServer server = new WebDAVServer();
|
||||
private final Cryptor cryptor = SamplingDecorator.decorate(new Aes256Cryptor());
|
||||
private final ObjectProperty<Boolean> unlocked = new SimpleObjectProperty<Boolean>(this, "unlocked", Boolean.FALSE);
|
||||
private final Path path;
|
||||
private boolean unlocked;
|
||||
// private boolean unlocked;
|
||||
private String unmountCommand;
|
||||
private final Runnable shutdownTask = new ShutdownTask();
|
||||
|
||||
@@ -103,12 +107,16 @@ public class Directory implements Serializable {
|
||||
return cryptor;
|
||||
}
|
||||
|
||||
public boolean isUnlocked() {
|
||||
public ObjectProperty<Boolean> unlockedProperty() {
|
||||
return unlocked;
|
||||
}
|
||||
|
||||
public boolean isUnlocked() {
|
||||
return unlocked.get();
|
||||
}
|
||||
|
||||
public void setUnlocked(boolean unlocked) {
|
||||
this.unlocked = unlocked;
|
||||
this.unlocked.set(unlocked);
|
||||
}
|
||||
|
||||
public WebDAVServer getServer() {
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.model.Directory;
|
||||
@@ -54,7 +54,7 @@ public class Settings implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<Directory> directories;
|
||||
private List<Directory> directories;
|
||||
private String username;
|
||||
|
||||
private Settings() {
|
||||
@@ -96,14 +96,14 @@ public class Settings implements Serializable {
|
||||
|
||||
/* Getter/Setter */
|
||||
|
||||
public Collection<Directory> getDirectories() {
|
||||
public List<Directory> getDirectories() {
|
||||
if (directories == null) {
|
||||
directories = new ArrayList<>();
|
||||
}
|
||||
return directories;
|
||||
}
|
||||
|
||||
public void setDirectories(Collection<Directory> directories) {
|
||||
public void setDirectories(List<Directory> directories) {
|
||||
this.directories = directories;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
|
||||
app.name=Cryptomator
|
||||
|
||||
# main.fxml
|
||||
main.directoryList.contextMenu.remove=Remove from list
|
||||
main.directoryList.contextMenu.addUser=Add user
|
||||
main.directoryList.contextMenu.changePassword=Change password
|
||||
|
||||
|
||||
# welcome.fxml
|
||||
welcome.welcomeLabel=Welcome to Cryptomator
|
||||
|
||||
@@ -14,13 +14,23 @@
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.control.ToolBar?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ContextMenu?>
|
||||
<?import javafx.scene.control.MenuItem?>
|
||||
|
||||
<HBox fx:id="rootPane" prefHeight="400.0" prefWidth="600.0" fx:controller="org.cryptomator.ui.MainController" xmlns:fx="http://javafx.com/fxml">
|
||||
|
||||
|
||||
<fx:define>
|
||||
<fx:include fx:id="welcomeView" source="welcome.fxml" />
|
||||
<ContextMenu fx:id="directoryContextMenu">
|
||||
<items>
|
||||
<MenuItem text="%main.directoryList.contextMenu.remove" onAction="#didClickRemoveSelectedEntry" />
|
||||
<!-- TODO: -->
|
||||
<MenuItem text="%main.directoryList.contextMenu.addUser" disable="true" />
|
||||
<MenuItem text="%main.directoryList.contextMenu.changePassword" disable="true" />
|
||||
</items>
|
||||
</ContextMenu>
|
||||
</fx:define>
|
||||
|
||||
|
||||
<children>
|
||||
<VBox prefWidth="200.0">
|
||||
<children>
|
||||
@@ -34,7 +44,7 @@
|
||||
</VBox>
|
||||
<Pane fx:id="contentPane">
|
||||
<children>
|
||||
<fx:reference source="welcomeView"/>
|
||||
<fx:reference source="welcomeView" />
|
||||
</children>
|
||||
</Pane>
|
||||
</children>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<Label fx:id="messageLabel" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2" />
|
||||
|
||||
<!-- Row 1 -->
|
||||
<Button text="%unlocked.button.lock" defaultButton="true" GridPane.rowIndex="1" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="RIGHT" prefWidth="150.0" onAction="#closeVault" focusTraversable="false"/>
|
||||
<Button text="%unlocked.button.lock" defaultButton="true" GridPane.rowIndex="1" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="RIGHT" prefWidth="150.0" onAction="#didClickCloseVault" focusTraversable="false"/>
|
||||
|
||||
<!-- Row 2 -->
|
||||
<LineChart fx:id="ioGraph" GridPane.rowIndex="2" GridPane.columnIndex="0" GridPane.columnSpan="2" animated="false" createSymbols="false" prefHeight="300.0" legendVisible="true" legendSide="BOTTOM" verticalZeroLineVisible="false" verticalGridLinesVisible="false" horizontalGridLinesVisible="true">
|
||||
|
||||
Reference in New Issue
Block a user