Merge branch 'develop' into feature/hub

# Conflicts:
#	.github/workflows/appimage.yml
#	dist/linux/appimage/build.sh
#	dist/linux/debian/rules
#	dist/mac/dmg/build.sh
#	dist/win/build.ps1
This commit is contained in:
Sebastian Stenzel
2022-04-25 15:30:56 +02:00
25 changed files with 338 additions and 215 deletions
+4 -2
View File
@@ -1,11 +1,13 @@
# Number of days of inactivity before an issue becomes stale # Number of days of inactivity before an issue becomes stale
daysUntilStale: 180 daysUntilStale: 365
# Number of days of inactivity before a stale issue is closed # Number of days of inactivity before a stale issue is closed
daysUntilClose: 30 daysUntilClose: 90
# Issues with these labels will never be considered stale # Issues with these labels will never be considered stale
exemptLabels: exemptLabels:
- type:security-issue # never close automatically - type:security-issue # never close automatically
- type:feature-request # never close automatically - type:feature-request # never close automatically
- type:enhancement # never close automatically
- type:upstream-bug # never close automatically
- state:awaiting-response # handled by different bot - state:awaiting-response # handled by different bot
- state:blocked - state:blocked
- state:confirmed - state:confirmed
+7 -4
View File
@@ -61,10 +61,16 @@ jobs:
--output runtime --output runtime
--module-path "${JAVA_HOME}/jmods" --module-path "${JAVA_HOME}/jmods"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
--strip-native-commands
--no-header-files --no-header-files
--no-man-pages --no-man-pages
--strip-debug --strip-debug
--compress=1 --compress=1
- name: Prepare additional launcher
run: envsubst '${SEMVER_STR} ${REVISION_NUM}' < dist/linux/launcher-gtk2.properties > launcher-gtk2.properties
env:
SEMVER_STR: ${{ steps.versions.outputs.semVerStr }}
REVISION_NUM: ${{ steps.versions.outputs.revNum }}
- name: Run jpackage - name: Run jpackage
run: > run: >
${JAVA_HOME}/bin/jpackage ${JAVA_HOME}/bin/jpackage
@@ -91,12 +97,12 @@ jobs:
--java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\""
--java-options "-Dcryptomator.showTrayIcon=false" --java-options "-Dcryptomator.showTrayIcon=false"
--java-options "-Dcryptomator.buildNumber=\"appimage-${{ steps.versions.outputs.revNum }}\"" --java-options "-Dcryptomator.buildNumber=\"appimage-${{ steps.versions.outputs.revNum }}\""
--add-launcher Cryptomator-gtk2=launcher-gtk2.properties
--resource-dir dist/linux/resources --resource-dir dist/linux/resources
- name: Patch Cryptomator.AppDir - name: Patch Cryptomator.AppDir
run: | run: |
mv appdir/Cryptomator Cryptomator.AppDir mv appdir/Cryptomator Cryptomator.AppDir
cp -r dist/linux/appimage/resources/AppDir/* Cryptomator.AppDir/ cp -r dist/linux/appimage/resources/AppDir/* Cryptomator.AppDir/
envsubst '${REVISION_NO} ${SEMVER_STR}' < dist/linux/appimage/resources/AppDir/bin/cryptomator.sh > Cryptomator.AppDir/bin/cryptomator.sh
cp dist/linux/common/org.cryptomator.Cryptomator256.png Cryptomator.AppDir/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png cp dist/linux/common/org.cryptomator.Cryptomator256.png Cryptomator.AppDir/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png
cp dist/linux/common/org.cryptomator.Cryptomator512.png Cryptomator.AppDir/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png cp dist/linux/common/org.cryptomator.Cryptomator512.png Cryptomator.AppDir/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png
cp dist/linux/common/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg cp dist/linux/common/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg
@@ -108,9 +114,6 @@ jobs:
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
env:
REVISION_NO: ${{ steps.versions.outputs.revNum }}
SEMVER_STR: ${{ steps.versions.outputs.semVerStr }}
- name: Extract libjffi.so # workaround for https://github.com/cryptomator/cryptomator-linux/issues/27 - name: Extract libjffi.so # workaround for https://github.com/cryptomator/cryptomator-linux/issues/27
run: | run: |
JFFI_NATIVE_JAR=`ls lib/app/ | grep -e 'jffi-[1-9]\.[0-9]\{1,2\}.[0-9]\{1,2\}-native.jar'` JFFI_NATIVE_JAR=`ls lib/app/ | grep -e 'jffi-[1-9]\.[0-9]\{1,2\}.[0-9]\{1,2\}-native.jar'`
+3
View File
@@ -20,12 +20,14 @@ ${JAVA_HOME}/bin/jlink \
--output runtime \ --output runtime \
--module-path "${JAVA_HOME}/jmods" \ --module-path "${JAVA_HOME}/jmods" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \ --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \
--strip-native-commands \
--no-header-files \ --no-header-files \
--no-man-pages \ --no-man-pages \
--strip-debug \ --strip-debug \
--compress=1 --compress=1
# create app dir # create app dir
envsubst '${SEMVER_STR} ${REVISION_NUM}' < dist/linux/launcher-gtk2.properties > launcher-gtk2.properties
${JAVA_HOME}/bin/jpackage \ ${JAVA_HOME}/bin/jpackage \
--verbose \ --verbose \
--type app-image \ --type app-image \
@@ -48,6 +50,7 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" \ --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" \
--java-options "-Dcryptomator.showTrayIcon=false" \ --java-options "-Dcryptomator.showTrayIcon=false" \
--java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \ --java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NO}\"" \
--add-launcher cryptomator-gtk2=launcher-gtk2.properties \
--resource-dir ../resources --resource-dir ../resources
# transform AppDir # transform AppDir
+5 -20
View File
@@ -15,26 +15,11 @@ elif command -v pacman &> /dev/null; then # don't forget arch
GTK3_PRESENT=`pacman -Qi gtk3 &> /dev/null; echo $?` GTK3_PRESENT=`pacman -Qi gtk3 &> /dev/null; echo $?`
fi fi
if [ "$GTK2_PRESENT" -eq 0 ] && [ "$GTK3_PRESENT" -ne 0 ]; then
GTK_FLAG="-Djdk.gtk.version=2"
fi
# workaround for https://github.com/cryptomator/cryptomator-linux/issues/27 # workaround for https://github.com/cryptomator/cryptomator-linux/issues/27
export LD_PRELOAD=lib/app/libjffi.so export LD_PRELOAD=lib/app/libjffi.so
# start Cryptomator if [ "$GTK2_PRESENT" -eq 0 ] && [ "$GTK3_PRESENT" -ne 0 ]; then
./lib/runtime/bin/java \ bin/Cryptomator-gtk2
-p "lib/app/mods" \ else
-cp "lib/app/*" \ bin/Cryptomator
-Dfile.encoding="utf-8" \ fi
-Dcryptomator.logDir="~/.local/share/Cryptomator/logs" \
-Dcryptomator.pluginDir="~/.local/share/Cryptomator/plugins" \
-Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" \
-Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json" \
-Dcryptomator.ipcSocketPath="~/.config/Cryptomator/ipc.socket" \
-Dcryptomator.buildNumber="appimage-${REVISION_NO}" \
-Dcryptomator.appVersion="${SEMVER_STR}" \
$GTK_FLAG \
-Xss5m \
-Xmx256m \
-m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
+1
View File
@@ -19,6 +19,7 @@ override_dh_auto_build:
jlink \ jlink \
--output runtime \ --output runtime \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \ --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \
--strip-native-commands \
--no-header-files \ --no-header-files \
--no-man-pages \ --no-man-pages \
--strip-debug \ --strip-debug \
+12
View File
@@ -0,0 +1,12 @@
java-options=-Xss5m \
-Xmx256m \
-Dfile.encoding=\"utf-8\" \
-Dcryptomator.appVersion=\"${SEMVER_STR}\" \
-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\" \
-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\" \
-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\" \
-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\" \
-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\" \
-Dcryptomator.showTrayIcon=false \
-Dcryptomator.buildNumber=\"appimage-${REVISION_NUM}\" \
-Djdk.gtk.version=2
+1
View File
@@ -38,6 +38,7 @@ ${JAVA_HOME}/bin/jlink \
--output runtime \ --output runtime \
--module-path "${JAVA_HOME}/jmods" \ --module-path "${JAVA_HOME}/jmods" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \ --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \
--strip-native-commands \
--no-header-files \ --no-header-files \
--no-man-pages \ --no-man-pages \
--strip-debug \ --strip-debug \
+1
View File
@@ -42,6 +42,7 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
--output runtime ` --output runtime `
--module-path "$Env:JAVA_HOME/jmods" ` --module-path "$Env:JAVA_HOME/jmods" `
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr ` --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr `
--strip-native-commands `
--no-header-files ` --no-header-files `
--no-man-pages ` --no-man-pages `
--strip-debug ` --strip-debug `
@@ -3,9 +3,9 @@ package org.cryptomator.common.settings;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
public enum UiTheme { public enum UiTheme {
LIGHT("preferences.general.theme.light"), // LIGHT("preferences.interface.theme.light"), //
DARK("preferences.general.theme.dark"), // DARK("preferences.interface.theme.dark"), //
AUTOMATIC("preferences.general.theme.automatic"); AUTOMATIC("preferences.interface.theme.automatic");
public static UiTheme[] applicableValues() { public static UiTheme[] applicableValues() {
if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_WINDOWS) { if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_WINDOWS) {
@@ -21,15 +21,18 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import javafx.application.Application; import javafx.application.Application;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@Singleton @Singleton
public class Cryptomator { public class Cryptomator {
private static final long STARTUP_TIME = System.currentTimeMillis();
// DaggerCryptomatorComponent gets generated by Dagger. // DaggerCryptomatorComponent gets generated by Dagger.
// Run Maven and include target/generated-sources/annotations in your IDE. // Run Maven and include target/generated-sources/annotations in your IDE.
private static final CryptomatorComponent CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.create(); private static final CryptomatorComponent CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.factory().create(STARTUP_TIME);
private static final Logger LOG = LoggerFactory.getLogger(Cryptomator.class); private static final Logger LOG = LoggerFactory.getLogger(Cryptomator.class);
private final LoggerConfiguration logConfig; private final LoggerConfiguration logConfig;
@@ -50,6 +53,20 @@ public class Cryptomator {
} }
public static void main(String[] args) { public static void main(String[] args) {
var printVersion = Optional.ofNullable(args) //
.stream() //Streams either one element (the args-array) or zero elements
.flatMap(Arrays::stream) //
.anyMatch(arg -> "-v".equals(arg) || "--version".equals(arg));
if (printVersion) {
var appVer = System.getProperty("cryptomator.appVersion", "SNAPSHOT");
var buildNumber = System.getProperty("cryptomator.buildNumber", "SNAPSHOT");
//Reduce noise for parsers by using System.out directly
System.out.printf("Cryptomator version %s (build %s)%n", appVer, buildNumber);
return;
}
int exitCode = CRYPTOMATOR_COMPONENT.application().run(args); int exitCode = CRYPTOMATOR_COMPONENT.application().run(args);
LOG.info("Exit {}", exitCode); LOG.info("Exit {}", exitCode);
System.exit(exitCode); // end remaining non-daemon threads. System.exit(exitCode); // end remaining non-daemon threads.
@@ -63,6 +80,7 @@ public class Cryptomator {
*/ */
private int run(String[] args) { private int run(String[] args) {
logConfig.init(); logConfig.init();
LOG.debug("Dagger graph initialized after {}ms", System.currentTimeMillis() - STARTUP_TIME);
LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion().orElse("SNAPSHOT"), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH); LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion().orElse("SNAPSHOT"), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
debugMode.initialize(); debugMode.initialize();
supportedLanguages.applyPreferred(); supportedLanguages.applyPreferred();
@@ -112,7 +130,7 @@ public class Cryptomator {
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
LOG.info("JavaFX application started."); LOG.info("JavaFX runtime started after {}ms", System.currentTimeMillis() - STARTUP_TIME);
FxApplicationComponent component = CRYPTOMATOR_COMPONENT.fxAppComponentBuilder() // FxApplicationComponent component = CRYPTOMATOR_COMPONENT.fxAppComponentBuilder() //
.fxApplication(this) // .fxApplication(this) //
.primaryStage(primaryStage) // .primaryStage(primaryStage) //
@@ -1,10 +1,12 @@
package org.cryptomator.launcher; package org.cryptomator.launcher;
import dagger.BindsInstance;
import dagger.Component; import dagger.Component;
import org.cryptomator.common.CommonsModule; import org.cryptomator.common.CommonsModule;
import org.cryptomator.logging.LoggerModule; import org.cryptomator.logging.LoggerModule;
import org.cryptomator.ui.fxapp.FxApplicationComponent; import org.cryptomator.ui.fxapp.FxApplicationComponent;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@Singleton @Singleton
@@ -15,4 +17,9 @@ public interface CryptomatorComponent {
FxApplicationComponent.Builder fxAppComponentBuilder(); FxApplicationComponent.Builder fxAppComponentBuilder();
@Component.Factory
interface Factory {
CryptomatorComponent create(@BindsInstance @Named("startupTime") long startupTime);
}
} }
@@ -7,16 +7,20 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.stage.StageStyle; import javafx.stage.StageStyle;
import java.awt.SystemTray; import java.awt.SystemTray;
import java.io.IOException;
import java.io.UncheckedIOException;
@FxApplicationScoped @FxApplicationScoped
public class FxApplication { public class FxApplication {
private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class); private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class);
private final long startupTime;
private final Settings settings; private final Settings settings;
private final AppLaunchEventHandler launchEventHandler; private final AppLaunchEventHandler launchEventHandler;
private final Lazy<TrayMenuComponent> trayMenu; private final Lazy<TrayMenuComponent> trayMenu;
@@ -26,7 +30,8 @@ public class FxApplication {
private final AutoUnlocker autoUnlocker; private final AutoUnlocker autoUnlocker;
@Inject @Inject
FxApplication(Settings settings, AppLaunchEventHandler launchEventHandler, Lazy<TrayMenuComponent> trayMenu, FxApplicationWindows appWindows, FxApplicationStyle applicationStyle, FxApplicationTerminator applicationTerminator, AutoUnlocker autoUnlocker) { FxApplication(@Named("startupTime") long startupTime, Settings settings, AppLaunchEventHandler launchEventHandler, Lazy<TrayMenuComponent> trayMenu, FxApplicationWindows appWindows, FxApplicationStyle applicationStyle, FxApplicationTerminator applicationTerminator, AutoUnlocker autoUnlocker) {
this.startupTime = startupTime;
this.settings = settings; this.settings = settings;
this.launchEventHandler = launchEventHandler; this.launchEventHandler = launchEventHandler;
this.trayMenu = trayMenu; this.trayMenu = trayMenu;
@@ -61,6 +66,10 @@ public class FxApplication {
stage.setIconified(true); stage.setIconified(true);
} }
} }
LOG.debug("Main window initialized after {}ms", System.currentTimeMillis() - startupTime);
}).exceptionally(error -> {
LOG.error("Failed to show main window", error);
return null;
}); });
launchEventHandler.startHandlingLaunchEvents(); launchEventHandler.startHandlingLaunchEvents();
@@ -1,37 +1,25 @@
package org.cryptomator.ui.preferences; package org.cryptomator.ui.preferences;
import com.google.common.base.Strings;
import org.cryptomator.common.Environment; import org.cryptomator.common.Environment;
import org.cryptomator.common.LicenseHolder;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.UiTheme;
import org.cryptomator.integrations.autostart.AutoStartProvider; import org.cryptomator.integrations.autostart.AutoStartProvider;
import org.cryptomator.integrations.autostart.ToggleAutoStartFailedException; import org.cryptomator.integrations.autostart.ToggleAutoStartFailedException;
import org.cryptomator.integrations.keychain.KeychainAccessProvider; import org.cryptomator.integrations.keychain.KeychainAccessProvider;
import org.cryptomator.launcher.SupportedLanguages;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.traymenu.TrayMenuComponent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.application.Application; import javafx.application.Application;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.NodeOrientation;
import javafx.scene.control.CheckBox; import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox; import javafx.scene.control.ChoiceBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup; import javafx.scene.control.ToggleGroup;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import java.util.Locale;
import java.util.Optional; import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set; import java.util.Set;
@PreferencesScoped @PreferencesScoped
@@ -41,39 +29,23 @@ public class GeneralPreferencesController implements FxController {
private final Stage window; private final Stage window;
private final Settings settings; private final Settings settings;
private final boolean trayMenuInitialized;
private final boolean trayMenuSupported;
private final Optional<AutoStartProvider> autoStartProvider; private final Optional<AutoStartProvider> autoStartProvider;
private final ObjectProperty<SelectedPreferencesTab> selectedTabProperty;
private final LicenseHolder licenseHolder;
private final ResourceBundle resourceBundle;
private final Application application; private final Application application;
private final Environment environment; private final Environment environment;
private final Set<KeychainAccessProvider> keychainAccessProviders; private final Set<KeychainAccessProvider> keychainAccessProviders;
private final FxApplicationWindows appWindows; private final FxApplicationWindows appWindows;
public ChoiceBox<UiTheme> themeChoiceBox;
public ChoiceBox<KeychainAccessProvider> keychainBackendChoiceBox; public ChoiceBox<KeychainAccessProvider> keychainBackendChoiceBox;
public CheckBox showMinimizeButtonCheckbox;
public CheckBox showTrayIconCheckbox;
public CheckBox startHiddenCheckbox; public CheckBox startHiddenCheckbox;
public ChoiceBox<String> preferredLanguageChoiceBox;
public CheckBox debugModeCheckbox; public CheckBox debugModeCheckbox;
public CheckBox autoStartCheckbox; public CheckBox autoStartCheckbox;
public ToggleGroup nodeOrientation; public ToggleGroup nodeOrientation;
public RadioButton nodeOrientationLtr;
public RadioButton nodeOrientationRtl;
@Inject @Inject
GeneralPreferencesController(@PreferencesWindow Stage window, Settings settings, TrayMenuComponent trayMenu, Optional<AutoStartProvider> autoStartProvider, Set<KeychainAccessProvider> keychainAccessProviders, ObjectProperty<SelectedPreferencesTab> selectedTabProperty, LicenseHolder licenseHolder, ResourceBundle resourceBundle, Application application, Environment environment, FxApplicationWindows appWindows) { GeneralPreferencesController(@PreferencesWindow Stage window, Settings settings, Optional<AutoStartProvider> autoStartProvider, Set<KeychainAccessProvider> keychainAccessProviders, Application application, Environment environment, FxApplicationWindows appWindows) {
this.window = window; this.window = window;
this.settings = settings; this.settings = settings;
this.trayMenuInitialized = trayMenu.isInitialized();
this.trayMenuSupported = trayMenu.isSupported();
this.autoStartProvider = autoStartProvider; this.autoStartProvider = autoStartProvider;
this.keychainAccessProviders = keychainAccessProviders; this.keychainAccessProviders = keychainAccessProviders;
this.selectedTabProperty = selectedTabProperty;
this.licenseHolder = licenseHolder;
this.resourceBundle = resourceBundle;
this.application = application; this.application = application;
this.environment = environment; this.environment = environment;
this.appWindows = appWindows; this.appWindows = appWindows;
@@ -81,32 +53,12 @@ public class GeneralPreferencesController implements FxController {
@FXML @FXML
public void initialize() { public void initialize() {
themeChoiceBox.getItems().addAll(UiTheme.applicableValues());
if (!themeChoiceBox.getItems().contains(settings.theme().get())) {
settings.theme().set(UiTheme.LIGHT);
}
themeChoiceBox.valueProperty().bindBidirectional(settings.theme());
themeChoiceBox.setConverter(new UiThemeConverter(resourceBundle));
showMinimizeButtonCheckbox.selectedProperty().bindBidirectional(settings.showMinimizeButton());
showTrayIconCheckbox.selectedProperty().bindBidirectional(settings.showTrayIcon());
startHiddenCheckbox.selectedProperty().bindBidirectional(settings.startHidden()); startHiddenCheckbox.selectedProperty().bindBidirectional(settings.startHidden());
preferredLanguageChoiceBox.getItems().add(null);
preferredLanguageChoiceBox.getItems().addAll(SupportedLanguages.LANGUAGAE_TAGS);
preferredLanguageChoiceBox.valueProperty().bindBidirectional(settings.languageProperty());
preferredLanguageChoiceBox.setConverter(new LanguageTagConverter(resourceBundle));
debugModeCheckbox.selectedProperty().bindBidirectional(settings.debugMode()); debugModeCheckbox.selectedProperty().bindBidirectional(settings.debugMode());
autoStartProvider.ifPresent(autoStart -> autoStartCheckbox.setSelected(autoStart.isEnabled())); autoStartProvider.ifPresent(autoStart -> autoStartCheckbox.setSelected(autoStart.isEnabled()));
nodeOrientationLtr.setSelected(settings.userInterfaceOrientation().get() == NodeOrientation.LEFT_TO_RIGHT);
nodeOrientationRtl.setSelected(settings.userInterfaceOrientation().get() == NodeOrientation.RIGHT_TO_LEFT);
nodeOrientation.selectedToggleProperty().addListener(this::toggleNodeOrientation);
var keychainSettingsConverter = new KeychainProviderClassNameConverter(keychainAccessProviders); var keychainSettingsConverter = new KeychainProviderClassNameConverter(keychainAccessProviders);
keychainBackendChoiceBox.getItems().addAll(keychainAccessProviders); keychainBackendChoiceBox.getItems().addAll(keychainAccessProviders);
keychainBackendChoiceBox.setValue(keychainSettingsConverter.fromString(settings.keychainProvider().get())); keychainBackendChoiceBox.setValue(keychainSettingsConverter.fromString(settings.keychainProvider().get()));
@@ -114,29 +66,10 @@ public class GeneralPreferencesController implements FxController {
Bindings.bindBidirectional(settings.keychainProvider(), keychainBackendChoiceBox.valueProperty(), keychainSettingsConverter); Bindings.bindBidirectional(settings.keychainProvider(), keychainBackendChoiceBox.valueProperty(), keychainSettingsConverter);
} }
public boolean isTrayMenuInitialized() {
return trayMenuInitialized;
}
public boolean isTrayMenuSupported() {
return trayMenuSupported;
}
public boolean isAutoStartSupported() { public boolean isAutoStartSupported() {
return autoStartProvider.isPresent(); return autoStartProvider.isPresent();
} }
private void toggleNodeOrientation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
if (nodeOrientationLtr.equals(newValue)) {
settings.userInterfaceOrientation().set(NodeOrientation.LEFT_TO_RIGHT);
} else if (nodeOrientationRtl.equals(newValue)) {
settings.userInterfaceOrientation().set(NodeOrientation.RIGHT_TO_LEFT);
} else {
LOG.warn("Unexpected toggle option {}", newValue);
}
}
@FXML @FXML
public void toggleAutoStart() { public void toggleAutoStart() {
autoStartProvider.ifPresent(autoStart -> { autoStartProvider.ifPresent(autoStart -> {
@@ -155,16 +88,6 @@ public class GeneralPreferencesController implements FxController {
}); });
} }
public LicenseHolder getLicenseHolder() {
return licenseHolder;
}
@FXML
public void showContributeTab() {
selectedTabProperty.set(SelectedPreferencesTab.CONTRIBUTE);
}
@FXML @FXML
public void showLogfileDirectory() { public void showLogfileDirectory() {
environment.getLogDir().ifPresent(logDirPath -> application.getHostServices().showDocument(logDirPath.toUri().toString())); environment.getLogDir().ifPresent(logDirPath -> application.getHostServices().showDocument(logDirPath.toUri().toString()));
@@ -172,53 +95,7 @@ public class GeneralPreferencesController implements FxController {
/* Helper classes */ /* Helper classes */
private static class UiThemeConverter extends StringConverter<UiTheme> { private static class KeychainProviderDisplayNameConverter extends StringConverter<KeychainAccessProvider> {
private final ResourceBundle resourceBundle;
UiThemeConverter(ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
@Override
public String toString(UiTheme impl) {
return resourceBundle.getString(impl.getDisplayName());
}
@Override
public UiTheme fromString(String string) {
throw new UnsupportedOperationException();
}
}
private static class LanguageTagConverter extends StringConverter<String> {
private final ResourceBundle resourceBundle;
LanguageTagConverter(ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
@Override
public String toString(String tag) {
if (tag == null) {
return resourceBundle.getString("preferences.general.language.auto");
} else {
var locale = Locale.forLanguageTag(tag);
var lang = locale.getDisplayLanguage(locale);
var region = locale.getDisplayCountry(locale);
return lang + (Strings.isNullOrEmpty(region) ? "" : " (" + region + ")");
}
}
@Override
public String fromString(String displayLanguage) {
throw new UnsupportedOperationException();
}
}
private class KeychainProviderDisplayNameConverter extends StringConverter<KeychainAccessProvider> {
@Override @Override
public String toString(KeychainAccessProvider provider) { public String toString(KeychainAccessProvider provider) {
@@ -0,0 +1,156 @@
package org.cryptomator.ui.preferences;
import com.google.common.base.Strings;
import org.cryptomator.common.LicenseHolder;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.UiTheme;
import org.cryptomator.launcher.SupportedLanguages;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.traymenu.TrayMenuComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.property.ObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.geometry.NodeOrientation;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.util.StringConverter;
import java.util.Locale;
import java.util.ResourceBundle;
@PreferencesScoped
public class InterfacePreferencesController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(InterfacePreferencesController.class);
private final Settings settings;
private final boolean trayMenuInitialized;
private final boolean trayMenuSupported;
private final ObjectProperty<SelectedPreferencesTab> selectedTabProperty;
private final LicenseHolder licenseHolder;
private final ResourceBundle resourceBundle;
public ChoiceBox<UiTheme> themeChoiceBox;
public CheckBox showMinimizeButtonCheckbox;
public CheckBox showTrayIconCheckbox;
public ChoiceBox<String> preferredLanguageChoiceBox;
public ToggleGroup nodeOrientation;
public RadioButton nodeOrientationLtr;
public RadioButton nodeOrientationRtl;
@Inject
InterfacePreferencesController(Settings settings, TrayMenuComponent trayMenu, ObjectProperty<SelectedPreferencesTab> selectedTabProperty, LicenseHolder licenseHolder, ResourceBundle resourceBundle) {
this.settings = settings;
this.trayMenuInitialized = trayMenu.isInitialized();
this.trayMenuSupported = trayMenu.isSupported();
this.selectedTabProperty = selectedTabProperty;
this.licenseHolder = licenseHolder;
this.resourceBundle = resourceBundle;
}
@FXML
public void initialize() {
themeChoiceBox.getItems().addAll(UiTheme.applicableValues());
if (!themeChoiceBox.getItems().contains(settings.theme().get())) {
settings.theme().set(UiTheme.LIGHT);
}
themeChoiceBox.valueProperty().bindBidirectional(settings.theme());
themeChoiceBox.setConverter(new UiThemeConverter(resourceBundle));
showMinimizeButtonCheckbox.selectedProperty().bindBidirectional(settings.showMinimizeButton());
showTrayIconCheckbox.selectedProperty().bindBidirectional(settings.showTrayIcon());
preferredLanguageChoiceBox.getItems().add(null);
preferredLanguageChoiceBox.getItems().addAll(SupportedLanguages.LANGUAGAE_TAGS);
preferredLanguageChoiceBox.valueProperty().bindBidirectional(settings.languageProperty());
preferredLanguageChoiceBox.setConverter(new LanguageTagConverter(resourceBundle));
nodeOrientationLtr.setSelected(settings.userInterfaceOrientation().get() == NodeOrientation.LEFT_TO_RIGHT);
nodeOrientationRtl.setSelected(settings.userInterfaceOrientation().get() == NodeOrientation.RIGHT_TO_LEFT);
nodeOrientation.selectedToggleProperty().addListener(this::toggleNodeOrientation);
}
public boolean isTrayMenuInitialized() {
return trayMenuInitialized;
}
public boolean isTrayMenuSupported() {
return trayMenuSupported;
}
private void toggleNodeOrientation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
if (nodeOrientationLtr.equals(newValue)) {
settings.userInterfaceOrientation().set(NodeOrientation.LEFT_TO_RIGHT);
} else if (nodeOrientationRtl.equals(newValue)) {
settings.userInterfaceOrientation().set(NodeOrientation.RIGHT_TO_LEFT);
} else {
LOG.warn("Unexpected toggle option {}", newValue);
}
}
public LicenseHolder getLicenseHolder() {
return licenseHolder;
}
@FXML
public void showContributeTab() {
selectedTabProperty.set(SelectedPreferencesTab.CONTRIBUTE);
}
/* Helper classes */
private static class UiThemeConverter extends StringConverter<UiTheme> {
private final ResourceBundle resourceBundle;
UiThemeConverter(ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
@Override
public String toString(UiTheme impl) {
return resourceBundle.getString(impl.getDisplayName());
}
@Override
public UiTheme fromString(String string) {
throw new UnsupportedOperationException();
}
}
private static class LanguageTagConverter extends StringConverter<String> {
private final ResourceBundle resourceBundle;
LanguageTagConverter(ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
@Override
public String toString(String tag) {
if (tag == null) {
return resourceBundle.getString("preferences.interface.language.auto");
} else {
var locale = Locale.forLanguageTag(tag);
var lang = locale.getDisplayLanguage(locale);
var region = locale.getDisplayCountry(locale);
return lang + (Strings.isNullOrEmpty(region) ? "" : " (" + region + ")");
}
}
@Override
public String fromString(String displayLanguage) {
throw new UnsupportedOperationException();
}
}
}
@@ -24,6 +24,7 @@ public class PreferencesController implements FxController {
private final BooleanBinding updateAvailable; private final BooleanBinding updateAvailable;
public TabPane tabPane; public TabPane tabPane;
public Tab generalTab; public Tab generalTab;
public Tab interfaceTab;
public Tab volumeTab; public Tab volumeTab;
public Tab updatesTab; public Tab updatesTab;
public Tab contributeTab; public Tab contributeTab;
@@ -50,10 +51,11 @@ public class PreferencesController implements FxController {
private Tab getTabToSelect(SelectedPreferencesTab selectedTab) { private Tab getTabToSelect(SelectedPreferencesTab selectedTab) {
return switch (selectedTab) { return switch (selectedTab) {
case UPDATES -> updatesTab;
case VOLUME -> volumeTab;
case CONTRIBUTE -> contributeTab;
case GENERAL -> generalTab; case GENERAL -> generalTab;
case INTERFACE -> interfaceTab;
case VOLUME -> volumeTab;
case UPDATES -> updatesTab;
case CONTRIBUTE -> contributeTab;
case ABOUT -> aboutTab; case ABOUT -> aboutTab;
case ANY -> updateAvailable.get() ? updatesTab : generalTab; case ANY -> updateAvailable.get() ? updatesTab : generalTab;
}; };
@@ -64,6 +64,11 @@ abstract class PreferencesModule {
@FxControllerKey(GeneralPreferencesController.class) @FxControllerKey(GeneralPreferencesController.class)
abstract FxController bindGeneralPreferencesController(GeneralPreferencesController controller); abstract FxController bindGeneralPreferencesController(GeneralPreferencesController controller);
@Binds
@IntoMap
@FxControllerKey(InterfacePreferencesController.class)
abstract FxController bindInterfacePreferencesController(InterfacePreferencesController controller);
@Binds @Binds
@IntoMap @IntoMap
@FxControllerKey(UpdatesPreferencesController.class) @FxControllerKey(UpdatesPreferencesController.class)
@@ -11,6 +11,11 @@ public enum SelectedPreferencesTab {
*/ */
GENERAL, GENERAL,
/**
* Show interface tab
*/
INTERFACE,
/** /**
* Show volume tab * Show volume tab
*/ */
+9 -1
View File
@@ -9,7 +9,7 @@
fx:controller="org.cryptomator.ui.preferences.PreferencesController" fx:controller="org.cryptomator.ui.preferences.PreferencesController"
minWidth="-Infinity" minWidth="-Infinity"
maxWidth="-Infinity" maxWidth="-Infinity"
prefWidth="500" prefWidth="650"
tabMinWidth="60" tabMinWidth="60"
tabClosingPolicy="UNAVAILABLE" tabClosingPolicy="UNAVAILABLE"
tabDragPolicy="FIXED"> tabDragPolicy="FIXED">
@@ -22,6 +22,14 @@
<fx:include source="preferences_general.fxml"/> <fx:include source="preferences_general.fxml"/>
</content> </content>
</Tab> </Tab>
<Tab fx:id="interfaceTab" id="INTERFACE" text="%preferences.interface">
<graphic>
<FontAwesome5IconView glyph="EYE"/>
</graphic>
<content>
<fx:include source="preferences_interface.fxml"/>
</content>
</Tab>
<Tab fx:id="volumeTab" id="VOLUME" text="%preferences.volume"> <Tab fx:id="volumeTab" id="VOLUME" text="%preferences.volume">
<graphic> <graphic>
<FontAwesome5IconView glyph="HDD"/> <FontAwesome5IconView glyph="HDD"/>
@@ -11,9 +11,9 @@
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.preferences.AboutController" fx:controller="org.cryptomator.ui.preferences.AboutController"
spacing="18"> spacing="24">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
<children> <children>
<HBox spacing="12" VBox.vgrow="NEVER"> <HBox spacing="12" VBox.vgrow="NEVER">
@@ -13,9 +13,9 @@
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.preferences.SupporterCertificateController" fx:controller="org.cryptomator.ui.preferences.SupporterCertificateController"
spacing="18"> spacing="24">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
<children> <children>
<StackPane VBox.vgrow="NEVER" prefHeight="60"> <StackPane VBox.vgrow="NEVER" prefHeight="60">
@@ -5,54 +5,35 @@
<?import javafx.scene.control.ChoiceBox?> <?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Hyperlink?> <?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.ToggleGroup?> <?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.Region?>
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.preferences.GeneralPreferencesController" fx:controller="org.cryptomator.ui.preferences.GeneralPreferencesController"
spacing="6"> spacing="12">
<fx:define> <fx:define>
<ToggleGroup fx:id="nodeOrientation"/> <ToggleGroup fx:id="nodeOrientation"/>
</fx:define> </fx:define>
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
<children> <children>
<HBox spacing="6" alignment="CENTER_LEFT"> <CheckBox fx:id="autoStartCheckbox" text="%preferences.general.autoStart" visible="${controller.autoStartSupported}" managed="${controller.autoStartSupported}" onAction="#toggleAutoStart"/>
<Label text="%preferences.general.theme"/>
<ChoiceBox fx:id="themeChoiceBox" disable="${!controller.licenseHolder.validLicense}"/>
<Hyperlink styleClass="hyperlink-underline,hyperlink-muted" text="%preferences.general.unlockThemes" onAction="#showContributeTab" visible="${!controller.licenseHolder.validLicense}" managed="${!controller.licenseHolder.validLicense}"/>
</HBox>
<HBox spacing="6" alignment="CENTER_LEFT">
<Label text="%preferences.general.interfaceOrientation" HBox.hgrow="NEVER"/>
<RadioButton fx:id="nodeOrientationLtr" text="%preferences.general.interfaceOrientation.ltr" alignment="CENTER_LEFT" toggleGroup="${nodeOrientation}"/>
<RadioButton fx:id="nodeOrientationRtl" text="%preferences.general.interfaceOrientation.rtl" alignment="CENTER_RIGHT" toggleGroup="${nodeOrientation}"/>
</HBox>
<CheckBox fx:id="showMinimizeButtonCheckbox" text="%preferences.general.showMinimizeButton" visible="${controller.trayMenuInitialized}" managed="${controller.trayMenuInitialized}"/>
<CheckBox fx:id="showTrayIconCheckbox" text="%preferences.general.showTrayIcon" visible="${controller.trayMenuSupported}" managed="${controller.trayMenuSupported}"/>
<CheckBox fx:id="startHiddenCheckbox" text="%preferences.general.startHidden" /> <CheckBox fx:id="startHiddenCheckbox" text="%preferences.general.startHidden" />
<HBox spacing="6" alignment="CENTER_LEFT"> <HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%preferences.general.language"/>
<ChoiceBox fx:id="preferredLanguageChoiceBox"/>
</HBox>
<HBox spacing="6" alignment="CENTER_LEFT">
<CheckBox fx:id="debugModeCheckbox" text="%preferences.general.debugLogging"/>
<Hyperlink styleClass="hyperlink-underline" text="%preferences.general.debugDirectory" onAction="#showLogfileDirectory"/>
</HBox>
<HBox spacing="6" alignment="CENTER_LEFT">
<Label text="%preferences.general.keychainBackend"/> <Label text="%preferences.general.keychainBackend"/>
<ChoiceBox fx:id="keychainBackendChoiceBox"/> <ChoiceBox fx:id="keychainBackendChoiceBox"/>
</HBox> </HBox>
<CheckBox fx:id="autoStartCheckbox" text="%preferences.general.autoStart" visible="${controller.autoStartSupported}" managed="${controller.autoStartSupported}" onAction="#toggleAutoStart"/> <Region VBox.vgrow="ALWAYS"/>
<HBox spacing="12" alignment="CENTER_LEFT">
<CheckBox fx:id="debugModeCheckbox" text="%preferences.general.debugLogging"/>
<Hyperlink styleClass="hyperlink-underline" text="%preferences.general.debugDirectory" onAction="#showLogfileDirectory"/>
</HBox>
</children> </children>
</VBox> </VBox>
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.preferences.InterfacePreferencesController"
spacing="12">
<fx:define>
<ToggleGroup fx:id="nodeOrientation"/>
</fx:define>
<padding>
<Insets topRightBottomLeft="24"/>
</padding>
<children>
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%preferences.interface.theme"/>
<ChoiceBox fx:id="themeChoiceBox" disable="${!controller.licenseHolder.validLicense}"/>
<Hyperlink styleClass="hyperlink-underline,hyperlink-muted" text="%preferences.interface.unlockThemes" onAction="#showContributeTab" visible="${!controller.licenseHolder.validLicense}" managed="${!controller.licenseHolder.validLicense}"/>
</HBox>
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%preferences.interface.language"/>
<ChoiceBox fx:id="preferredLanguageChoiceBox"/>
</HBox>
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%preferences.interface.interfaceOrientation" HBox.hgrow="NEVER"/>
<RadioButton fx:id="nodeOrientationLtr" text="%preferences.interface.interfaceOrientation.ltr" alignment="CENTER_LEFT" toggleGroup="${nodeOrientation}"/>
<RadioButton fx:id="nodeOrientationRtl" text="%preferences.interface.interfaceOrientation.rtl" alignment="CENTER_RIGHT" toggleGroup="${nodeOrientation}"/>
</HBox>
<CheckBox fx:id="showMinimizeButtonCheckbox" text="%preferences.interface.showMinimizeButton" visible="${controller.trayMenuInitialized}" managed="${controller.trayMenuInitialized}"/>
<CheckBox fx:id="showTrayIconCheckbox" text="%preferences.interface.showTrayIcon" visible="${controller.trayMenuSupported}" managed="${controller.trayMenuSupported}"/>
</children>
</VBox>
@@ -11,19 +11,19 @@
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.preferences.UpdatesPreferencesController" fx:controller="org.cryptomator.ui.preferences.UpdatesPreferencesController"
spacing="6"> spacing="12">
<fx:define> <fx:define>
<FormattedString fx:id="linkLabel" format="%preferences.updates.updateAvailable" arg1="${controller.latestVersion}"/> <FormattedString fx:id="linkLabel" format="%preferences.updates.updateAvailable" arg1="${controller.latestVersion}"/>
</fx:define> </fx:define>
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
<children> <children>
<FormattedLabel format="%preferences.updates.currentVersion" arg1="${controller.currentVersion}" textAlignment="CENTER" wrapText="true"/> <FormattedLabel format="%preferences.updates.currentVersion" arg1="${controller.currentVersion}" textAlignment="CENTER" wrapText="true"/>
<CheckBox fx:id="checkForUpdatesCheckbox" text="%preferences.updates.autoUpdateCheck"/> <CheckBox fx:id="checkForUpdatesCheckbox" text="%preferences.updates.autoUpdateCheck"/>
<VBox alignment="CENTER" spacing="6"> <VBox alignment="CENTER" spacing="12">
<Button text="%preferences.updates.checkNowBtn" defaultButton="true" onAction="#checkNow" contentDisplay="${controller.checkForUpdatesButtonState}"> <Button text="%preferences.updates.checkNowBtn" defaultButton="true" onAction="#checkNow" contentDisplay="${controller.checkForUpdatesButtonState}">
<graphic> <graphic>
<FontAwesome5Spinner fx:id="spinner" glyphSize="12"/> <FontAwesome5Spinner fx:id="spinner" glyphSize="12"/>
@@ -10,23 +10,23 @@
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.preferences.VolumePreferencesController" fx:controller="org.cryptomator.ui.preferences.VolumePreferencesController"
spacing="6"> spacing="12">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="24"/>
</padding> </padding>
<children> <children>
<HBox spacing="6" alignment="CENTER_LEFT"> <HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%preferences.volume.type"/> <Label text="%preferences.volume.type"/>
<ChoiceBox fx:id="volumeTypeChoiceBox"/> <ChoiceBox fx:id="volumeTypeChoiceBox"/>
</HBox> </HBox>
<HBox spacing="6" alignment="CENTER_LEFT" visible="${controller.showWebDavSettings}"> <HBox spacing="12" alignment="CENTER_LEFT" visible="${controller.showWebDavSettings}">
<Label text="%preferences.volume.webdav.port"/> <Label text="%preferences.volume.webdav.port"/>
<NumericTextField fx:id="webDavPortField"/> <NumericTextField fx:id="webDavPortField"/>
<Button text="%generic.button.apply" fx:id="changeWebDavPortButton" onAction="#doChangeWebDavPort"/> <Button text="%generic.button.apply" fx:id="changeWebDavPortButton" onAction="#doChangeWebDavPort"/>
</HBox> </HBox>
<HBox spacing="6" alignment="CENTER_LEFT" visible="${controller.showWebDavScheme}"> <HBox spacing="12" alignment="CENTER_LEFT" visible="${controller.showWebDavScheme}">
<Label text="%preferences.volume.webdav.scheme"/> <Label text="%preferences.volume.webdav.scheme"/>
<ChoiceBox fx:id="webDavUrlSchemeChoiceBox" maxWidth="Infinity"/> <ChoiceBox fx:id="webDavUrlSchemeChoiceBox" maxWidth="Infinity"/>
</HBox> </HBox>
+14 -12
View File
@@ -191,23 +191,25 @@ health.fix.failTip=Fix failed, see log for details
preferences.title=Preferences preferences.title=Preferences
## General ## General
preferences.general=General preferences.general=General
preferences.general.theme=Look & Feel
preferences.general.theme.automatic=Automatic
preferences.general.theme.light=Light
preferences.general.theme.dark=Dark
preferences.general.unlockThemes=Unlock dark mode
preferences.general.showMinimizeButton=Show minimize button
preferences.general.showTrayIcon=Show tray icon (requires restart)
preferences.general.startHidden=Hide window when starting Cryptomator preferences.general.startHidden=Hide window when starting Cryptomator
preferences.general.language=Language (requires restart)
preferences.general.language.auto=System Default
preferences.general.debugLogging=Enable debug logging preferences.general.debugLogging=Enable debug logging
preferences.general.debugDirectory=Reveal log files preferences.general.debugDirectory=Reveal log files
preferences.general.autoStart=Launch Cryptomator on system start preferences.general.autoStart=Launch Cryptomator on system start
preferences.general.keychainBackend=Store passwords with preferences.general.keychainBackend=Store passwords with
preferences.general.interfaceOrientation=Interface Orientation ## Interface
preferences.general.interfaceOrientation.ltr=Left to Right preferences.interface=Interface
preferences.general.interfaceOrientation.rtl=Right to Left preferences.interface.theme=Look & Feel
preferences.interface.theme.automatic=Automatic
preferences.interface.theme.dark=Dark
preferences.interface.theme.light=Light
preferences.interface.unlockThemes=Unlock dark mode
preferences.interface.language=Language (requires restart)
preferences.interface.language.auto=System Default
preferences.interface.interfaceOrientation=Interface Orientation
preferences.interface.interfaceOrientation.ltr=Left to Right
preferences.interface.interfaceOrientation.rtl=Right to Left
preferences.interface.showMinimizeButton=Show minimize button
preferences.interface.showTrayIcon=Show tray icon (requires restart)
## Volume ## Volume
preferences.volume=Virtual Drive preferences.volume=Virtual Drive
preferences.volume.type=Volume Type preferences.volume.type=Volume Type