mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-04-21 18:16:54 -04:00
Updated to integrations-api 1.1.0-beta2
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -28,10 +28,10 @@
|
||||
|
||||
<!-- cryptomator dependencies -->
|
||||
<cryptomator.cryptofs.version>2.3.1</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>1.1.0-beta1</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.0.0</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.0.0</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.0.1</cryptomator.integrations.linux.version>
|
||||
<cryptomator.integrations.version>1.1.0-beta2</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.1.0-beta1</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.1.0-beta1</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.1.0-beta1</cryptomator.integrations.linux.version>
|
||||
<cryptomator.fuse.version>1.3.3</cryptomator.fuse.version>
|
||||
<cryptomator.dokany.version>1.3.3</cryptomator.dokany.version>
|
||||
<cryptomator.webdav.version>1.2.6</cryptomator.webdav.version>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import org.cryptomator.integrations.autostart.AutoStartProvider;
|
||||
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
|
||||
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
|
||||
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
|
||||
import org.cryptomator.integrations.tray.TrayMenuController;
|
||||
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
|
||||
|
||||
module org.cryptomator.desktop {
|
||||
requires org.cryptomator.cryptofs;
|
||||
@@ -29,10 +27,7 @@ module org.cryptomator.desktop {
|
||||
requires logback.classic;
|
||||
requires logback.core;
|
||||
|
||||
uses AutoStartProvider;
|
||||
uses KeychainAccessProvider;
|
||||
uses TrayIntegrationProvider;
|
||||
uses UiAppearanceProvider;
|
||||
provides TrayMenuController with AwtTrayMenuController;
|
||||
|
||||
opens org.cryptomator.common.settings to com.google.gson;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
@Deprecated // to be moved to integrations-api 1.1.0
|
||||
@Singleton
|
||||
public class PluginClassLoader extends URLClassLoader {
|
||||
|
||||
|
||||
@@ -44,9 +44,9 @@ public class KeychainManager implements KeychainAccessProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void storePassphrase(String key, CharSequence passphrase) throws KeychainAccessException {
|
||||
getKeychainOrFail().storePassphrase(key, passphrase);
|
||||
setPassphraseStored(key, true);
|
||||
storePassphrase(key, null, passphrase);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,11 +69,9 @@ public class KeychainManager implements KeychainAccessProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void changePassphrase(String key, CharSequence passphrase) throws KeychainAccessException {
|
||||
if (isPassphraseStored(key)) {
|
||||
getKeychainOrFail().changePassphrase(key, passphrase);
|
||||
setPassphraseStored(key, true);
|
||||
}
|
||||
changePassphrase(key, null, passphrase);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,42 +2,30 @@ package org.cryptomator.common.keychain;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.cryptomator.common.PluginClassLoader;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.ObjectExpression;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.List;
|
||||
|
||||
@Module
|
||||
public class KeychainModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static Set<ServiceLoader.Provider<KeychainAccessProvider>> provideAvailableKeychainAccessProviderFactories(PluginClassLoader classLoader) {
|
||||
return ServiceLoader.load(KeychainAccessProvider.class, classLoader).stream().collect(Collectors.toUnmodifiableSet());
|
||||
static List<KeychainAccessProvider> provideSupportedKeychainAccessProviders() {
|
||||
return KeychainAccessProvider.get().toList();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static Set<KeychainAccessProvider> provideSupportedKeychainAccessProviders(Set<ServiceLoader.Provider<KeychainAccessProvider>> availableFactories) {
|
||||
return availableFactories.stream() //
|
||||
.map(ServiceLoader.Provider::get) //
|
||||
.filter(KeychainAccessProvider::isSupported) //
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static ObjectExpression<KeychainAccessProvider> provideKeychainAccessProvider(Settings settings, Set<KeychainAccessProvider> providers) {
|
||||
static ObjectExpression<KeychainAccessProvider> provideKeychainAccessProvider(Settings settings, List<KeychainAccessProvider> providers) {
|
||||
return Bindings.createObjectBinding(() -> {
|
||||
var selectedProviderClass = settings.keychainProvider().get();
|
||||
var selectedProvider = providers.stream().filter(provider -> provider.getClass().getName().equals(selectedProviderClass)).findAny();
|
||||
var fallbackProvider = providers.stream().findAny().orElse(null);
|
||||
var fallbackProvider = providers.stream().findFirst().orElse(null);
|
||||
return selectedProvider.orElse(fallbackProvider);
|
||||
}, settings.keychainProvider());
|
||||
}
|
||||
|
||||
@@ -34,21 +34,20 @@ public abstract class UiLauncherModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static Optional<UiAppearanceProvider> provideAppearanceProvider(PluginClassLoader classLoader) {
|
||||
return ServiceLoader.load(UiAppearanceProvider.class, classLoader).findFirst();
|
||||
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
|
||||
return UiAppearanceProvider.get();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static Optional<AutoStartProvider> provideAutostartProvider(PluginClassLoader classLoader) {
|
||||
return ServiceLoader.load(AutoStartProvider.class, classLoader).findFirst();
|
||||
static Optional<AutoStartProvider> provideAutostartProvider() {
|
||||
return AutoStartProvider.get();
|
||||
}
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static Optional<TrayIntegrationProvider> provideTrayIntegrationProvider(PluginClassLoader classLoader) {
|
||||
return ServiceLoader.load(TrayIntegrationProvider.class, classLoader).findFirst();
|
||||
static Optional<TrayIntegrationProvider> provideTrayIntegrationProvider() {
|
||||
return TrayIntegrationProvider.get();
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -27,6 +27,7 @@ import javafx.scene.control.Toggle;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.StringConverter;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
@@ -46,7 +47,7 @@ public class GeneralPreferencesController implements FxController {
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final Application application;
|
||||
private final Environment environment;
|
||||
private final Set<KeychainAccessProvider> keychainAccessProviders;
|
||||
private final List<KeychainAccessProvider> keychainAccessProviders;
|
||||
private final ErrorComponent.Builder errorComponent;
|
||||
public ChoiceBox<UiTheme> themeChoiceBox;
|
||||
public ChoiceBox<KeychainAccessProvider> keychainBackendChoiceBox;
|
||||
@@ -61,7 +62,7 @@ public class GeneralPreferencesController implements FxController {
|
||||
|
||||
|
||||
@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, ErrorComponent.Builder errorComponent) {
|
||||
GeneralPreferencesController(@PreferencesWindow Stage window, Settings settings, TrayMenuComponent trayMenu, Optional<AutoStartProvider> autoStartProvider, List<KeychainAccessProvider> keychainAccessProviders, ObjectProperty<SelectedPreferencesTab> selectedTabProperty, LicenseHolder licenseHolder, ResourceBundle resourceBundle, Application application, Environment environment, ErrorComponent.Builder errorComponent) {
|
||||
this.window = window;
|
||||
this.settings = settings;
|
||||
this.trayMenuInitialized = trayMenu.isInitialized();
|
||||
@@ -204,9 +205,9 @@ public class GeneralPreferencesController implements FxController {
|
||||
|
||||
private static class KeychainProviderClassNameConverter extends StringConverter<KeychainAccessProvider> {
|
||||
|
||||
private final Set<KeychainAccessProvider> keychainAccessProviders;
|
||||
private final List<KeychainAccessProvider> keychainAccessProviders;
|
||||
|
||||
public KeychainProviderClassNameConverter(Set<KeychainAccessProvider> keychainAccessProviders) {
|
||||
public KeychainProviderClassNameConverter(List<KeychainAccessProvider> keychainAccessProviders) {
|
||||
this.keychainAccessProviders = keychainAccessProviders;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.integrations.common.Priority;
|
||||
import org.cryptomator.integrations.tray.ActionItem;
|
||||
import org.cryptomator.integrations.tray.SeparatorItem;
|
||||
import org.cryptomator.integrations.tray.SubMenuItem;
|
||||
import org.cryptomator.integrations.tray.TrayMenuItem;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Menu;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.TrayIcon;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
@Priority(Priority.FALLBACK)
|
||||
public class AwtTrayMenuController implements org.cryptomator.integrations.tray.TrayMenuController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AwtTrayMenuController.class);
|
||||
|
||||
private TrayIcon trayIcon;
|
||||
private PopupMenu menu = new PopupMenu();
|
||||
|
||||
@Override
|
||||
public void showTrayIcon(InputStream rawImageData, Runnable defaultAction, String tooltip) throws IOException {
|
||||
var image = Toolkit.getDefaultToolkit().createImage(rawImageData.readAllBytes());
|
||||
trayIcon = new TrayIcon(image, tooltip, menu);
|
||||
|
||||
trayIcon.setImageAutoSize(true);
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
trayIcon.addActionListener(evt -> defaultAction.run());
|
||||
}
|
||||
|
||||
try {
|
||||
SystemTray.getSystemTray().add(trayIcon);
|
||||
LOG.debug("initialized tray icon");
|
||||
} catch (AWTException e) {
|
||||
LOG.error("Error adding tray icon", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTrayMenu(List<TrayMenuItem> items) {
|
||||
menu.removeAll();
|
||||
addChildren(menu, items);
|
||||
}
|
||||
|
||||
private void addChildren(Menu menu, List<TrayMenuItem> items) {
|
||||
for (var item : items) {
|
||||
// TODO: use Pattern Matching for switch, once available
|
||||
if (item instanceof ActionItem a) {
|
||||
var menuItem = new MenuItem(a.title());
|
||||
menuItem.addActionListener(evt -> a.action().run());
|
||||
menu.add(menuItem);
|
||||
} else if (item instanceof SeparatorItem) {
|
||||
menu.addSeparator();
|
||||
} else if (item instanceof SubMenuItem s) {
|
||||
var submenu = new Menu(s.title());
|
||||
addChildren(submenu, s.items());
|
||||
menu.add(submenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.TrayIcon;
|
||||
|
||||
@TrayMenuScoped
|
||||
public class TrayIconController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TrayIconController.class);
|
||||
|
||||
private final TrayMenuController trayMenuController;
|
||||
private final TrayIcon trayIcon;
|
||||
private volatile boolean initialized;
|
||||
|
||||
@Inject
|
||||
TrayIconController(TrayImageFactory imageFactory, TrayMenuController trayMenuController) {
|
||||
this.trayMenuController = trayMenuController;
|
||||
this.trayIcon = new TrayIcon(imageFactory.loadImage(), "Cryptomator", trayMenuController.getMenu());
|
||||
}
|
||||
|
||||
public synchronized void initializeTrayIcon() throws IllegalStateException {
|
||||
Preconditions.checkState(!initialized);
|
||||
|
||||
trayIcon.setImageAutoSize(true);
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
trayIcon.addActionListener(trayMenuController::showMainWindow);
|
||||
}
|
||||
|
||||
try {
|
||||
SystemTray.getSystemTray().add(trayIcon);
|
||||
LOG.debug("initialized tray icon");
|
||||
} catch (AWTException e) {
|
||||
LOG.error("Error adding tray icon", e);
|
||||
}
|
||||
|
||||
trayMenuController.initTrayMenu();
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.integrations.uiappearance.Theme;
|
||||
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.Image;
|
||||
import java.awt.Toolkit;
|
||||
import java.util.Optional;
|
||||
|
||||
@TrayMenuScoped
|
||||
class TrayImageFactory {
|
||||
|
||||
private final Optional<UiAppearanceProvider> appearanceProvider;
|
||||
|
||||
@Inject
|
||||
TrayImageFactory(Optional<UiAppearanceProvider> appearanceProvider) {
|
||||
this.appearanceProvider = appearanceProvider;
|
||||
}
|
||||
|
||||
public Image loadImage() {
|
||||
String resourceName = SystemUtils.IS_OS_MAC_OSX ? getMacResourceName() : getWinOrLinuxResourceName();
|
||||
return Toolkit.getDefaultToolkit().getImage(getClass().getResource(resourceName));
|
||||
}
|
||||
|
||||
private String getMacResourceName() {
|
||||
return "/img/tray_icon_mac.png";
|
||||
}
|
||||
|
||||
private String getWinOrLinuxResourceName() {
|
||||
return "/img/tray_icon.png";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,28 +5,34 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import dagger.Lazy;
|
||||
import com.google.common.base.Preconditions;
|
||||
import dagger.Subcomponent;
|
||||
import org.cryptomator.integrations.tray.TrayMenuController;
|
||||
|
||||
import java.awt.SystemTray;
|
||||
import java.util.Optional;
|
||||
|
||||
@TrayMenuScoped
|
||||
@Subcomponent
|
||||
@Subcomponent(modules = {TrayMenuModule.class})
|
||||
public interface TrayMenuComponent {
|
||||
|
||||
Lazy<TrayIconController> trayIconController();
|
||||
Optional<TrayMenuController> trayMenuController();
|
||||
|
||||
org.cryptomator.ui.traymenu.TrayMenuController trayMenuController2(); // TODO tmp name
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if a tray icon can be installed
|
||||
*/
|
||||
default boolean isSupported() {
|
||||
return SystemTray.isSupported();
|
||||
// TODO add isSupported to API and move SystemTray.isSupported() to impl
|
||||
return trayMenuController().isPresent() && SystemTray.isSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if a tray icon has been installed
|
||||
*/
|
||||
default boolean isInitialized() {
|
||||
return isSupported() && trayIconController().get().isInitialized();
|
||||
return isSupported() && trayMenuController2().isInitialized();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,8 +41,9 @@ public interface TrayMenuComponent {
|
||||
* @throws IllegalStateException If already added
|
||||
*/
|
||||
default void initializeTrayIcon() throws IllegalStateException {
|
||||
assert isSupported();
|
||||
trayIconController().get().initializeTrayIcon();
|
||||
Preconditions.checkState(isSupported(), "system tray not supported");
|
||||
|
||||
trayMenuController2().initTrayMenu();
|
||||
}
|
||||
|
||||
@Subcomponent.Builder
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.integrations.tray.ActionItem;
|
||||
import org.cryptomator.integrations.tray.SeparatorItem;
|
||||
import org.cryptomator.integrations.tray.SubMenuItem;
|
||||
import org.cryptomator.integrations.tray.TrayMenuItem;
|
||||
import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.launcher.AppLifecycleListener;
|
||||
import org.cryptomator.ui.launcher.FxApplicationStarter;
|
||||
@@ -10,44 +16,61 @@ import javax.inject.Inject;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.collections.ObservableList;
|
||||
import java.awt.Menu;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.Image;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventObject;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@TrayMenuScoped
|
||||
class TrayMenuController {
|
||||
public class TrayMenuController {
|
||||
|
||||
private static final String TRAY_ICON_MAC = "/img/tray_icon_mac.png";
|
||||
private static final String TRAY_ICON = "/img/tray_icon.png";
|
||||
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final AppLifecycleListener appLifecycle;
|
||||
private final FxApplicationStarter fxApplicationStarter;
|
||||
private final ObservableList<Vault> vaults;
|
||||
private final PopupMenu menu;
|
||||
private final org.cryptomator.integrations.tray.TrayMenuController trayMenu;
|
||||
|
||||
private volatile boolean initialized;
|
||||
|
||||
@Inject
|
||||
TrayMenuController(ResourceBundle resourceBundle, AppLifecycleListener appLifecycle, FxApplicationStarter fxApplicationStarter, ObservableList<Vault> vaults) {
|
||||
TrayMenuController(ResourceBundle resourceBundle, AppLifecycleListener appLifecycle, FxApplicationStarter fxApplicationStarter, ObservableList<Vault> vaults, Optional<org.cryptomator.integrations.tray.TrayMenuController> trayMenu) {
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.appLifecycle = appLifecycle;
|
||||
this.fxApplicationStarter = fxApplicationStarter;
|
||||
this.vaults = vaults;
|
||||
this.menu = new PopupMenu();
|
||||
this.trayMenu = trayMenu.orElse(null);
|
||||
}
|
||||
|
||||
public PopupMenu getMenu() {
|
||||
return menu;
|
||||
}
|
||||
public synchronized void initTrayMenu() {
|
||||
Preconditions.checkState(!initialized, "tray icon already initialized");
|
||||
|
||||
public void initTrayMenu() {
|
||||
vaults.addListener(this::vaultListChanged);
|
||||
vaults.forEach(v -> {
|
||||
v.displayNameProperty().addListener(this::vaultListChanged);
|
||||
});
|
||||
rebuildMenu();
|
||||
|
||||
try (var image = getClass().getResourceAsStream(SystemUtils.IS_OS_MAC_OSX ? TRAY_ICON_MAC : TRAY_ICON)) {
|
||||
trayMenu.showTrayIcon(image, this::showMainWindow, "Cryptomator");
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to load embedded resource", e);
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
private void vaultListChanged(@SuppressWarnings("unused") Observable observable) {
|
||||
@@ -56,58 +79,42 @@ class TrayMenuController {
|
||||
}
|
||||
|
||||
private void rebuildMenu() {
|
||||
menu.removeAll();
|
||||
List<TrayMenuItem> menu = new ArrayList<>();
|
||||
|
||||
MenuItem showMainWindowItem = new MenuItem(resourceBundle.getString("traymenu.showMainWindow"));
|
||||
showMainWindowItem.addActionListener(this::showMainWindow);
|
||||
menu.add(showMainWindowItem);
|
||||
|
||||
MenuItem showPreferencesItem = new MenuItem(resourceBundle.getString("traymenu.showPreferencesWindow"));
|
||||
showPreferencesItem.addActionListener(this::showPreferencesWindow);
|
||||
menu.add(showPreferencesItem);
|
||||
|
||||
menu.addSeparator();
|
||||
for (Vault v : vaults) {
|
||||
MenuItem submenu = buildSubmenu(v);
|
||||
menu.add(submenu);
|
||||
menu.add(new ActionItem(resourceBundle.getString("traymenu.showMainWindow"), this::showMainWindow));
|
||||
menu.add(new ActionItem(resourceBundle.getString("traymenu.showPreferencesWindow"), this::showPreferencesWindow));
|
||||
menu.add(new SeparatorItem());
|
||||
for (Vault vault : vaults) {
|
||||
List<TrayMenuItem> submenu = buildSubmenu(vault);
|
||||
menu.add(new SubMenuItem(vault.getDisplayName(), submenu));
|
||||
}
|
||||
menu.addSeparator();
|
||||
menu.add(new SeparatorItem());
|
||||
menu.add(new ActionItem(resourceBundle.getString("traymenu.lockAllVaults"), this::lockAllVaults));
|
||||
menu.add(new ActionItem(resourceBundle.getString("traymenu.quitApplication"), this::quitApplication));
|
||||
// lockAllItem.setEnabled(!vaults.filtered(Vault::isUnlocked).isEmpty());
|
||||
|
||||
MenuItem lockAllItem = new MenuItem(resourceBundle.getString("traymenu.lockAllVaults"));
|
||||
lockAllItem.addActionListener(this::lockAllVaults);
|
||||
lockAllItem.setEnabled(!vaults.filtered(Vault::isUnlocked).isEmpty());
|
||||
menu.add(lockAllItem);
|
||||
|
||||
MenuItem quitApplicationItem = new MenuItem(resourceBundle.getString("traymenu.quitApplication"));
|
||||
quitApplicationItem.addActionListener(this::quitApplication);
|
||||
menu.add(quitApplicationItem);
|
||||
trayMenu.updateTrayMenu(menu);
|
||||
}
|
||||
|
||||
private Menu buildSubmenu(Vault vault) {
|
||||
Menu submenu = new Menu(vault.getDisplayName());
|
||||
|
||||
private List<TrayMenuItem> buildSubmenu(Vault vault) {
|
||||
if (vault.isLocked()) {
|
||||
MenuItem unlockItem = new MenuItem(resourceBundle.getString("traymenu.vault.unlock"));
|
||||
unlockItem.addActionListener(createActionListenerForVault(vault, this::unlockVault));
|
||||
submenu.add(unlockItem);
|
||||
return List.of(
|
||||
new ActionItem(resourceBundle.getString("traymenu.vault.unlock"), () -> this.unlockVault(vault))
|
||||
);
|
||||
} else if (vault.isUnlocked()) {
|
||||
MenuItem lockItem = new MenuItem(resourceBundle.getString("traymenu.vault.lock"));
|
||||
lockItem.addActionListener(createActionListenerForVault(vault, this::lockVault));
|
||||
submenu.add(lockItem);
|
||||
return List.of(
|
||||
new ActionItem(resourceBundle.getString("traymenu.vault.lock"), () -> this.lockVault(vault)),
|
||||
new ActionItem(resourceBundle.getString("traymenu.vault.reveal"), () -> this.revealVault(vault))
|
||||
|
||||
MenuItem revealItem = new MenuItem(resourceBundle.getString("traymenu.vault.reveal"));
|
||||
revealItem.addActionListener(createActionListenerForVault(vault, this::revealVault));
|
||||
submenu.add(revealItem);
|
||||
);
|
||||
} else {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
return submenu;
|
||||
}
|
||||
|
||||
private ActionListener createActionListenerForVault(Vault vault, Consumer<Vault> consumer) {
|
||||
return actionEvent -> consumer.accept(vault);
|
||||
}
|
||||
/* action listeners: */
|
||||
|
||||
private void quitApplication(EventObject actionEvent) {
|
||||
private void quitApplication() {
|
||||
appLifecycle.quit();
|
||||
}
|
||||
|
||||
@@ -119,7 +126,7 @@ class TrayMenuController {
|
||||
showMainAppAndThen(app -> app.startLockWorkflow(vault, Optional.empty()));
|
||||
}
|
||||
|
||||
private void lockAllVaults(ActionEvent actionEvent) {
|
||||
private void lockAllVaults() {
|
||||
showMainAppAndThen(app -> app.getVaultService().lockAll(vaults.filtered(Vault::isUnlocked), false));
|
||||
}
|
||||
|
||||
@@ -127,11 +134,11 @@ class TrayMenuController {
|
||||
showMainAppAndThen(app -> app.getVaultService().reveal(vault));
|
||||
}
|
||||
|
||||
void showMainWindow(@SuppressWarnings("unused") ActionEvent actionEvent) {
|
||||
showMainAppAndThen(app -> app.showMainWindow());
|
||||
void showMainWindow() {
|
||||
showMainAppAndThen(FxApplication::showMainWindow);
|
||||
}
|
||||
|
||||
private void showPreferencesWindow(@SuppressWarnings("unused") EventObject actionEvent) {
|
||||
private void showPreferencesWindow() {
|
||||
showMainAppAndThen(app -> app.showPreferencesWindow(SelectedPreferencesTab.ANY));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.cryptomator.integrations.tray.TrayMenuController;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Module
|
||||
public class TrayMenuModule {
|
||||
|
||||
@Provides
|
||||
@TrayMenuScoped
|
||||
static Optional<TrayMenuController> provideSupportedKeychainAccessProviders() {
|
||||
return TrayMenuController.get();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user