Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ public class AppShellConfiguratorImpl implements AppShellConfigurator {
}
```

When targeting Vaadin 14-25 or 23-25, the `AppShellConfigurator` approach cannot be used due to framework and library limitations.
To resolve this, you must create a configuration file `src/test/resources/META-INF/dynamic-theme.properties` with the following content:
```properties
theme=LUMO
```

## Code Viewer

Expand Down
49 changes: 46 additions & 3 deletions src/main/java/com/flowingcode/vaadin/addons/demo/DynamicTheme.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
import com.vaadin.flow.server.AppShellSettings;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.server.Version;
import com.vaadin.flow.server.communication.IndexHtmlResponse;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.jsoup.nodes.Element;

/**
* Enumeration representing supported themes for dynamic switching.
Expand Down Expand Up @@ -84,12 +86,12 @@ public static DynamicTheme getCurrent() {
}

/**
* Initializes the theme settings.
* Initializes the theme settings into the provided {@code AppShellSettings}.
* <p>
* This method performs a lazy initialization of the {@link DynamicTheme} within the
* This method performs a lazy initialization of the {@code DynamicTheme} within the
* current {@link VaadinSession}. If no theme is present, it registers this instance
* as the session default. Subsequently, it injects the corresponding CSS stylesheet
* link into the {@link AppShellSettings}.
* link into the document head.
* </p>
*
* @param settings the application shell settings to be modified
Expand All @@ -116,6 +118,47 @@ public void initialize(AppShellSettings settings) {
}
}

/**
* Initializes the theme settings into the provided {@code IndexHtmlResponse}.
* <p>
* This method performs a lazy initialization of the {@code DynamicTheme} within the
* current {@link VaadinSession}. If no theme is present, it registers this instance
* as the session default. Subsequently, it injects the corresponding CSS stylesheet
* link into the document head.
* </p>
*
* @param response the index HTML response to be modified
* @throws UnsupportedOperationException if the runtime Vaadin version is older than 25
*/
public void initialize(IndexHtmlResponse response) {
assertFeatureSupported();

DynamicTheme theme = getCurrent();
if (theme == null) {
theme = this;
VaadinSession.getCurrent().setAttribute(DynamicTheme.class, theme);
}

String href = null;
switch (theme) {
case AURA:
href = "aura/aura.css";
break;
case LUMO:
href = "lumo/lumo.css";
break;
default:
break;
}

if (href != null) {
Element link = response.getDocument().createElement("link");
link.attr("rel", "stylesheet");
link.attr("href", href);
response.getDocument().head().appendChild(link);
}
}

/**
* Prepares the component for dynamic theme switching by preloading stylesheets.
* <p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.flowingcode.vaadin.addons.demo;

import com.vaadin.flow.server.ServiceInitEvent;
import com.vaadin.flow.server.VaadinServiceInitListener;
import com.vaadin.flow.server.communication.IndexHtmlRequestListener;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
* Service initialization listener that automatically applies a dynamic theme.
* <p>
* If the dynamic theme feature is supported, this listener checks for the presence of a
* {@code /META-INF/dynamic-theme.properties} file. If found, it reads the {@code theme} property
* (e.g., {@code theme=LUMO}) and registers an {@link IndexHtmlRequestListener} to initialize the
* theme for all requests.
* </p>
*/
@SuppressWarnings("serial")
public class DynamicThemeInitializer implements VaadinServiceInitListener {

@Override
public void serviceInit(ServiceInitEvent event) {
if (DynamicTheme.isFeatureSupported()) {
try (InputStream in = getClass().getResourceAsStream("/META-INF/dynamic-theme.properties")) {
if (in != null) {
Properties props = new Properties();
props.load(in);
String themeName = props.getProperty("theme");
if (themeName != null) {
DynamicTheme theme = DynamicTheme.valueOf(themeName.trim());
event.addIndexHtmlRequestListener(theme::initialize);
}
}
} catch (IOException e) {
throw new RuntimeException("Error reading dynamic-theme.properties", e);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
com.flowingcode.vaadin.addons.DevSourceRequestHandlerInitializer
com.flowingcode.vaadin.addons.DevSourceRequestHandlerInitializer
com.flowingcode.vaadin.addons.demo.DynamicThemeInitializer