From 9a9fa465cae74d9f0c788cae8445ca6f14201b7a Mon Sep 17 00:00:00 2001 From: keke125 Date: Thu, 25 May 2023 21:38:36 +0800 Subject: [PATCH] bugfix - preserve toggled theme and selected language after page reload, and clear upload list after saving or discarding images. --- .../com/keke125/pixel/views/MainLayout.java | 122 ++++++++++++++++-- .../generateimage/PixelTransformView.java | 17 ++- .../keke125/pixel/views/login/LoginView.java | 27 +++- .../pixel/views/signup/SignupView.java | 45 +++++-- 4 files changed, 185 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/keke125/pixel/views/MainLayout.java b/src/main/java/com/keke125/pixel/views/MainLayout.java index e569a72..aa08640 100644 --- a/src/main/java/com/keke125/pixel/views/MainLayout.java +++ b/src/main/java/com/keke125/pixel/views/MainLayout.java @@ -9,6 +9,7 @@ import com.keke125.pixel.views.generateimage.PixelTransformView; import com.keke125.pixel.views.usermanagement.UserManagementView; import com.keke125.pixel.views.userprofile.UserProfileView; +import com.vaadin.flow.component.AttachEvent; import com.vaadin.flow.component.UI; import com.vaadin.flow.component.applayout.AppLayout; import com.vaadin.flow.component.applayout.DrawerToggle; @@ -31,6 +32,7 @@ import com.vaadin.flow.i18n.LocaleChangeObserver; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.server.StreamResource; +import com.vaadin.flow.server.VaadinService; import com.vaadin.flow.server.auth.AccessAnnotationChecker; import com.vaadin.flow.theme.lumo.Lumo; import com.vaadin.flow.theme.lumo.LumoUtility; @@ -39,6 +41,7 @@ import java.util.Locale; import java.util.Optional; +import jakarta.servlet.http.Cookie; import org.vaadin.lineawesome.LineAwesomeIcon; /** @@ -52,6 +55,7 @@ public class MainLayout extends AppLayout implements LocaleChangeObserver { private final AccessAnnotationChecker accessChecker; private static final Translator translator = new Translator(); + private Button themeButton; private final Select selectLanguage = new Select<>(); // Navigation private AppNavItem galleryViewNav; @@ -86,20 +90,15 @@ private void addHeaderContent() { // check is current language available // if not available, using the first available language if (translator.getProvidedLocales().contains(UI.getCurrent().getLocale())) { - selectLanguage.setValue(UI.getCurrent().getLocale()); + selectLanguage(UI.getCurrent().getLocale()); } else { - selectLanguage.setValue(translator.getProvidedLocales().get(0)); + selectLanguage(translator.getProvidedLocales().get(0)); } - selectLanguage.addValueChangeListener(e -> UI.getCurrent().setLocale(e.getValue())); + // selectLanguage.addValueChangeListener(e -> UI.getCurrent().setLocale(e.getValue())); + selectLanguage.addValueChangeListener(e -> selectLanguage(e.getValue())); // switch between light and dark theme - Button themeButton = new Button(new Icon(VaadinIcon.ADJUST), click -> { - ThemeList themeList = UI.getCurrent().getElement().getThemeList(); - if (themeList.contains(Lumo.DARK)) { - themeList.remove(Lumo.DARK); - } else { - themeList.add(Lumo.DARK); - } - }); + themeButton = new Button(new Icon(VaadinIcon.ADJUST)); + themeButton.addClickListener(e -> toggleTheme()); // set selectLanguage on right selectLanguage.getStyle().set("margin-left", "auto"); selectLanguage.addClassNames(LumoUtility.Margin.MEDIUM); @@ -223,4 +222,105 @@ public void localeChange(LocaleChangeEvent localeChangeEvent) { loginLink.setText(translator.getTranslation("log-in", UI.getCurrent().getLocale())); } + private void setThemeFromCookie() { + ThemeList themeList = UI.getCurrent().getElement().getThemeList(); + if (isLightThemeOn()) { + themeList.remove(Lumo.DARK); + themeList.add(Lumo.LIGHT); + } else { + themeList.remove(Lumo.LIGHT); + themeList.add(Lumo.DARK); + } + } + + private void setLanguageFromCookie() { + UI.getCurrent().setLocale(checkLanguage()); + selectLanguage.setValue(checkLanguage()); + } + + private void toggleTheme() { + boolean saveLightTheme = true; + ThemeList themeList = UI.getCurrent().getElement().getThemeList(); + if (themeList.contains(Lumo.DARK)) { + themeList.remove(Lumo.DARK); + themeList.add(Lumo.LIGHT); + } else { + themeList.remove(Lumo.LIGHT); + themeList.add(Lumo.DARK); + saveLightTheme = false; + } + setLightThemeInCookie(saveLightTheme); + } + + private void selectLanguage(Locale locale) { + setLanguageInCookie(locale); + UI.getCurrent().setLocale(locale); + selectLanguage.setValue(locale); + } + + + private void setLightThemeInCookie(boolean b) { + Cookie myCookie = new Cookie("light-mode", b ? "true" : "false"); + // Make cookie expire in 2 minutes + myCookie.setMaxAge(3600); + myCookie.setPath(VaadinService.getCurrentRequest().getContextPath()); + VaadinService.getCurrentResponse().addCookie(myCookie); + } + + private void setLanguageInCookie(Locale locale) { + String language = locale.getLanguage(); + Cookie myCookie = new Cookie("language", language); + // Make cookie expire in 60 minutes + myCookie.setMaxAge(3600); + myCookie.setPath(VaadinService.getCurrentRequest().getContextPath()); + VaadinService.getCurrentResponse().addCookie(myCookie); + } + + private String getLightModeCookieValue() { + for (Cookie c : VaadinService.getCurrentRequest().getCookies()) { + if ("light-mode".equals(c.getName())) { + return c.getValue(); + } + } + return null; + } + + private String getLanguageCookieValue() { + for (Cookie c : VaadinService.getCurrentRequest().getCookies()) { + if ("language".equals(c.getName())) { + return c.getValue(); + } + } + return null; + } + + private boolean isLightThemeOn() { + String value = getLightModeCookieValue(); + if (value == null) { + setLightThemeInCookie(true); + return true; + } + return "true".equals(value); + } + + private Locale checkLanguage() { + String value = getLanguageCookieValue(); + if (value == null) { + setLanguageInCookie(UI.getCurrent().getLocale()); + return UI.getCurrent().getLocale(); + } + if (value.equals(Translator.LOCALE_ZHT.getLanguage())) { + return Translator.LOCALE_ZHT; + } else { + return translator.getProvidedLocales().get(0); + } + } + + @Override + protected void onAttach(AttachEvent attachEvent) { + setThemeFromCookie(); + setLanguageFromCookie(); + super.onAttach(attachEvent); + } + } diff --git a/src/main/java/com/keke125/pixel/views/generateimage/PixelTransformView.java b/src/main/java/com/keke125/pixel/views/generateimage/PixelTransformView.java index f70a612..e3a97be 100644 --- a/src/main/java/com/keke125/pixel/views/generateimage/PixelTransformView.java +++ b/src/main/java/com/keke125/pixel/views/generateimage/PixelTransformView.java @@ -117,7 +117,6 @@ public PixelTransformView(ImageInfoService imageInfoService, AuthenticatedUser a confirmDialog = new ConfirmDialog(); addClassName("pixel-transform-view"); - //add(createTitle()); add(setParameterTitle); add(createFormLayout()); add(uploadImageTitle); @@ -127,7 +126,18 @@ public PixelTransformView(ImageInfoService imageInfoService, AuthenticatedUser a clearForm(); cancel.addClickListener(e -> { + if (!imageFileMap.isEmpty()) { + for (String s : imageFileMap.keySet()) { + if (imageFileMap.get(s).delete()) { + System.out.printf("Unsaved image %s have been deleted.\n", s); + } else { + System.err.printf("Failed to delete image %s.\n", s); + } + } + imageFileMap.clear(); + } clearForm(); + multiFileUpload.clearFileList(); isSaved = false; } ); @@ -169,6 +179,7 @@ public PixelTransformView(ImageInfoService imageInfoService, AuthenticatedUser a } isSaved = true; clearForm(); + multiFileUpload.clearFileList(); }); } @@ -479,7 +490,8 @@ public void beforeLeave(BeforeLeaveEvent beforeLeaveEvent) { } imageFileMap.clear(); } - UI.getCurrent().getPage().reload(); + clearForm(); + multiFileUpload.clearFileList(); }); confirmDialog.addConfirmListener(e -> { if (!imageFileMap.isEmpty()) { @@ -519,6 +531,7 @@ public void beforeLeave(BeforeLeaveEvent beforeLeaveEvent) { } isSaved = true; clearForm(); + multiFileUpload.clearFileList(); }); confirmDialog.open(); } diff --git a/src/main/java/com/keke125/pixel/views/login/LoginView.java b/src/main/java/com/keke125/pixel/views/login/LoginView.java index 8b961db..11d2a75 100644 --- a/src/main/java/com/keke125/pixel/views/login/LoginView.java +++ b/src/main/java/com/keke125/pixel/views/login/LoginView.java @@ -14,6 +14,9 @@ import com.vaadin.flow.server.VaadinService; import com.vaadin.flow.server.auth.AnonymousAllowed; import com.vaadin.flow.component.UI; +import jakarta.servlet.http.Cookie; + +import java.util.Locale; @AnonymousAllowed @PageTitle("Login") @@ -24,6 +27,7 @@ public class LoginView extends LoginOverlay implements BeforeEnterObserver { private final AuthenticatedUser authenticatedUser; private final LoginI18n.Header headerTC; private final LoginI18n.Header headerEN; + private static final Translator translator = new Translator(); public LoginView(AppConfig appConfig, AuthenticatedUser authenticatedUser) { this.appConfig = appConfig; @@ -66,7 +70,7 @@ public LoginView(AppConfig appConfig, AuthenticatedUser authenticatedUser) { i18nEN.setForm(loginFormEN); // support message i18nEN.setAdditionalInformation(this.appConfig.getLoginInfoEN()); - if (UI.getCurrent().getLocale().equals(Translator.LOCALE_ZHT)) { + if (checkLanguage().equals(Translator.LOCALE_ZHT)) { setI18n(i18nTC); } else { setI18n(i18nEN); @@ -87,4 +91,25 @@ public void beforeEnter(BeforeEnterEvent event) { setError(event.getLocation().getQueryParameters().getParameters().containsKey("error")); } + + private Locale checkLanguage() { + String value = getLanguageCookieValue(); + if (value == null) { + return UI.getCurrent().getLocale(); + } + if (value.equals(Translator.LOCALE_ZHT.getLanguage())) { + return Translator.LOCALE_ZHT; + } else { + return translator.getProvidedLocales().get(0); + } + } + + private String getLanguageCookieValue() { + for (Cookie c : VaadinService.getCurrentRequest().getCookies()) { + if ("language".equals(c.getName())) { + return c.getValue(); + } + } + return null; + } } diff --git a/src/main/java/com/keke125/pixel/views/signup/SignupView.java b/src/main/java/com/keke125/pixel/views/signup/SignupView.java index 9c2fb10..8cd3312 100644 --- a/src/main/java/com/keke125/pixel/views/signup/SignupView.java +++ b/src/main/java/com/keke125/pixel/views/signup/SignupView.java @@ -26,7 +26,9 @@ import com.vaadin.flow.dom.DomEventListener; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; +import com.vaadin.flow.server.VaadinService; import com.vaadin.flow.server.auth.AnonymousAllowed; +import jakarta.servlet.http.Cookie; import org.apache.tika.Tika; import org.springframework.beans.factory.annotation.Autowired; @@ -34,6 +36,7 @@ import java.io.InputStream; import java.util.Arrays; import java.util.HashSet; +import java.util.Locale; import java.util.Set; @AnonymousAllowed @@ -81,28 +84,25 @@ public SignupView(AppConfig appConfig, @Autowired UserService service) { this.maxFileSizeInBytes = this.appConfig.getMaxAvatarSizeInMegaBytes() * 1024 * 1024; this.defaultImageSizeLimit = this.appConfig.getNewSignupImageSizeLimit(); newUser = new User(); - - /* - * Create the components we'll need - */ - - title = new H3(translator.getTranslation("Sign-up", UI.getCurrent().getLocale())); - - usernameField = new TextField(translator.getTranslation("User-name", UI.getCurrent().getLocale())); - nameField = new TextField(translator.getTranslation("Name", UI.getCurrent().getLocale())); - // upload field upload = new Upload(); memoryBuffer = new MemoryBuffer(); // setup upload i18n uploadTCI18N = new UploadTCI18N(); uploadENI18N = new UploadENI18N(); - if (UI.getCurrent().getLocale().equals(Translator.LOCALE_ZHT)) { + // setup language and theme from cookie + if (checkLanguage().equals(Translator.LOCALE_ZHT)) { upload.setI18n(uploadTCI18N); } else { upload.setI18n(uploadENI18N); } - + UI.getCurrent().setLocale(checkLanguage()); + /* + * Create the components we'll need + */ + title = new H3(translator.getTranslation("Sign-up", UI.getCurrent().getLocale())); + usernameField = new TextField(translator.getTranslation("User-name", UI.getCurrent().getLocale())); + nameField = new TextField(translator.getTranslation("Name", UI.getCurrent().getLocale())); // only image file can be uploaded upload.setAcceptedFileTypes("image/*"); upload.setMaxFileSize(maxFileSizeInBytes); @@ -425,4 +425,25 @@ public String convertToPresentation(String fieldValue, ValueContext valueContext return service.getPasswordEncoder().encode(fieldValue); } } + + private Locale checkLanguage() { + String value = getLanguageCookieValue(); + if (value == null) { + return UI.getCurrent().getLocale(); + } + if (value.equals(Translator.LOCALE_ZHT.getLanguage())) { + return Translator.LOCALE_ZHT; + } else { + return translator.getProvidedLocales().get(0); + } + } + + private String getLanguageCookieValue() { + for (Cookie c : VaadinService.getCurrentRequest().getCookies()) { + if ("language".equals(c.getName())) { + return c.getValue(); + } + } + return null; + } } \ No newline at end of file