From 948a62b4829cb5ab374e2cc6ca02d4a959f2401b Mon Sep 17 00:00:00 2001 From: Ralph Plawetzki Date: Sat, 6 May 2023 09:18:47 +0200 Subject: [PATCH] Code improvements continued Discussion: https://github.com/cryptomator/integrations-linux/pull/18 --- pom.xml | 2 +- .../ui/traymenu/AwtTrayMenuController.java | 30 +++++++++----- .../ui/traymenu/TrayMenuBuilder.java | 39 ++++++++++--------- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index ad322fffe..cfda771f3 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ 2.6.2 - 2.0.0-alpha1 + 2.0.0-alpha2 1.2.0 1.2.0 2.0.0-alpha1 diff --git a/src/main/java/org/cryptomator/ui/traymenu/AwtTrayMenuController.java b/src/main/java/org/cryptomator/ui/traymenu/AwtTrayMenuController.java index 46ed63550..51b1dc46e 100644 --- a/src/main/java/org/cryptomator/ui/traymenu/AwtTrayMenuController.java +++ b/src/main/java/org/cryptomator/ui/traymenu/AwtTrayMenuController.java @@ -7,6 +7,7 @@ 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.TrayIconLoader; import org.cryptomator.integrations.tray.TrayMenuController; import org.cryptomator.integrations.tray.TrayMenuException; import org.cryptomator.integrations.tray.TrayMenuItem; @@ -14,6 +15,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.AWTException; +import java.awt.Image; import java.awt.Menu; import java.awt.MenuItem; import java.awt.PopupMenu; @@ -25,6 +27,7 @@ import java.awt.event.MouseEvent; import java.net.URI; import java.util.Base64; import java.util.List; +import java.util.function.Consumer; /** * Responsible to manage the tray icon on macOS and Windows using AWT. @@ -39,6 +42,7 @@ public class AwtTrayMenuController implements TrayMenuController { private static final String DATA_URI_SCHEME = "data:image/png;base64,"; private final PopupMenu menu = new PopupMenu(); private TrayIcon trayIcon; + private Image image; @CheckAvailability public static boolean isAvailable() { @@ -46,8 +50,9 @@ public class AwtTrayMenuController implements TrayMenuController { } @Override - public void showTrayIcon(URI uri, Runnable defaultAction, String tooltip) throws TrayMenuException { - var image = Toolkit.getDefaultToolkit().createImage(getImageBytes(uri)); + public void showTrayIcon(Consumer iconLoader, Runnable defaultAction, String tooltip) throws TrayMenuException { + TrayIconLoader.PngData callback = this::updateTrayIconWithPngData; + iconLoader.accept(callback); trayIcon = new TrayIcon(image, tooltip, menu); trayIcon.setImageAutoSize(true); @@ -63,9 +68,21 @@ public class AwtTrayMenuController implements TrayMenuController { } } + private void showTrayIconWithPngData(byte[] imageData) { + image = Toolkit.getDefaultToolkit().createImage(imageData); + } + @Override - public void updateTrayIcon(URI uri) { - var image = Toolkit.getDefaultToolkit().createImage(getImageBytes(uri)); + public void updateTrayIcon(Consumer iconLoader) { + TrayIconLoader.PngData callback = this::updateTrayIconWithPngData; + iconLoader.accept(callback); + } + + private void updateTrayIconWithPngData(byte[] imageData) { + if (trayIcon == null) { + throw new IllegalStateException("Failed to update the icon as it has not yet been added"); + } + var image = Toolkit.getDefaultToolkit().createImage(imageData); trayIcon.setImage(image); } @@ -104,9 +121,4 @@ public class AwtTrayMenuController implements TrayMenuController { } } } - - private byte[] getImageBytes(URI uri) { - var data = uri.toString().split(DATA_URI_SCHEME)[1]; - return Base64.getDecoder().decode(data); - } } diff --git a/src/main/java/org/cryptomator/ui/traymenu/TrayMenuBuilder.java b/src/main/java/org/cryptomator/ui/traymenu/TrayMenuBuilder.java index 4cbfa3cac..4431c1e07 100644 --- a/src/main/java/org/cryptomator/ui/traymenu/TrayMenuBuilder.java +++ b/src/main/java/org/cryptomator/ui/traymenu/TrayMenuBuilder.java @@ -7,6 +7,7 @@ import org.cryptomator.common.vaults.VaultListManager; import org.cryptomator.integrations.tray.ActionItem; import org.cryptomator.integrations.tray.SeparatorItem; import org.cryptomator.integrations.tray.SubMenuItem; +import org.cryptomator.integrations.tray.TrayIconLoader; import org.cryptomator.integrations.tray.TrayMenuController; import org.cryptomator.integrations.tray.TrayMenuException; import org.cryptomator.integrations.tray.TrayMenuItem; @@ -23,9 +24,7 @@ import javafx.beans.Observable; import javafx.collections.ObservableList; import java.io.IOException; import java.io.UncheckedIOException; -import java.net.URI; import java.util.ArrayList; -import java.util.Base64; import java.util.List; import java.util.Optional; import java.util.ResourceBundle; @@ -38,10 +37,6 @@ public class TrayMenuBuilder { private static final String TRAY_ICON_UNLOCKED_MAC = "/img/tray_icon_unlocked_mac@2x.png"; private static final String TRAY_ICON = "/img/tray_icon.png"; private static final String TRAY_ICON_UNLOCKED = "/img/tray_icon_unlocked.png"; - private static final String TRAY_ICON_SVG = "tray_icon.svg"; - private static final String TRAY_ICON_UNLOCKED_SVG = "tray_icon_unlocked.svg"; - private static final String DATA_URI_SCHEME = "data:image/png;base64,"; - private static final String FILE_URI_SCHEME = "file:///"; private final ResourceBundle resourceBundle; private final VaultService vaultService; @@ -71,7 +66,12 @@ public class TrayMenuBuilder { }); try { - trayMenu.showTrayIcon(getAppropriateTrayIconImage(), this::showMainWindow, "Cryptomator"); + trayMenu.showTrayIcon(loader -> { + switch (loader) { + case TrayIconLoader.PngData l -> l.loadPng(getAppropriateTrayIconImage()); + case TrayIconLoader.FreedesktopIconName l -> l.lookupByName(getAppropriateTrayIconSVG()); + } + }, this::showMainWindow, "Cryptomator"); trayMenu.onBeforeOpenMenu(() -> { for (Vault vault : vaults) { VaultListManager.redetermineVaultState(vault); @@ -90,7 +90,12 @@ public class TrayMenuBuilder { private void vaultListChanged(@SuppressWarnings("unused") Observable observable) { assert Platform.isFxApplicationThread(); - trayMenu.updateTrayIcon(getAppropriateTrayIconImage()); + trayMenu.updateTrayIcon(loader -> { + switch (loader) { + case TrayIconLoader.PngData l -> l.loadPng(getAppropriateTrayIconImage()); + case TrayIconLoader.FreedesktopIconName l -> l.lookupByName(getAppropriateTrayIconSVG()); + } + }); rebuildMenu(); } @@ -161,16 +166,10 @@ public class TrayMenuBuilder { appWindows.showPreferencesWindow(SelectedPreferencesTab.ANY); } - private URI getAppropriateTrayIconImage() { + private byte[] getAppropriateTrayIconImage() { boolean isAnyVaultUnlocked = vaults.stream().anyMatch(Vault::isUnlocked); String resourceName; - - if (SystemUtils.IS_OS_LINUX) { - resourceName = isAnyVaultUnlocked ? TRAY_ICON_UNLOCKED_SVG : TRAY_ICON_SVG; - return URI.create(FILE_URI_SCHEME + resourceName); - } - if (SystemUtils.IS_OS_MAC_OSX) { resourceName = isAnyVaultUnlocked ? TRAY_ICON_UNLOCKED_MAC : TRAY_ICON_MAC; } else { @@ -179,11 +178,15 @@ public class TrayMenuBuilder { try (var image = getClass().getResourceAsStream(resourceName)) { assert image != null; - var imageBytes = image.readAllBytes(); - var data = Base64.getEncoder().encodeToString(imageBytes); - return URI.create(DATA_URI_SCHEME + data); + return image.readAllBytes(); } catch (IOException e) { throw new UncheckedIOException("Failed to load tray icon image: " + resourceName, e); } } + + private String getAppropriateTrayIconSVG() { + boolean isAnyVaultUnlocked = vaults.stream().anyMatch(Vault::isUnlocked); + + return isAnyVaultUnlocked ? "org.cryptomator.Cryptomator-unlocked" : "org.cryptomator.Cryptomator"; + } }