Add "restart required" notification for some settings

This commit is contained in:
0xb00bface 2020-12-07 20:52:12 +01:00
parent 68371876b5
commit 9c440e3750
3 changed files with 104 additions and 13 deletions

View File

@ -48,12 +48,17 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
private Config config; private Config config;
private Settings settings; private Settings settings;
private Preferences prefs;
public CtbrecPreferencesStorage(Config config) { public CtbrecPreferencesStorage(Config config) {
this.config = config; this.config = config;
this.settings = config.getSettings(); this.settings = config.getSettings();
} }
public void setPreferences(Preferences prefs) {
this.prefs = prefs;
}
@Override @Override
public void save(Preferences preferences) throws IOException { public void save(Preferences preferences) throws IOException {
throw new RuntimeException("not implemented"); throw new RuntimeException("not implemented");
@ -103,6 +108,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
prop.addListener((obs, oldV, newV) -> saveValue(() -> { prop.addListener((obs, oldV, newV) -> saveValue(() -> {
Field field = Settings.class.getField(setting.getKey()); Field field = Settings.class.getField(setting.getKey());
field.set(settings, newV); field.set(settings, newV);
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
prefs.getRestartRequiredCallback().run();
}
config.save(); config.save();
})); }));
HBox row = new HBox(); HBox row = new HBox();
@ -143,7 +151,7 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
private int getRangeSliderValue(List<Integer> values, List<Integer> labels, int value) { private int getRangeSliderValue(List<Integer> values, List<Integer> labels, int value) {
for (int i = 0; i < labels.size(); i++) { for (int i = 0; i < labels.size(); i++) {
int label = labels.get(i).intValue(); int label = labels.get(i).intValue();
if(label == value) { if (label == value) {
return values.get(i); return values.get(i);
} }
} }
@ -158,6 +166,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
String oldValue = (String) field.get(settings); String oldValue = (String) field.get(settings);
if (!Objects.equals(path, oldValue)) { if (!Objects.equals(path, oldValue)) {
field.set(settings, path); field.set(settings, path);
if (setting.doesNeedRestart()) {
prefs.getRestartRequiredCallback().run();
}
config.save(); config.save();
} }
})); }));
@ -175,6 +186,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
String oldValue = (String) field.get(settings); String oldValue = (String) field.get(settings);
if (!Objects.equals(path, oldValue)) { if (!Objects.equals(path, oldValue)) {
field.set(settings, path); field.set(settings, path);
if (setting.doesNeedRestart()) {
prefs.getRestartRequiredCallback().run();
}
config.save(); config.save();
} }
})); }));
@ -188,6 +202,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> { ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
Field field = Settings.class.getField(setting.getKey()); Field field = Settings.class.getField(setting.getKey());
field.set(settings, newV); field.set(settings, newV);
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
prefs.getRestartRequiredCallback().run();
}
config.save(); config.save();
})); }));
StringProperty prop = (StringProperty) setting.getProperty(); StringProperty prop = (StringProperty) setting.getProperty();
@ -205,6 +222,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
if (!ctrl.getText().isEmpty()) { if (!ctrl.getText().isEmpty()) {
Field field = Settings.class.getField(setting.getKey()); Field field = Settings.class.getField(setting.getKey());
field.set(settings, Integer.parseInt(ctrl.getText())); field.set(settings, Integer.parseInt(ctrl.getText()));
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
prefs.getRestartRequiredCallback().run();
}
config.save(); config.save();
} }
})); }));
@ -227,6 +247,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
} }
Field field = Settings.class.getField(setting.getKey()); Field field = Settings.class.getField(setting.getKey());
field.set(settings, value); field.set(settings, value);
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
prefs.getRestartRequiredCallback().run();
}
config.save(); config.save();
} }
})); }));
@ -240,6 +263,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
ctrl.selectedProperty().addListener((obs, oldV, newV) -> saveValue(() -> { ctrl.selectedProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
Field field = Settings.class.getField(setting.getKey()); Field field = Settings.class.getField(setting.getKey());
field.set(settings, newV); field.set(settings, newV);
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
prefs.getRestartRequiredCallback().run();
}
config.save(); config.save();
})); }));
BooleanProperty prop = (BooleanProperty) setting.getProperty(); BooleanProperty prop = (BooleanProperty) setting.getProperty();
@ -266,9 +292,12 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
} else { } else {
field.set(settings, newV); field.set(settings, newV);
} }
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
prefs.getRestartRequiredCallback().run();
}
config.save(); config.save();
})); }));
if(setting.getChangeListener() != null) { if (setting.getChangeListener() != null) {
comboBox.valueProperty().addListener((ChangeListener<? super Object>) setting.getChangeListener()); comboBox.valueProperty().addListener((ChangeListener<? super Object>) setting.getChangeListener());
} }
return comboBox; return comboBox;

View File

@ -37,6 +37,9 @@ import ctbrec.ui.settings.api.SimpleRangeProperty;
import ctbrec.ui.settings.api.ValueConverter; import ctbrec.ui.settings.api.ValueConverter;
import ctbrec.ui.sites.ConfigUI; import ctbrec.ui.sites.ConfigUI;
import ctbrec.ui.tabs.TabSelectionListener; import ctbrec.ui.tabs.TabSelectionListener;
import javafx.animation.FadeTransition;
import javafx.animation.PauseTransition;
import javafx.animation.Transition;
import javafx.beans.binding.BooleanExpression; import javafx.beans.binding.BooleanExpression;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleIntegerProperty;
@ -46,13 +49,26 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TextInputDialog; import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority; import javafx.scene.layout.Priority;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.util.Duration;
public class SettingsTab extends Tab implements TabSelectionListener { public class SettingsTab extends Tab implements TabSelectionListener {
@ -109,6 +125,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
private ExclusiveSelectionProperty recordLocal; private ExclusiveSelectionProperty recordLocal;
private SimpleIntegerProperty postProcessingThreads; private SimpleIntegerProperty postProcessingThreads;
private IgnoreList ignoreList; private IgnoreList ignoreList;
private Label restartNotification;
public SettingsTab(List<Site> sites, Recorder recorder) { public SettingsTab(List<Site> sites, Recorder recorder) {
this.sites = sites; this.sites = sites;
@ -171,19 +188,20 @@ public class SettingsTab extends Tab implements TabSelectionListener {
.ifPresent(configPanel -> siteCategories.add(Category.of(site.getName(), configPanel))); .ifPresent(configPanel -> siteCategories.add(Category.of(site.getName(), configPanel)));
} }
Preferences prefs = Preferences.of(new CtbrecPreferencesStorage(config), CtbrecPreferencesStorage storage = new CtbrecPreferencesStorage(config);
Preferences prefs = Preferences.of(storage,
Category.of("General", Category.of("General",
Group.of("General", Group.of("General",
Setting.of("User-Agent", httpUserAgent), Setting.of("User-Agent", httpUserAgent),
Setting.of("User-Agent mobile", httpUserAgentMobile), Setting.of("User-Agent mobile", httpUserAgentMobile),
Setting.of("Update overview interval (seconds)", overviewUpdateIntervalInSecs, "Update the thumbnail overviews every x seconds"), Setting.of("Update overview interval (seconds)", overviewUpdateIntervalInSecs, "Update the thumbnail overviews every x seconds").needsRestart(),
Setting.of("Update thumbnails", updateThumbnails, "The overviews will still be updated, but the thumbnails won't be changed. This is useful for less powerful systems."), Setting.of("Update thumbnails", updateThumbnails, "The overviews will still be updated, but the thumbnails won't be changed. This is useful for less powerful systems."),
Setting.of("Display stream resolution in overview", determineResolution), Setting.of("Display stream resolution in overview", determineResolution),
Setting.of("Manually select stream quality", chooseStreamQuality, "Opens a dialog to select the video resolution before recording"), Setting.of("Manually select stream quality", chooseStreamQuality, "Opens a dialog to select the video resolution before recording"),
Setting.of("Enable live previews (experimental)", livePreviews), Setting.of("Enable live previews (experimental)", livePreviews),
Setting.of("Add models from clipboard", monitorClipboard, "Monitor clipboard for model URLs and automatically add them to the recorder").needsRestart(), Setting.of("Add models from clipboard", monitorClipboard, "Monitor clipboard for model URLs and automatically add them to the recorder").needsRestart(),
Setting.of("Start Tab", startTab), Setting.of("Start Tab", startTab),
Setting.of("Colors (Base / Accent)", new ColorSettingsPane(Config.getInstance())) Setting.of("Colors (Base / Accent)", new ColorSettingsPane(Config.getInstance())).needsRestart()
), ),
Group.of("Player", Group.of("Player",
Setting.of("Player", mediaPlayer), Setting.of("Player", mediaPlayer),
@ -208,7 +226,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
Setting.of("Skip online check for paused models", onlineCheckSkipsPausedModels, "Skip online check for paused models") Setting.of("Skip online check for paused models", onlineCheckSkipsPausedModels, "Skip online check for paused models")
), ),
Group.of("Location", Group.of("Location",
Setting.of("Record Location", recordLocal), Setting.of("Record Location", recordLocal).needsRestart(),
Setting.of("Server", server), Setting.of("Server", server),
Setting.of("Port", port), Setting.of("Port", port),
Setting.of("Path", path, "Leave empty, if you didn't change the servletContext in the server config"), Setting.of("Path", path, "Leave empty, if you didn't change the servletContext in the server config"),
@ -230,15 +248,17 @@ public class SettingsTab extends Tab implements TabSelectionListener {
Category.of("Sites", siteCategories.toArray(new Category[0])), Category.of("Sites", siteCategories.toArray(new Category[0])),
Category.of("Proxy", Category.of("Proxy",
Group.of("Proxy", Group.of("Proxy",
Setting.of("Type", proxyType), Setting.of("Type", proxyType).needsRestart(),
Setting.of("Host", proxyHost), Setting.of("Host", proxyHost).needsRestart(),
Setting.of("Port", proxyPort), Setting.of("Port", proxyPort).needsRestart(),
Setting.of("Username", proxyUser), Setting.of("Username", proxyUser).needsRestart(),
Setting.of("Password", proxyPassword) Setting.of("Password", proxyPassword).needsRestart()
) )
) )
); );
Region preferencesView = prefs.getView(); Region preferencesView = prefs.getView();
prefs.onRestartRequired(this::showRestartRequired);
storage.setPreferences(prefs);
preferencesView.setMinSize(800, 400); preferencesView.setMinSize(800, 400);
preferencesView.setPrefSize(1280, 960); preferencesView.setPrefSize(1280, 960);
ScrollPane scrollPane = new ScrollPane(preferencesView); ScrollPane scrollPane = new ScrollPane(preferencesView);
@ -248,7 +268,20 @@ public class SettingsTab extends Tab implements TabSelectionListener {
GridPane.setFillHeight(scrollPane, true); GridPane.setFillHeight(scrollPane, true);
GridPane.setHgrow(scrollPane, Priority.ALWAYS); GridPane.setHgrow(scrollPane, Priority.ALWAYS);
GridPane.setVgrow(scrollPane, Priority.ALWAYS); GridPane.setVgrow(scrollPane, Priority.ALWAYS);
setContent(container);
StackPane stackPane = new StackPane();
stackPane.getChildren().add(container);
restartNotification = new Label("Restart Required");
restartNotification.setVisible(false);
restartNotification.setOpacity(0);
restartNotification.setStyle("-fx-font-size: 28; -fx-padding: .3em");
restartNotification.setBorder(new Border(new BorderStroke(Color.web(settings.colorAccent), BorderStrokeStyle.SOLID, new CornerRadii(5), new BorderWidths(2))));
restartNotification.setBackground(new Background(new BackgroundFill(Color.web(settings.colorBase), new CornerRadii(5), Insets.EMPTY)));
stackPane.getChildren().add(restartNotification);
StackPane.setAlignment(restartNotification, Pos.TOP_RIGHT);
StackPane.setMargin(restartNotification, new Insets(10, 40, 0, 0));
setContent(stackPane);
prefs.expandTree(); prefs.expandTree();
@ -407,7 +440,26 @@ public class SettingsTab extends Tab implements TabSelectionListener {
} }
void showRestartRequired() { void showRestartRequired() {
// TODO restartLabel.setVisible(true); if (!restartNotification.isVisible()) {
restartNotification.setVisible(true);
Transition fadeIn = changeOpacity(restartNotification, 1);
fadeIn.play();
fadeIn.setOnFinished(e -> {
Transition fadeOut = changeOpacity(restartNotification, 0);
fadeOut.setOnFinished(e2 -> restartNotification.setVisible(false));
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(5));
pauseTransition.setOnFinished(evt -> fadeOut.play());
pauseTransition.play();
});
}
}
private static final Duration ANIMATION_DURATION = new Duration(500);
private Transition changeOpacity(Node node, double opacity) {
FadeTransition transition = new FadeTransition(ANIMATION_DURATION, node);
transition.setFromValue(node.getOpacity());
transition.setToValue(opacity);
return transition;
} }
public static class SplitAfterOption { public static class SplitAfterOption {

View File

@ -35,6 +35,8 @@ public class Preferences {
private PreferencesStorage preferencesStorage; private PreferencesStorage preferencesStorage;
private Runnable restartRequiredCallback = () -> {};
private Preferences(PreferencesStorage preferencesStorage, Category...categories) { private Preferences(PreferencesStorage preferencesStorage, Category...categories) {
this.preferencesStorage = preferencesStorage; this.preferencesStorage = preferencesStorage;
this.categories = categories; this.categories = categories;
@ -248,4 +250,12 @@ public class Preferences {
return result; return result;
} }
} }
public void onRestartRequired(Runnable callback) {
this.restartRequiredCallback = callback;
}
public Runnable getRestartRequiredCallback() {
return restartRequiredCallback;
}
} }