simplify JfxUiAppearanceProvider

and move loading of appearance service into the fx app
This commit is contained in:
Armin Schrenk
2026-02-16 11:55:03 +01:00
parent cf0052b4f5
commit 83ef9d06d9
4 changed files with 34 additions and 88 deletions

View File

@@ -4,7 +4,6 @@ import dagger.Module;
import dagger.Provides;
import org.cryptomator.integrations.autostart.AutoStartProvider;
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.ui.fxapp.FxApplicationComponent;
import javax.inject.Named;
@@ -30,11 +29,6 @@ class CryptomatorModule {
return new ArrayBlockingQueue<>(10);
}
@Provides
@Singleton
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
return UiAppearanceProvider.get();
}
@Provides
@Singleton

View File

@@ -7,6 +7,7 @@ package org.cryptomator.ui.fxapp;
import dagger.Module;
import dagger.Provides;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.ui.decryptname.DecryptNameComponent;
import org.cryptomator.ui.error.ErrorComponent;
import org.cryptomator.ui.eventview.EventViewComponent;
@@ -26,6 +27,7 @@ import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
import javafx.scene.image.Image;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
@Module(subcomponents = {TrayMenuComponent.class, //
DecryptNameComponent.class, //
@@ -41,7 +43,7 @@ import java.io.InputStream;
ShareVaultComponent.class, //
EventViewComponent.class, //
RecoveryKeyComponent.class, //
NotificationComponent.class })
NotificationComponent.class})
abstract class FxApplicationModule {
private static Image createImageFromResource(String resourceName) throws IOException {
@@ -50,6 +52,12 @@ abstract class FxApplicationModule {
}
}
@Provides
@FxApplicationScoped
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
return UiAppearanceProvider.get();
}
@Provides
@FxApplicationScoped
static TrayMenuComponent provideTrayMenuComponent(TrayMenuComponent.Builder builder) {

View File

@@ -37,11 +37,6 @@ public class FxApplicationStyle {
}
public void initialize() {
appearanceProvider.ifPresent(service -> {
if (service instanceof JfxUiAppearanceProvider fxService) {
fxService.initialize(Platform.getPreferences());
}
});
applyTheme(settings.theme.get());
settings.theme.addListener(this::appThemeChanged);
}

View File

@@ -14,7 +14,6 @@ import javafx.application.ColorScheme;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
@DisplayName("JavaFX Color Scheme switcher")
@OperatingSystem(OperatingSystem.Value.LINUX)
@@ -24,97 +23,47 @@ public class JfxUiAppearanceProvider implements UiAppearanceProvider {
private static final Logger LOG = LoggerFactory.getLogger(JfxUiAppearanceProvider.class);
private final AtomicReference<JfxUiAppearanceImpl> realImpl = new AtomicReference<>(null);
public void initialize(Platform.Preferences preferences) {
var isSet = realImpl.compareAndSet(null, new JfxUiAppearanceImpl(preferences));
if (isSet) {
LOG.debug("Initialized {} with JavaFX preferences", JfxUiAppearanceImpl.class);
}
}
private static class JfxUiAppearanceImpl implements UiAppearanceProvider {
private final Platform.Preferences preferences;
private final ConcurrentHashMap<UiAppearanceListener, ChangeListener<ColorScheme>> uiAppearanceListeners = new ConcurrentHashMap<>();
private JfxUiAppearanceImpl(Platform.Preferences preferences) {
this.preferences = preferences;
}
@Override
public Theme getSystemTheme() {
return switch (preferences.getColorScheme()) {
case DARK -> Theme.DARK;
case LIGHT -> Theme.LIGHT;
};
}
@Override
public void adjustToTheme(Theme theme) {
//no-op
}
@Override
public void addListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
var fxChangeListener = (ChangeListener<ColorScheme>) (_, _, newScheme) -> {
var newTheme = switch (newScheme) {
case DARK -> Theme.DARK;
case LIGHT -> Theme.LIGHT;
};
uiAppearanceListener.systemAppearanceChanged(newTheme);
};
LOG.debug("Register listener for OS theme changes");
uiAppearanceListeners.computeIfAbsent(uiAppearanceListener, k -> {
Platform.runLater(() -> preferences.colorSchemeProperty().addListener(fxChangeListener));
return fxChangeListener;
});
}
@Override
public void removeListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
var fxChangeListener = uiAppearanceListeners.remove(uiAppearanceListener);
if (fxChangeListener != null) {
LOG.debug("Removing listener for OS theme changes");
Platform.runLater(() -> preferences.colorSchemeProperty().removeListener(fxChangeListener));
}
}
}
private final ConcurrentHashMap<UiAppearanceListener, ChangeListener<ColorScheme>> uiAppearanceListeners = new ConcurrentHashMap<>();
private final Platform.Preferences preferences = Platform.getPreferences(); //Note: this service impl MUST be loaded in the fx application thread
//just delegate methods
@Override
public Theme getSystemTheme() {
var impl = realImpl.get();
if (impl != null) {
return impl.getSystemTheme();
} else {
return Theme.LIGHT;
}
return switch (preferences.getColorScheme()) {
case DARK -> Theme.DARK;
case LIGHT -> Theme.LIGHT;
};
}
@Override
public void adjustToTheme(Theme theme) {
var impl = realImpl.get();
if (impl != null) {
impl.adjustToTheme(theme);
}
//no-op
}
@Override
public void addListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
var impl = realImpl.get();
if (impl != null) {
impl.addListener(uiAppearanceListener);
}
var fxChangeListener = (ChangeListener<ColorScheme>) (_, _, newScheme) -> {
var newTheme = switch (newScheme) {
case DARK -> Theme.DARK;
case LIGHT -> Theme.LIGHT;
};
uiAppearanceListener.systemAppearanceChanged(newTheme);
};
LOG.debug("Register listener for OS theme changes");
uiAppearanceListeners.computeIfAbsent(uiAppearanceListener, k -> {
Platform.runLater(() -> preferences.colorSchemeProperty().addListener(fxChangeListener));
return fxChangeListener;
});
}
@Override
public void removeListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
var impl = realImpl.get();
if (impl != null) {
impl.removeListener(uiAppearanceListener);
var fxChangeListener = uiAppearanceListeners.remove(uiAppearanceListener);
if (fxChangeListener != null) {
LOG.debug("Removing listener for OS theme changes");
Platform.runLater(() -> preferences.colorSchemeProperty().removeListener(fxChangeListener));
}
}
}