server

Clone or download

Renamed "Close on X" to "Minimize to system tray on close"

Modified Files

package com.stream_pi.server.controller;
package com.stream_pi.server.controller;
import com.stream_pi.action_api.action.ServerConnection;
import com.stream_pi.action_api.action.ServerConnection;
import com.stream_pi.action_api.action.PropertySaver;
import com.stream_pi.action_api.action.PropertySaver;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.server.Main;
import com.stream_pi.server.Main;
import com.stream_pi.server.action.NormalActionPlugins;
import com.stream_pi.server.action.NormalActionPlugins;
import com.stream_pi.server.connection.ClientConnections;
import com.stream_pi.server.connection.ClientConnections;
import com.stream_pi.server.connection.MainServer;
import com.stream_pi.server.connection.MainServer;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.window.Base;
import com.stream_pi.server.window.Base;
import com.stream_pi.server.window.dashboard.DonatePopupContent;
import com.stream_pi.server.window.dashboard.DonatePopupContent;
import com.stream_pi.server.window.firsttimeuse.FirstTimeUse;
import com.stream_pi.server.window.firsttimeuse.FirstTimeUse;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlertListener;
import com.stream_pi.util.alert.StreamPiAlertListener;
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.iohelper.IOHelper;
import com.stream_pi.util.iohelper.IOHelper;
import javafx.animation.Interpolator;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.concurrent.Task;
import javafx.event.EventHandler;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.stage.WindowEvent;
import java.awt.SystemTray;
import java.awt.SystemTray;
import javafx.util.Duration;
import javafx.util.Duration;
import java.awt.Toolkit;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.TrayIcon;
import java.awt.PopupMenu;
import java.awt.PopupMenu;
import java.awt.MenuItem;
import java.awt.MenuItem;
import java.io.File;
import java.io.File;
import java.net.Inet4Address;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Enumeration;
import java.util.Random;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Level;
public class Controller extends Base implements PropertySaver, ServerConnection
public class Controller extends Base implements PropertySaver, ServerConnection
{
{
MainServer mainServer;
MainServer mainServer;
public void setupDashWindow() throws SevereException
public void setupDashWindow() throws SevereException
{
{
try
try
{
{
StringBuilder ips = new StringBuilder();
StringBuilder ips = new StringBuilder();
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
while(e.hasMoreElements())
while(e.hasMoreElements())
{
{
NetworkInterface n = e.nextElement();
NetworkInterface n = e.nextElement();
Enumeration<InetAddress> ee = n.getInetAddresses();
Enumeration<InetAddress> ee = n.getInetAddresses();
while (ee.hasMoreElements())
while (ee.hasMoreElements())
{
{
InetAddress i = ee.nextElement();
InetAddress i = ee.nextElement();
String hostAddress = i.getHostAddress();
String hostAddress = i.getHostAddress();
if(i instanceof Inet4Address)
if(i instanceof Inet4Address)
{
{
ips.append(hostAddress);
ips.append(hostAddress);
if(e.hasMoreElements())
if(e.hasMoreElements())
ips.append(" / ");
ips.append(" / ");
}
}
}
}
}
}
getStage().setTitle("Stream-Pi Server - IP(s): "+ips.toString()+" | Port: "+ Config.getInstance().getPort()); //Sets title
getStage().setTitle("Stream-Pi Server - IP(s): "+ips.toString()+" | Port: "+ Config.getInstance().getPort()); //Sets title
getStage().setOnCloseRequest(this::onCloseRequest);
getStage().setOnCloseRequest(this::onCloseRequest);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new SevereException(e.getMessage());
throw new SevereException(e.getMessage());
}
}
}
}
@Override
@Override
public void init()
public void init()
{
{
try {
try {
initBase();
initBase();
setupDashWindow();
setupDashWindow();
setupSettingsWindowsAnimations();
setupSettingsWindowsAnimations();
NormalActionPlugins.getInstance().setPropertySaver(this);
NormalActionPlugins.getInstance().setPropertySaver(this);
NormalActionPlugins.getInstance().setServerConnection(this);
NormalActionPlugins.getInstance().setServerConnection(this);
getDashboardPane().getPluginsPane().getSettingsButton().setOnAction(event -> {
getDashboardPane().getPluginsPane().getSettingsButton().setOnAction(event -> {
openSettingsTimeLine.play();
openSettingsTimeLine.play();
});
});
getSettingsPane().getCloseButton().setOnAction(event -> {
getSettingsPane().getCloseButton().setOnAction(event -> {
closeSettingsTimeLine.play();
closeSettingsTimeLine.play();
});
});
getSettingsPane().getThemesSettings().setController(this);
getSettingsPane().getThemesSettings().setController(this);
mainServer = new MainServer(this, this);
mainServer = new MainServer(this, this);
if(getConfig().isFirstTimeUse())
if(getConfig().isFirstTimeUse())
{
{
Stage stage = new Stage();
Stage stage = new Stage();
Scene s = new Scene(new FirstTimeUse(this, this), 512, 300);
Scene s = new Scene(new FirstTimeUse(this, this), 512, 300);
stage.setResizable(false);
stage.setResizable(false);
stage.setScene(s);
stage.setScene(s);
stage.setTitle("Stream-Pi Server Setup");
stage.setTitle("Stream-Pi Server Setup");
stage.initModality(Modality.APPLICATION_MODAL);
stage.initModality(Modality.APPLICATION_MODAL);
stage.setOnCloseRequest(event->Platform.exit());
stage.setOnCloseRequest(event->Platform.exit());
stage.show();
stage.show();
}
}
else
else
{
{
if(getConfig().isAllowDonatePopup())
if(getConfig().isAllowDonatePopup())
{
{
if(new Random().nextInt(5) == 3)
if(new Random().nextInt(5) == 3)
new DonatePopupContent(getHostServices(), this).show();
new DonatePopupContent(getHostServices(), this).show();
}
}
othInit();
othInit();
}
}
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
}
}
@Override
@Override
public void othInit()
public void othInit()
{
{
try
try
{
{
if(ServerInfo.getInstance().isStartMinimised() && SystemTray.isSupported())
if(ServerInfo.getInstance().isStartMinimised() && SystemTray.isSupported())
minimiseApp();
minimiseApp();
else
else
getStage().show();
getStage().show();
}
}
catch(MinorException e)
catch(MinorException e)
{
{
handleMinorException(e);
handleMinorException(e);
}
}
new Thread(new Task<Void>() {
new Thread(new Task<Void>() {
@Override
@Override
protected Void call()
protected Void call()
{
{
try
try
{
{
getSettingsPane().getGeneralSettings().loadDataFromConfig();
getSettingsPane().getGeneralSettings().loadDataFromConfig();
//themes
//themes
getSettingsPane().getThemesSettings().setThemes(getThemes());
getSettingsPane().getThemesSettings().setThemes(getThemes());
getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
getSettingsPane().getThemesSettings().loadThemes();
getSettingsPane().getThemesSettings().loadThemes();
//clients
//clients
getSettingsPane().getClientsSettings().loadData();
getSettingsPane().getClientsSettings().loadData();
try
try
{
{
//Plugins
//Plugins
Platform.runLater(()->{
Platform.runLater(()->{
getDashboardPane().getPluginsPane().clearData();
getDashboardPane().getPluginsPane().clearData();
getDashboardPane().getPluginsPane().loadOtherActions();
getDashboardPane().getPluginsPane().loadOtherActions();
});
});
NormalActionPlugins.setPluginsLocation(getConfig().getPluginsPath());
NormalActionPlugins.setPluginsLocation(getConfig().getPluginsPath());
NormalActionPlugins.getInstance().init();
NormalActionPlugins.getInstance().init();
Platform.runLater(()->getDashboardPane().getPluginsPane().loadData());
Platform.runLater(()->getDashboardPane().getPluginsPane().loadData());
getSettingsPane().getPluginsSettings().loadPlugins();
getSettingsPane().getPluginsSettings().loadPlugins();
}
}
catch (MinorException e)
catch (MinorException e)
{
{
getSettingsPane().getPluginsSettings().showPluginInitError();
getSettingsPane().getPluginsSettings().showPluginInitError();
handleMinorException(e);
handleMinorException(e);
}
}
//Server
//Server
mainServer.setPort(getConfig().getPort());
mainServer.setPort(getConfig().getPort());
mainServer.start();
mainServer.start();
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
return null;
return null;
}
}
}).start();
}).start();
}
}
private void setupSettingsWindowsAnimations()
private void setupSettingsWindowsAnimations()
{
{
Node settingsNode = getSettingsPane();
Node settingsNode = getSettingsPane();
Node dashboardNode = getDashboardPane();
Node dashboardNode = getDashboardPane();
openSettingsTimeLine = new Timeline();
openSettingsTimeLine = new Timeline();
openSettingsTimeLine.setCycleCount(1);
openSettingsTimeLine.setCycleCount(1);
openSettingsTimeLine.getKeyFrames().addAll(
openSettingsTimeLine.getKeyFrames().addAll(
new KeyFrame(Duration.millis(0.0D),
new KeyFrame(Duration.millis(0.0D),
new KeyValue(settingsNode.opacityProperty(),
new KeyValue(settingsNode.opacityProperty(),
0.0D, Interpolator.EASE_IN),
0.0D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleXProperty(),
new KeyValue(settingsNode.scaleXProperty(),
1.1D, Interpolator.EASE_IN),
1.1D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleYProperty(),
new KeyValue(settingsNode.scaleYProperty(),
1.1D, Interpolator.EASE_IN),
1.1D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleZProperty(),
new KeyValue(settingsNode.scaleZProperty(),
1.1D, Interpolator.EASE_IN)),
1.1D, Interpolator.EASE_IN)),
new KeyFrame(Duration.millis(90.0D),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(settingsNode.opacityProperty(),
new KeyValue(settingsNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
new KeyValue(settingsNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
new KeyValue(settingsNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
new KeyValue(settingsNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(0.0D),
new KeyFrame(Duration.millis(0.0D),
new KeyValue(dashboardNode.opacityProperty(),
new KeyValue(dashboardNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
new KeyValue(dashboardNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
new KeyValue(dashboardNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
new KeyValue(dashboardNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(dashboardNode.opacityProperty(),
new KeyValue(dashboardNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
0.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
new KeyValue(dashboardNode.scaleXProperty(),
0.9D, Interpolator.LINEAR),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
new KeyValue(dashboardNode.scaleYProperty(),
0.9D, Interpolator.LINEAR),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
new KeyValue(dashboardNode.scaleZProperty(),
0.9D, Interpolator.LINEAR))
0.9D, Interpolator.LINEAR))
);
);
openSettingsTimeLine.setOnFinished(event1 -> {
openSettingsTimeLine.setOnFinished(event1 -> {
settingsNode.toFront();
settingsNode.toFront();
});
});
closeSettingsTimeLine = new Timeline();
closeSettingsTimeLine = new Timeline();
closeSettingsTimeLine.setCycleCount(1);
closeSettingsTimeLine.setCycleCount(1);
closeSettingsTimeLine.getKeyFrames().addAll(
closeSettingsTimeLine.getKeyFrames().addAll(
new KeyFrame(Duration.millis(0.0D),
new KeyFrame(Duration.millis(0.0D),
new KeyValue(settingsNode.opacityProperty(),
new KeyValue(settingsNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
new KeyValue(settingsNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
new KeyValue(settingsNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
new KeyValue(settingsNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(settingsNode.opacityProperty(),
new KeyValue(settingsNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
0.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
new KeyValue(settingsNode.scaleXProperty(),
1.1D, Interpolator.LINEAR),
1.1D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
new KeyValue(settingsNode.scaleYProperty(),
1.1D, Interpolator.LINEAR),
1.1D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
new KeyValue(settingsNode.scaleZProperty(),
1.1D, Interpolator.LINEAR)),
1.1D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(0.0D),
new KeyFrame(Duration.millis(0.0D),
new KeyValue(dashboardNode.opacityProperty(),
new KeyValue(dashboardNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
0.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
new KeyValue(dashboardNode.scaleXProperty(),
0.9D, Interpolator.LINEAR),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
new KeyValue(dashboardNode.scaleYProperty(),
0.9D, Interpolator.LINEAR),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
new KeyValue(dashboardNode.scaleZProperty(),
0.9D, Interpolator.LINEAR)),
0.9D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(dashboardNode.opacityProperty(),
new KeyValue(dashboardNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
new KeyValue(dashboardNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
new KeyValue(dashboardNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
new KeyValue(dashboardNode.scaleZProperty(),
1.0D, Interpolator.LINEAR))
1.0D, Interpolator.LINEAR))
);
);
closeSettingsTimeLine.setOnFinished(event1 -> {
closeSettingsTimeLine.setOnFinished(event1 -> {
dashboardNode.toFront();
dashboardNode.toFront();
new Thread(new Task<Void>() {
new Thread(new Task<Void>() {
@Override
@Override
protected Void call() {
protected Void call() {
try {
try {
getSettingsPane().getClientsSettings().loadData();
getSettingsPane().getClientsSettings().loadData();
getSettingsPane().getGeneralSettings().loadDataFromConfig();
getSettingsPane().getGeneralSettings().loadDataFromConfig();
getSettingsPane().getPluginsSettings().loadPlugins();
getSettingsPane().getPluginsSettings().loadPlugins();
getSettingsPane().getThemesSettings().setThemes(getThemes());
getSettingsPane().getThemesSettings().setThemes(getThemes());
getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
getSettingsPane().getThemesSettings().loadThemes();
getSettingsPane().getThemesSettings().loadThemes();
getSettingsPane().setDefaultTabToGeneral();
getSettingsPane().setDefaultTabToGeneral();
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
catch (MinorException e)
catch (MinorException e)
{
{
handleMinorException(e);
handleMinorException(e);
}
}
return null;
return null;
}
}
}).start();
}).start();
});
});
}
}
private Timeline openSettingsTimeLine;
private Timeline openSettingsTimeLine;
private Timeline closeSettingsTimeLine;
private Timeline closeSettingsTimeLine;
public Controller(){
public Controller(){
mainServer = null;
mainServer = null;
}
}
public void onCloseRequest(WindowEvent event)
public void onCloseRequest(WindowEvent event)
{
{
try
try
{
{
if(!Config.getInstance().getCloseOnX())
if(Config.getInstance().getMinimiseToSystemTrayOnClose() &&
SystemTray.isSupported())
{
{
if(SystemTray.isSupported())
minimiseApp();
{
event.consume();
minimiseApp();
return;
event.consume();
return;
}
}
}
getConfig().setStartupWindowSize(
getConfig().setStartupWindowSize(
getWidth(),
getWidth(),
getHeight()
getHeight()
);
);
getConfig().save();
getConfig().save();
onQuitApp();
onQuitApp();
NormalActionPlugins.getInstance().shutDownActions();
NormalActionPlugins.getInstance().shutDownActions();
Platform.exit();
Platform.exit();
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
catch (MinorException e)
catch (MinorException e)
{
{
handleMinorException(e);
handleMinorException(e);
}
}
finally
finally
{
{
closeLogger();
closeLogger();
}
}
}
}
public void onQuitApp()
public void onQuitApp()
{
{
if(mainServer!=null)
if(mainServer!=null)
mainServer.stopListeningForConnections();
mainServer.stopListeningForConnections();
ClientConnections.getInstance().disconnectAll();
ClientConnections.getInstance().disconnectAll();
getLogger().info("Shutting down ...");
getLogger().info("Shutting down ...");
}
}
public void minimiseApp() throws MinorException
public void minimiseApp() throws MinorException
{
{
try
try
{
{
SystemTray systemTray = SystemTray.getSystemTray();
SystemTray systemTray = SystemTray.getSystemTray();
if(getTrayIcon() == null)
if(getTrayIcon() == null)
initIconTray(systemTray);
initIconTray(systemTray);
systemTray.add(getTrayIcon());
systemTray.add(getTrayIcon());
getStage().hide();
getStage().hide();
getStage().setOnShown(windowEvent -> {
getStage().setOnShown(windowEvent -> {
systemTray.remove(getTrayIcon());
systemTray.remove(getTrayIcon());
});
});
}
}
catch(Exception e)
catch(Exception e)
{
{
throw new MinorException(e.getMessage());
throw new MinorException(e.getMessage());
}
}
}
}
public void initIconTray(SystemTray systemTray)
public void initIconTray(SystemTray systemTray)
{
{
Platform.setImplicitExit(false);
Platform.setImplicitExit(false);
PopupMenu popup = new PopupMenu();
PopupMenu popup = new PopupMenu();
MenuItem showItem = new MenuItem("Show");
MenuItem showItem = new MenuItem("Show");
showItem.addActionListener(l->{
showItem.addActionListener(l->{
Platform.runLater(()->{
Platform.runLater(()->{
getStage().show();
getStage().show();
});
});
});
});
MenuItem exitItem = new MenuItem("Exit");
MenuItem exitItem = new MenuItem("Exit");
exitItem.addActionListener(l->{
exitItem.addActionListener(l->{
systemTray.remove(getTrayIcon());
systemTray.remove(getTrayIcon());
onQuitApp();
onQuitApp();
Platform.exit();
Platform.exit();
});
});
popup.add(showItem);
popup.add(showItem);
popup.addSeparator();
popup.addSeparator();
popup.add(exitItem);
popup.add(exitItem);
TrayIcon trayIcon = new TrayIcon(
TrayIcon trayIcon = new TrayIcon(
Toolkit.getDefaultToolkit().getImage(Main.class.getResource("app_icon.png")),
Toolkit.getDefaultToolkit().getImage(Main.class.getResource("app_icon.png")),
"Stream-Pi Server",
"Stream-Pi Server",
popup
popup
);
);
trayIcon.setImageAutoSize(true);
trayIcon.setImageAutoSize(true);
this.trayIcon = trayIcon;
this.trayIcon = trayIcon;
}
}
private TrayIcon trayIcon = null;
private TrayIcon trayIcon = null;
public TrayIcon getTrayIcon()
public TrayIcon getTrayIcon()
{
{
return trayIcon;
return trayIcon;
}
}
@Override
@Override
public void handleMinorException(MinorException e) {
public void handleMinorException(MinorException e) {
getLogger().log(Level.SEVERE, e.getMessage(), e);
getLogger().log(Level.SEVERE, e.getMessage(), e);
e.printStackTrace();
e.printStackTrace();
Platform.runLater(()->{
Platform.runLater(()->{
new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.WARNING).show();
new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.WARNING).show();
});
});
}
}
@Override
@Override
public void handleSevereException(SevereException e) {
public void handleSevereException(SevereException e) {
getLogger().log(Level.SEVERE, e.getMessage(), e);
getLogger().log(Level.SEVERE, e.getMessage(), e);
e.printStackTrace();
e.printStackTrace();
Platform.runLater(()->{
Platform.runLater(()->{
StreamPiAlert alert = new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.ERROR);
StreamPiAlert alert = new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.ERROR);
alert.setOnClicked(new StreamPiAlertListener()
alert.setOnClicked(new StreamPiAlertListener()
{
{
@Override
@Override
public void onClick(String txt)
public void onClick(String txt)
{
{
onQuitApp();
onQuitApp();
Platform.exit();
Platform.exit();
}
}
});
});
alert.show();
alert.show();
});
});
}
}
@Override
@Override
public synchronized boolean onNormalActionClicked(NormalAction action) {
public synchronized boolean onNormalActionClicked(NormalAction action) {
try{
try{
getLogger().info("action "+action.getID()+" clicked!");
getLogger().info("action "+action.getID()+" clicked!");
action.onActionClicked();
action.onActionClicked();
return true;
return true;
}
}
catch (Exception e)
catch (Exception e)
{
{
//check if its windows UAC related
//check if its windows UAC related
if(e.getMessage().contains("operation requires elevation"))
if(e.getMessage().contains("operation requires elevation"))
{
{
handleMinorException(new MinorException(
handleMinorException(new MinorException(
"Action Execution Failed!",
"Action Execution Failed!",
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"This action requires higher UAC privileges. Re-launch Stream-Pi Server with 'Administrator Privileges' in order to run this command.")
"This action requires higher UAC privileges. Re-launch Stream-Pi Server with 'Administrator Privileges' in order to run this command.")
);
);
}
}
else
else
{
{
handleMinorException(new MinorException(
handleMinorException(new MinorException(
"Action Execution Failed!",
"Action Execution Failed!",
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Check stacktrace/log to know what exactly happened\n\nMessage : \n"+e.getMessage() )
"Check stacktrace/log to know what exactly happened\n\nMessage : \n"+e.getMessage() )
);
);
}
}
return false;
return false;
}
}
}
}
@Override
@Override
public void clearTemp() {
public void clearTemp() {
Platform.runLater(() -> {
Platform.runLater(() -> {
getDashboardPane().getClientDetailsPane().refresh();
getDashboardPane().getClientDetailsPane().refresh();
getDashboardPane().getActionGridPane().clear();
getDashboardPane().getActionGridPane().clear();
getDashboardPane().getActionGridPane().setFreshRender(true);
getDashboardPane().getActionGridPane().setFreshRender(true);
getDashboardPane().getActionDetailsPane().clear();
getDashboardPane().getActionDetailsPane().clear();
getSettingsPane().getClientsSettings().loadData();
getSettingsPane().getClientsSettings().loadData();
});
});
}
}
@Override
@Override
public void saveServerProperties() {
public void saveServerProperties() {
try {
try {
NormalActionPlugins.getInstance().saveServerSettings();
NormalActionPlugins.getInstance().saveServerSettings();
getSettingsPane().getPluginsSettings().loadPlugins();
getSettingsPane().getPluginsSettings().loadPlugins();
} catch (MinorException e) {
} catch (MinorException e) {
e.printStackTrace();
e.printStackTrace();
handleMinorException(e);
handleMinorException(e);
}
}
}
}
@Override
@Override
public com.stream_pi.util.platform.Platform getPlatform() {
public com.stream_pi.util.platform.Platform getPlatform() {
return ServerInfo.getInstance().getPlatformType();
return ServerInfo.getInstance().getPlatformType();
}
}
}
}
/*
/*
Config.java
Config.java
Contributor(s) : Debayan Sutradhar (@rnayabed)
Contributor(s) : Debayan Sutradhar (@rnayabed)
handler for config.xml
handler for config.xml
*/
*/
package com.stream_pi.server.io;
package com.stream_pi.server.io;
import java.io.File;
import java.io.File;
import java.util.logging.Logger;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamResult;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Element;
public class Config
public class Config
{
{
private static Config instance = null;
private static Config instance = null;
private final File configFile;
private final File configFile;
private Document document;
private Document document;
private Config() throws SevereException {
private Config() throws SevereException {
try {
try {
configFile = new File(ServerInfo.getInstance().getPrePath()+"config.xml");
configFile = new File(ServerInfo.getInstance().getPrePath()+"config.xml");
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
document = docBuilder.parse(configFile);
document = docBuilder.parse(configFile);
} catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace();
throw new SevereException("Config", "unable to read config.xml");
throw new SevereException("Config", "unable to read config.xml");
}
}
}
}
public static synchronized Config getInstance() throws SevereException
public static synchronized Config getInstance() throws SevereException
{
{
if(instance == null)
if(instance == null)
instance = new Config();
instance = new Config();
return instance;
return instance;
}
}
Logger logger = Logger.getLogger(Config.class.getName());
Logger logger = Logger.getLogger(Config.class.getName());
public void save() throws SevereException {
public void save() throws SevereException {
try {
try {
logger.info("Saving config ...");
logger.info("Saving config ...");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(configFile);
Result output = new StreamResult(configFile);
Source input = new DOMSource(document);
Source input = new DOMSource(document);
transformer.transform(input, output);
transformer.transform(input, output);
logger.info("... Done!");
logger.info("... Done!");
} catch (Exception e) {
} catch (Exception e) {
throw new SevereException("Config", "unable to save config.xml");
throw new SevereException("Config", "unable to save config.xml");
}
}
}
}
//Getters
//Getters
//comms
//comms
private Element getCommsElement()
private Element getCommsElement()
{
{
return (Element) document.getElementsByTagName("comms").item(0);
return (Element) document.getElementsByTagName("comms").item(0);
}
}
public String getServerName()
public String getServerName()
{
{
return XMLConfigHelper.getStringProperty(getCommsElement(), "name",
return XMLConfigHelper.getStringProperty(getCommsElement(), "name",
getDefaultServerName(), false, true, document, configFile);
getDefaultServerName(), false, true, document, configFile);
}
}
public int getPort()
public int getPort()
{
{
return XMLConfigHelper.getIntProperty(getCommsElement(), "port",
return XMLConfigHelper.getIntProperty(getCommsElement(), "port",
getDefaultPort(), false, true, document, configFile);
getDefaultPort(), false, true, document, configFile);
}
}
//default getters
//default getters
public String getDefaultServerName()
public String getDefaultServerName()
{
{
return "Stream-Pi Server";
return "Stream-Pi Server";
}
}
public int getDefaultPort()
public int getDefaultPort()
{
{
return 2004;
return 2004;
}
}
private Element getServerElement()
private Element getServerElement()
{
{
return (Element) document.getElementsByTagName("server").item(0);
return (Element) document.getElementsByTagName("server").item(0);
}
}
//server
//server
private Element getActionGridElement()
private Element getActionGridElement()
{
{
return (Element) getServerElement().getElementsByTagName("action-grid").item(0);
return (Element) getServerElement().getElementsByTagName("action-grid").item(0);
}
}
public int getActionGridActionGap()
public int getActionGridActionGap()
{
{
return XMLConfigHelper.getIntProperty(getActionGridElement(), "gap",
return XMLConfigHelper.getIntProperty(getActionGridElement(), "gap",
getDefaultActionGridActionGap(), false, true, document, configFile);
getDefaultActionGridActionGap(), false, true, document, configFile);
}
}
public int getActionGridActionSize()
public int getActionGridActionSize()
{
{
return XMLConfigHelper.getIntProperty(getActionGridElement(), "size",
return XMLConfigHelper.getIntProperty(getActionGridElement(), "size",
getDefaultActionGridSize(), false, true, document, configFile);
getDefaultActionGridSize(), false, true, document, configFile);
}
}
public String getCurrentThemeFullName()
public String getCurrentThemeFullName()
{
{
return XMLConfigHelper.getStringProperty(getServerElement(), "current-theme-full-name",
return XMLConfigHelper.getStringProperty(getServerElement(), "current-theme-full-name",
getDefaultCurrentThemeFullName(), false, true, document, configFile);
getDefaultCurrentThemeFullName(), false, true, document, configFile);
}
}
public String getThemesPath()
public String getThemesPath()
{
{
return XMLConfigHelper.getStringProperty(getServerElement(), "themes-path",
return XMLConfigHelper.getStringProperty(getServerElement(), "themes-path",
getDefaultThemesPath(), false, true, document, configFile);
getDefaultThemesPath(), false, true, document, configFile);
}
}
public String getPluginsPath()
public String getPluginsPath()
{
{
return XMLConfigHelper.getStringProperty(getServerElement(), "plugins-path",
return XMLConfigHelper.getStringProperty(getServerElement(), "plugins-path",
getDefaultPluginsPath(), false, true, document, configFile);
getDefaultPluginsPath(), false, true, document, configFile);
}
}
//default getters
//default getters
public String getDefaultCurrentThemeFullName()
public String getDefaultCurrentThemeFullName()
{
{
return "com.stream_pi.defaultlight";
return "com.stream_pi.defaultlight";
}
}
public String getDefaultThemesPath()
public String getDefaultThemesPath()
{
{
return "Themes/";
return "Themes/";
}
}
public String getDefaultPluginsPath()
public String getDefaultPluginsPath()
{
{
return "Plugins/";
return "Plugins/";
}
}
//server > startup-window-size
//server > startup-window-size
private Element getStartupWindowSizeElement()
private Element getStartupWindowSizeElement()
{
{
return (Element) getServerElement().getElementsByTagName("startup-window-size").item(0);
return (Element) getServerElement().getElementsByTagName("startup-window-size").item(0);
}
}
public double getStartupWindowWidth()
public double getStartupWindowWidth()
{
{
return XMLConfigHelper.getDoubleProperty(getStartupWindowSizeElement(), "width",
return XMLConfigHelper.getDoubleProperty(getStartupWindowSizeElement(), "width",
getDefaultStartupWindowWidth(), false, true, document, configFile);
getDefaultStartupWindowWidth(), false, true, document, configFile);
}
}
public double getStartupWindowHeight()
public double getStartupWindowHeight()
{
{
return XMLConfigHelper.getDoubleProperty(getStartupWindowSizeElement(), "height",
return XMLConfigHelper.getDoubleProperty(getStartupWindowSizeElement(), "height",
getDefaultStartupWindowHeight(), false, true, document, configFile);
getDefaultStartupWindowHeight(), false, true, document, configFile);
}
}
//default getters
//default getters
public int getDefaultStartupWindowWidth()
public int getDefaultStartupWindowWidth()
{
{
return 1024;
return 1024;
}
}
public int getDefaultStartupWindowHeight()
public int getDefaultStartupWindowHeight()
{
{
return 768;
return 768;
}
}
//others
//others
private Element getOthersElement()
private Element getOthersElement()
{
{
return (Element) document.getElementsByTagName("others").item(0);
return (Element) document.getElementsByTagName("others").item(0);
}
}
public boolean getStartOnBoot()
public boolean getStartOnBoot()
{
{
return XMLConfigHelper.getBooleanProperty(getOthersElement(), "start-on-boot",
return XMLConfigHelper.getBooleanProperty(getOthersElement(), "start-on-boot",
getDefaultStartOnBoot(), false, true, document, configFile);
getDefaultStartOnBoot(), false, true, document, configFile);
}
}
public boolean getCloseOnX()
public boolean getMinimiseToSystemTrayOnClose()
{
{
return XMLConfigHelper.getBooleanProperty(getOthersElement(), "close-on-x",
return XMLConfigHelper.getBooleanProperty(getOthersElement(), "minimize-to-tray-on-close",
getDefaultCloseOnX(), false, true, document, configFile);
getDefaultMinimiseToSystemTrayOnClose(), false, true, document, configFile);
}
}
public boolean isFirstTimeUse()
public boolean isFirstTimeUse()
{
{
return XMLConfigHelper.getBooleanProperty(getOthersElement(), "first-time-use", true, false, true, document, configFile);
return XMLConfigHelper.getBooleanProperty(getOthersElement(), "first-time-use", true, false, true, document, configFile);
}
}
public boolean isAllowDonatePopup()
public boolean isAllowDonatePopup()
{
{
return XMLConfigHelper.getBooleanProperty(getOthersElement(), "allow-donate-popup", true, false, true, document, configFile);
return XMLConfigHelper.getBooleanProperty(getOthersElement(), "allow-donate-popup", true, false, true, document, configFile);
}
}
//default getters
//default getters
public boolean getDefaultStartOnBoot()
public boolean getDefaultStartOnBoot()
{
{
return false;
return false;
}
}
public boolean getDefaultCloseOnX()
public boolean getDefaultMinimiseToSystemTrayOnClose()
{
{
return false;
return true;
}
}
//Setters
//Setters
//comms
//comms
public void setServerName(String name)
public void setServerName(String name)
{
{
getCommsElement().getElementsByTagName("name").item(0).setTextContent(name);
getCommsElement().getElementsByTagName("name").item(0).setTextContent(name);
}
}
public void setServerPort(int port)
public void setServerPort(int port)
{
{
getCommsElement().getElementsByTagName("port").item(0).setTextContent(port+"");
getCommsElement().getElementsByTagName("port").item(0).setTextContent(port+"");
}
}
//server
//server
public int getDefaultActionGridActionGap()
public int getDefaultActionGridActionGap()
{
{
return 5;
return 5;
}
}
public int getDefaultActionGridSize()
public int getDefaultActionGridSize()
{
{
return 100;
return 100;
}
}
public void setActionGridSize(int size)
public void setActionGridSize(int size)
{
{
getActionGridElement().getElementsByTagName("size").item(0).setTextContent(size+"");
getActionGridElement().getElementsByTagName("size").item(0).setTextContent(size+"");
}
}
public void setActionGridGap(int size)
public void setActionGridGap(int size)
{
{
getActionGridElement().getElementsByTagName("gap").item(0).setTextContent(size+"");
getActionGridElement().getElementsByTagName("gap").item(0).setTextContent(size+"");
}
}
public void setPluginsPath(String path)
public void setPluginsPath(String path)
{
{
getServerElement().getElementsByTagName("plugins-path").item(0).setTextContent(path);
getServerElement().getElementsByTagName("plugins-path").item(0).setTextContent(path);
}
}
public void setThemesPath(String path)
public void setThemesPath(String path)
{
{
getServerElement().getElementsByTagName("themes-path").item(0).setTextContent(path);
getServerElement().getElementsByTagName("themes-path").item(0).setTextContent(path);
}
}
public void setCurrentThemeFullName(String themeName)
public void setCurrentThemeFullName(String themeName)
{
{
getServerElement().getElementsByTagName("current-theme-full-name").item(0).setTextContent(themeName);
getServerElement().getElementsByTagName("current-theme-full-name").item(0).setTextContent(themeName);
}
}
//server > startup-window-size
//server > startup-window-size
public void setStartupWindowSize(double width, double height)
public void setStartupWindowSize(double width, double height)
{
{
setStartupWindowWidth(width);
setStartupWindowWidth(width);
setStartupWindowHeight(height);
setStartupWindowHeight(height);
}
}
public void setStartupWindowWidth(double width)
public void setStartupWindowWidth(double width)
{
{
getStartupWindowSizeElement().getElementsByTagName("width").item(0).setTextContent(width+"");
getStartupWindowSizeElement().getElementsByTagName("width").item(0).setTextContent(width+"");
}
}
public void setStartupWindowHeight(double height)
public void setStartupWindowHeight(double height)
{
{
getStartupWindowSizeElement().getElementsByTagName("height").item(0).setTextContent(height+"");
getStartupWindowSizeElement().getElementsByTagName("height").item(0).setTextContent(height+"");
}
}
//others
//others
public void setStartupOnBoot(boolean value)
public void setStartupOnBoot(boolean value)
{
{
getOthersElement().getElementsByTagName("start-on-boot").item(0).setTextContent(value+"");
getOthersElement().getElementsByTagName("start-on-boot").item(0).setTextContent(value+"");
}
}
public void setCloseOnX(boolean value)
public void setMinimiseToSystemTrayOnClose(boolean value)
{
{
getOthersElement().getElementsByTagName("close-on-x").item(0).setTextContent(value+"");
getOthersElement().getElementsByTagName("minimize-to-tray-on-close").item(0).setTextContent(value+"");
}
}
public void setFirstTimeUse(boolean value)
public void setFirstTimeUse(boolean value)
{
{
getOthersElement().getElementsByTagName("first-time-use").item(0).setTextContent(value+"");
getOthersElement().getElementsByTagName("first-time-use").item(0).setTextContent(value+"");
}
}
public void setAllowDonatePopup(boolean value)
public void setAllowDonatePopup(boolean value)
{
{
getOthersElement().getElementsByTagName("allow-donate-popup").item(0).setTextContent(value+"");
getOthersElement().getElementsByTagName("allow-donate-popup").item(0).setTextContent(value+"");
}
}
}
}
package com.stream_pi.server.window.settings;
package com.stream_pi.server.window.settings;
import com.stream_pi.server.connection.ServerListener;
import com.stream_pi.server.connection.ServerListener;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.checkforupdates.CheckForUpdates;
import com.stream_pi.util.checkforupdates.CheckForUpdates;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.platform.PlatformType;
import com.stream_pi.util.platform.PlatformType;
import com.stream_pi.util.startatboot.StartAtBoot;
import com.stream_pi.util.startatboot.StartAtBoot;
import com.stream_pi.util.version.Version;
import com.stream_pi.util.version.Version;
import javafx.application.HostServices;
import javafx.application.HostServices;
import javafx.application.Platform;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.TextField;
import javafx.scene.layout.*;
import javafx.scene.layout.*;
import javafx.stage.DirectoryChooser;
import javafx.stage.DirectoryChooser;
import org.kordamp.ikonli.javafx.FontIcon;
import org.kordamp.ikonli.javafx.FontIcon;
import java.awt.SystemTray;
import java.awt.SystemTray;
import java.io.BufferedReader;
import java.io.BufferedReader;
import java.io.File;
import java.io.File;
import java.io.InputStreamReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URL;
import java.util.logging.Logger;
import java.util.logging.Logger;
public class GeneralSettings extends VBox {
public class GeneralSettings extends VBox {
private final TextField serverNameTextField;
private final TextField serverNameTextField;
private final TextField portTextField;
private final TextField portTextField;
private final TextField pluginsPathTextField;
private final TextField pluginsPathTextField;
private final TextField themesPathTextField;
private final TextField themesPathTextField;
private final TextField actionGridPaneActionBoxSize;
private final TextField actionGridPaneActionBoxSize;
private final TextField actionGridPaneActionBoxGap;
private final TextField actionGridPaneActionBoxGap;
private final ToggleButton startOnBootToggleButton;
private final ToggleButton startOnBootToggleButton;
private final ToggleButton closeOnXToggleButton;
private final ToggleButton minimizeToSystemTrayOnCloseToggleButton;
private final Button saveButton;
private final Button saveButton;
private final Button checkForUpdatesButton;
private final Button checkForUpdatesButton;
private Logger logger;
private Logger logger;
private ExceptionAndAlertHandler exceptionAndAlertHandler;
private ExceptionAndAlertHandler exceptionAndAlertHandler;
private ServerListener serverListener;
private ServerListener serverListener;
private HostServices hostServices;
private HostServices hostServices;
public GeneralSettings(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener, HostServices hostServices)
public GeneralSettings(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener, HostServices hostServices)
{
{
this.hostServices = hostServices;
this.hostServices = hostServices;
this.exceptionAndAlertHandler = exceptionAndAlertHandler;
this.exceptionAndAlertHandler = exceptionAndAlertHandler;
this.serverListener = serverListener;
this.serverListener = serverListener;
logger = Logger.getLogger(GeneralSettings.class.getName());
logger = Logger.getLogger(GeneralSettings.class.getName());
serverNameTextField = new TextField();
serverNameTextField = new TextField();
portTextField = new TextField();
portTextField = new TextField();
pluginsPathTextField = new TextField();
pluginsPathTextField = new TextField();
themesPathTextField = new TextField();
themesPathTextField = new TextField();
actionGridPaneActionBoxSize = new TextField();
actionGridPaneActionBoxSize = new TextField();
actionGridPaneActionBoxGap = new TextField();
actionGridPaneActionBoxGap = new TextField();
startOnBootToggleButton = new ToggleButton("Start on Boot");
startOnBootToggleButton = new ToggleButton("Start on Boot");
closeOnXToggleButton = new ToggleButton("Quit On window Close");
minimizeToSystemTrayOnCloseToggleButton = new ToggleButton("Minimise To Tray On Close");
checkForUpdatesButton = new Button("Check for updates");
checkForUpdatesButton = new Button("Check for updates");
checkForUpdatesButton.setOnAction(event->checkForUpdates());
checkForUpdatesButton.setOnAction(event->checkForUpdates());
getStyleClass().add("general_settings");
getStyleClass().add("general_settings");
prefWidthProperty().bind(widthProperty());
prefWidthProperty().bind(widthProperty());
setAlignment(Pos.CENTER);
setAlignment(Pos.CENTER);
setSpacing(5);
setSpacing(5);
getChildren().addAll(
getChildren().addAll(
getUIInputBox("Server Name", serverNameTextField),
getUIInputBox("Server Name", serverNameTextField),
getUIInputBox("Port", portTextField),
getUIInputBox("Port", portTextField),
getUIInputBox("Grid Pane - Box Size", actionGridPaneActionBoxSize),
getUIInputBox("Grid Pane - Box Size", actionGridPaneActionBoxSize),
getUIInputBox("Grid Pane - Box Gap", actionGridPaneActionBoxGap),
getUIInputBox("Grid Pane - Box Gap", actionGridPaneActionBoxGap),
getUIInputBoxWithDirectoryChooser("Plugins Path", pluginsPathTextField),
getUIInputBoxWithDirectoryChooser("Plugins Path", pluginsPathTextField),
getUIInputBoxWithDirectoryChooser("Themes Path", themesPathTextField)
getUIInputBoxWithDirectoryChooser("Themes Path", themesPathTextField)
);
);
serverNameTextField.setPrefWidth(200);
serverNameTextField.setPrefWidth(200);
HBox toggleButtons = new HBox(closeOnXToggleButton, startOnBootToggleButton);
HBox toggleButtons = new HBox(minimizeToSystemTrayOnCloseToggleButton, startOnBootToggleButton);
toggleButtons.setSpacing(10.0);
toggleButtons.setSpacing(10.0);
VBox.setMargin(toggleButtons, new Insets(30, 0 , 0,0));
VBox.setMargin(toggleButtons, new Insets(30, 0 , 0,0));
toggleButtons.setAlignment(Pos.CENTER);
toggleButtons.setAlignment(Pos.CENTER);
saveButton = new Button("Save");
saveButton = new Button("Save");
saveButton.setOnAction(event->save());
saveButton.setOnAction(event->save());
getChildren().addAll(toggleButtons, checkForUpdatesButton, saveButton);
getChildren().addAll(toggleButtons, checkForUpdatesButton, saveButton);
setPadding(new Insets(10));
setPadding(new Insets(10));
}
}
private void checkForUpdates()
private void checkForUpdates()
{
{
new CheckForUpdates(checkForUpdatesButton, hostServices,
new CheckForUpdates(checkForUpdatesButton, hostServices,
PlatformType.SERVER, ServerInfo.getInstance().getVersion());
PlatformType.SERVER, ServerInfo.getInstance().getVersion());
}
}
private HBox getUIInputBoxWithDirectoryChooser(String labelText, TextField textField)
private HBox getUIInputBoxWithDirectoryChooser(String labelText, TextField textField)
{
{
HBox hBox = getUIInputBox(labelText, textField);
HBox hBox = getUIInputBox(labelText, textField);
hBox.setSpacing(5.0);
hBox.setSpacing(5.0);
TextField tf = (TextField) hBox.getChildren().get(2);
TextField tf = (TextField) hBox.getChildren().get(2);
tf.setPrefWidth(300);
tf.setPrefWidth(300);
tf.setDisable(true);
tf.setDisable(true);
Button button = new Button();
Button button = new Button();
FontIcon fontIcon = new FontIcon("far-folder");
FontIcon fontIcon = new FontIcon("far-folder");
button.setGraphic(fontIcon);
button.setGraphic(fontIcon);
button.setOnAction(event -> {
button.setOnAction(event -> {
DirectoryChooser directoryChooser = new DirectoryChooser();
DirectoryChooser directoryChooser = new DirectoryChooser();
try {
try {
File selectedDirectory = directoryChooser.showDialog(getScene().getWindow());
File selectedDirectory = directoryChooser.showDialog(getScene().getWindow());
textField.setText(selectedDirectory.getAbsolutePath());
textField.setText(selectedDirectory.getAbsolutePath());
}
}
catch (NullPointerException e)
catch (NullPointerException e)
{
{
logger.info("No folder selected");
logger.info("No folder selected");
}
}
});
});
hBox.getChildren().add(button);
hBox.getChildren().add(button);
return hBox;
return hBox;
}
}
private HBox getUIInputBox(String labelText, TextField textField)
private HBox getUIInputBox(String labelText, TextField textField)
{
{
textField.setPrefWidth(100);
textField.setPrefWidth(100);
Label label = new Label(labelText);
Label label = new Label(labelText);
Region region = new Region();
Region region = new Region();
HBox.setHgrow(region, Priority.ALWAYS);
HBox.setHgrow(region, Priority.ALWAYS);
return new HBox(label, region, textField);
return new HBox(label, region, textField);
}
}
public void loadDataFromConfig() throws SevereException {
public void loadDataFromConfig() throws SevereException {
Config config = Config.getInstance();
Config config = Config.getInstance();
Platform.runLater(()->
Platform.runLater(()->
{
{
serverNameTextField.setText(config.getServerName());
serverNameTextField.setText(config.getServerName());
portTextField.setText(config.getPort()+"");
portTextField.setText(config.getPort()+"");
pluginsPathTextField.setText(config.getPluginsPath());
pluginsPathTextField.setText(config.getPluginsPath());
themesPathTextField.setText(config.getThemesPath());
themesPathTextField.setText(config.getThemesPath());
actionGridPaneActionBoxSize.setText(config.getActionGridActionSize()+"");
actionGridPaneActionBoxSize.setText(config.getActionGridActionSize()+"");
actionGridPaneActionBoxGap.setText(config.getActionGridActionGap()+"");
actionGridPaneActionBoxGap.setText(config.getActionGridActionGap()+"");
closeOnXToggleButton.setSelected(config.getCloseOnX());
minimizeToSystemTrayOnCloseToggleButton.setSelected(config.getMinimiseToSystemTrayOnClose());
startOnBootToggleButton.setSelected(config.getStartOnBoot());
startOnBootToggleButton.setSelected(config.getStartOnBoot());
});
});
}
}
public void save()
public void save()
{
{
new Thread(new Task<Void>() {
new Thread(new Task<Void>() {
@Override
@Override
protected Void call()
protected Void call()
{
{
try {
try {
boolean toBeReloaded = false;
boolean toBeReloaded = false;
boolean dashToBeReRendered = false;
boolean dashToBeReRendered = false;
Platform.runLater(()->{
Platform.runLater(()->{
saveButton.setDisable(true);
saveButton.setDisable(true);
serverNameTextField.setDisable(true);
serverNameTextField.setDisable(true);
portTextField.setDisable(true);
portTextField.setDisable(true);
closeOnXToggleButton.setDisable(true);
minimizeToSystemTrayOnCloseToggleButton.setDisable(true);
startOnBootToggleButton.setDisable(true);
startOnBootToggleButton.setDisable(true);
});
});
String serverNameStr = serverNameTextField.getText();
String serverNameStr = serverNameTextField.getText();
String serverPortStr = portTextField.getText();
String serverPortStr = portTextField.getText();
String pluginsPathStr = pluginsPathTextField.getText();
String pluginsPathStr = pluginsPathTextField.getText();
String themesPathStr = themesPathTextField.getText();
String themesPathStr = themesPathTextField.getText();
String actionGridActionBoxSize = actionGridPaneActionBoxSize.getText();
String actionGridActionBoxSize = actionGridPaneActionBoxSize.getText();
String actionGridActionBoxGap = actionGridPaneActionBoxGap.getText();
String actionGridActionBoxGap = actionGridPaneActionBoxGap.getText();
boolean closeOnX = closeOnXToggleButton.isSelected();
boolean minimizeToSystemTrayOnClose = minimizeToSystemTrayOnCloseToggleButton.isSelected();
boolean startOnBoot = startOnBootToggleButton.isSelected();
boolean startOnBoot = startOnBootToggleButton.isSelected();
Config config = Config.getInstance();
Config config = Config.getInstance();
StringBuilder errors = new StringBuilder();
StringBuilder errors = new StringBuilder();
if(serverNameStr.isBlank())
if(serverNameStr.isBlank())
{
{
errors.append("* Server Name cannot be blank.\n");
errors.append("* Server Name cannot be blank.\n");
}
}
else
else
{
{
if(!config.getServerName().equals(serverNameStr))
if(!config.getServerName().equals(serverNameStr))
{
{
toBeReloaded = true;
toBeReloaded = true;
}
}
}
}
int serverPort=-1;
int serverPort=-1;
try {
try {
serverPort = Integer.parseInt(serverPortStr);
serverPort = Integer.parseInt(serverPortStr);
if (serverPort < 1024)
if (serverPort < 1024)
errors.append("* Server Port must be more than 1024");
errors.append("* Server Port must be more than 1024");
if(config.getPort()!=serverPort)
if(config.getPort()!=serverPort)
{
{
toBeReloaded = true;
toBeReloaded = true;
}
}
}
}
catch (NumberFormatException e)
catch (NumberFormatException e)
{
{
errors.append("* Server Port must be integer.\n");
errors.append("* Server Port must be integer.\n");
}
}
int actionSize=-1;
int actionSize=-1;
try {
try {
actionSize = Integer.parseInt(actionGridActionBoxSize);
actionSize = Integer.parseInt(actionGridActionBoxSize);
if(config.getActionGridActionSize() != actionSize)
if(config.getActionGridActionSize() != actionSize)
{
{
dashToBeReRendered = true;
dashToBeReRendered = true;
}
}
}
}
catch (NumberFormatException e)
catch (NumberFormatException e)
{
{
errors.append("* action Size must be integer.\n");
errors.append("* action Size must be integer.\n");
}
}
int actionGap=-1;
int actionGap=-1;
try {
try {
actionGap = Integer.parseInt(actionGridActionBoxGap);
actionGap = Integer.parseInt(actionGridActionBoxGap);
if(config.getActionGridActionGap() != actionGap)
if(config.getActionGridActionGap() != actionGap)
{
{
dashToBeReRendered = true;
dashToBeReRendered = true;
}
}
}
}
catch (NumberFormatException e)
catch (NumberFormatException e)
{
{
errors.append("* action Gap must be integer.\n");
errors.append("* action Gap must be integer.\n");
}
}
if(pluginsPathStr.isBlank())
if(pluginsPathStr.isBlank())
{
{
errors.append("* Plugins Path must not be blank.\n");
errors.append("* Plugins Path must not be blank.\n");
}
}
else
else
{
{
if(!config.getPluginsPath().equals(pluginsPathStr))
if(!config.getPluginsPath().equals(pluginsPathStr))
{
{
toBeReloaded = true;
toBeReloaded = true;
}
}
}
}
if(themesPathStr.isBlank())
if(themesPathStr.isBlank())
{
{
errors.append("* Themes Path must not be blank.\n");
errors.append("* Themes Path must not be blank.\n");
}
}
else
else
{
{
if(!config.getThemesPath().equals(themesPathStr))
if(!config.getThemesPath().equals(themesPathStr))
{
{
toBeReloaded = true;
toBeReloaded = true;
}
}
}
}
if(!errors.toString().isEmpty())
if(!errors.toString().isEmpty())
{
{
throw new MinorException("settings", "Please rectify the following errors and try again :\n"+errors.toString());
throw new MinorException("settings", "Please rectify the following errors and try again :\n"+errors.toString());
}
}
if(config.getStartOnBoot() != startOnBoot)
if(config.getStartOnBoot() != startOnBoot)
{
{
if(ServerInfo.getInstance().getRunnerFileName() == null)
if(ServerInfo.getInstance().getRunnerFileName() == null)
{
{
new StreamPiAlert("Uh Oh", "No Runner File Name Specified as startup arguments. Cant set run at boot.", StreamPiAlertType.ERROR).show();
new StreamPiAlert("Uh Oh", "No Runner File Name Specified as startup arguments. Cant set run at boot.", StreamPiAlertType.ERROR).show();
startOnBoot = false;
startOnBoot = false;
}
}
else
else
{
{
StartAtBoot startAtBoot = new StartAtBoot(PlatformType.SERVER, ServerInfo.getInstance().getPlatformType());
StartAtBoot startAtBoot = new StartAtBoot(PlatformType.SERVER, ServerInfo.getInstance().getPlatformType());
if(startOnBoot)
if(startOnBoot)
{
{
startAtBoot.create(new File(ServerInfo.getInstance().getRunnerFileName()));
startAtBoot.create(new File(ServerInfo.getInstance().getRunnerFileName()));
}
}
else
else
{
{
boolean result = startAtBoot.delete();
boolean result = startAtBoot.delete();
if(!result)
if(!result)
new StreamPiAlert("Uh Oh!", "Unable to delete starter file", StreamPiAlertType.ERROR).show();
new StreamPiAlert("Uh Oh!", "Unable to delete starter file", StreamPiAlertType.ERROR).show();
}
}
}
}
}
}
if(!closeOnX)
if(!minimizeToSystemTrayOnClose)
{
{
if(!SystemTray.isSupported())
if(!SystemTray.isSupported())
{
{
StreamPiAlert alert = new StreamPiAlert("Not Supported", "Tray System not supported on this platform ", StreamPiAlertType.ERROR);
StreamPiAlert alert = new StreamPiAlert("Not Supported", "Tray System not supported on this platform ", StreamPiAlertType.ERROR);
alert.show();
alert.show();
closeOnX = true;
minimizeToSystemTrayOnClose = true;
}
}
}
}
config.setServerName(serverNameStr);
config.setServerName(serverNameStr);
config.setServerPort(serverPort);
config.setServerPort(serverPort);
config.setActionGridGap(actionGap);
config.setActionGridGap(actionGap);
config.setActionGridSize(actionSize);
config.setActionGridSize(actionSize);
config.setPluginsPath(pluginsPathStr);
config.setPluginsPath(pluginsPathStr);
config.setThemesPath(themesPathStr);
config.setThemesPath(themesPathStr);
config.setCloseOnX(closeOnX);
config.setMinimiseToSystemTrayOnClose(minimizeToSystemTrayOnClose);
config.setStartupOnBoot(startOnBoot);
config.setStartupOnBoot(startOnBoot);
config.save();
config.save();
loadDataFromConfig();
loadDataFromConfig();
if(toBeReloaded)
if(toBeReloaded)
{
{
new StreamPiAlert("Restart","Restart to see changes", StreamPiAlertType.INFORMATION).show();
new StreamPiAlert("Restart","Restart to see changes", StreamPiAlertType.INFORMATION).show();
}
}
if(dashToBeReRendered)
if(dashToBeReRendered)
{
{
serverListener.clearTemp();
serverListener.clearTemp();
}
}
}
}
catch (MinorException e)
catch (MinorException e)
{
{
exceptionAndAlertHandler.handleMinorException(e);
exceptionAndAlertHandler.handleMinorException(e);
}
}
catch (SevereException e)
catch (SevereException e)
{
{
exceptionAndAlertHandler.handleSevereException(e);
exceptionAndAlertHandler.handleSevereException(e);
}
}
finally {
finally {
Platform.runLater(()->{
Platform.runLater(()->{
saveButton.setDisable(false);
saveButton.setDisable(false);
serverNameTextField.setDisable(false);
serverNameTextField.setDisable(false);
portTextField.setDisable(false);
portTextField.setDisable(false);
closeOnXToggleButton.setDisable(false);
minimizeToSystemTrayOnCloseToggleButton.setDisable(false);
startOnBootToggleButton.setDisable(false);
startOnBootToggleButton.setDisable(false);
});
});
}
}
return null;
return null;
}
}
}).start();
}).start();
}
}
}
}
PKϮPR
PKϮPR
config.xmlUT +`+`+`ux uRn +, NGz\Ѱ0 Mԯ}<f0pt>(kftBvu0Rhk`_[]iUWUpˆ1?Eb GU5.
config.xmlUT +`+`+`ux uRn +, NGz\Ѱ0 Mԯ}<f0pt>(kftBvu0Rhk`_[]iUWUpˆ1?Eb GU5.
g}ۦy`4с-XVN@="
g}ۦy`4с-XVN@="
z, c,Lx9)ZqXt^ŒgOa4㏌K-KL$ &I!_ǛSk H:jKS}L\J%*E6/y͟vNx7,Fa`wk#o0ɩFƣO(ZE*š)ANEk '.I #o/PKqTPK霟Q Plugins/UT _w+`w+`ux PK霟Qm Plugins/config.xmlUT _u`w+`ux Q(K-*ϳU23PRHKOKU
z, c,Lx9)ZqXt^ŒgOa4㏌K-KL$ &I!_ǛSk H:jKS}L\J%*E6/y͟vNx7,Fa`wk#o0ɩFƣO(ZE*š)ANEk '.I #o/PKqTPK霟Q Plugins/UT _w+`w+`ux PK霟Qm Plugins/config.xmlUT _u`w+`ux Q(K-*ϳU23PRHKOKU
qӵPR(.IKIKUWIKL/-J,jRPIL1la,.}4ePKTXmPKPR Themes/UT +`+`+`ux PKDR! Themes/com.stream_pi.defaultdark/UT k`+`+`ux PKDR% Themes/com.stream_pi.defaultdark/res/UT 2`w+`w+`ux PKDR . Themes/com.stream_pi.defaultdark/res/style.cssUT 2`7`w+`ux Vێ0}G,*[u/,9BF$r<|eV
qӵPR(.IKIKUWIKL/-J,jRPIL1la,.}4ePKTXmPKPR Themes/UT +`+`+`ux PKDR! Themes/com.stream_pi.defaultdark/UT k`+`+`ux PKDR% Themes/com.stream_pi.defaultdark/res/UT 2`w+`w+`ux PKDR . Themes/com.stream_pi.defaultdark/res/style.cssUT 2`7`w+`ux Vێ0}G,*[u/,9BF$r<|eV
Z` ao~ٿ>'ݏZjnjN9E :j0*wxΩzD,v@/./!,mkkkO" NQEJB)t3( taiN%쒋]Cy{Mi[\Xxgh_76~n>MPelZvp:UHiz8K<i*@6r'\d 6]S M\(aYwZe!^4L԰ᒣANآn:k{.H۬ 9 E Ñ!rz7Ͱ=JpK 6|Et~gXm9K,m~`F:P= F%y)j`1wi4 8߰NXn󙅎EE{3SV^E%w)ta g>Տ L-aVῷ.PKЛE$ PKDR* Themes/com.stream_pi.defaultdark/theme.xmlUT k`+`w+`ux uP MNi ]89>/VZݽ˽cK FpnL; )ÑU|cr&+|a1
Z` ao~ٿ>'ݏZjnjN9E :j0*wxΩzD,v@/./!,mkkkO" NQEJB)t3( taiN%쒋]Cy{Mi[\Xxgh_76~n>MPelZvp:UHiz8K<i*@6r'\d 6]S M\(aYwZe!^4L԰ᒣANآn:k{.H۬ 9 E Ñ!rz7Ͱ=JpK 6|Et~gXm9K,m~`F:P= F%y)j`1wi4 8߰NXn󙅎EE{3SV^E%w)ta g>Տ L-aVῷ.PKЛE$ PKDR* Themes/com.stream_pi.defaultdark/theme.xmlUT k`+`w+`ux uP MNi ]89>/VZݽ˽cK FpnL; )ÑU|cr&+|a1
/U$aaDd]o'Z(5H1MD.&pn ZF#H6)MO2yxtY9F&^Ot]PK}PKDR" Themes/com.stream_pi.defaultlight/UT k`+`+`ux PKDR+ Themes/com.stream_pi.defaultlight/theme.xmlUT k`+`w+`ux uPA0{)L0)ă/@hM{(3kSFIf ]FLη+-Ñ ~k[MV{1Hli0+8~oҭ ȲXZ Ni@rQ]ELz\X-gyDMu ΢WP8ztǖ5,b"+-PK|PK#DR& Themes/com.stream_pi.defaultlight/res/UT ;1`w+`w+`ux PK#DR / Themes/com.stream_pi.defaultlight/res/style.cssUT ;1`7`w+`ux VM G@꭪^{NAK &bmժ}#IxTh@R|jYZ_~AmDm;Yx"AeIaVXpaoG()PQPg?ﺊ/W<-\.( ڞg%N57XcB"WJ6ImC7qkzBU%-xz$_C tS3&ZaxRBi'geJ472,Ǹ0a%I]Hk.H+mN(GLm5p]3LW3bYOlܲ.wOqMj8p/ưi:kG.ZrLlp٘94#>A6ê1R] l,IVbsXYhmnpK
/U$aaDd]o'Z(5H1MD.&pn ZF#H6)MO2yxtY9F&^Ot]PK}PKDR" Themes/com.stream_pi.defaultlight/UT k`+`+`ux PKDR+ Themes/com.stream_pi.defaultlight/theme.xmlUT k`+`w+`ux uPA0{)L0)ă/@hM{(3kSFIf ]FLη+-Ñ ~k[MV{1Hli0+8~oҭ ȲXZ Ni@rQ]ELz\X-gyDMu ΢WP8ztǖ5,b"+-PK|PK#DR& Themes/com.stream_pi.defaultlight/res/UT ;1`w+`w+`ux PK#DR / Themes/com.stream_pi.defaultlight/res/style.cssUT ;1`7`w+`ux VM G@꭪^{NAK &bmժ}#IxTh@R|jYZ_~AmDm;Yx"AeIaVXpaoG()PQPg?ﺊ/W<-\.( ڞg%N57XcB"WJ6ImC7qkzBU%-xz$_C tS3&ZaxRBi'geJ472,Ǹ0a%I]Hk.H+mN(GLm5p]3LW3bYOlܲ.wOqMj8p/ưi:kG.ZrLlp٘94#>A6ê1R] l,IVbsXYhmnpK
&᪂mS^
&᪂mS^
ްNoHBǢ,ܽNˌ{%)Qxewza7.Í T;a]鿷>PKF; PKͺDR) Themes/com.stream_pi.defaulthighcontrast/UT Z4`+`+`ux PKѸDR- Themes/com.stream_pi.defaulthighcontrast/res/UT 0`w+`w+`ux PKѸDR" 6 Themes/com.stream_pi.defaulthighcontrast/res/style.cssUT 0`7`w+`ux UK0 .`ƹB 8BѐIA^ſHYN,D톅N;=B͖L5/ '/^σnDIvv3=&`k6E="%GT];xUP
ްNoHBǢ,ܽNˌ{%)Qxewza7.Í T;a]鿷>PKF; PKͺDR) Themes/com.stream_pi.defaulthighcontrast/UT Z4`+`+`ux PKѸDR- Themes/com.stream_pi.defaulthighcontrast/res/UT 0`w+`w+`ux PKѸDR" 6 Themes/com.stream_pi.defaulthighcontrast/res/style.cssUT 0`7`w+`ux UK0 .`ƹB 8BѐIA^ſHYN,D톅N;=B͖L5/ '/^σnDIvv3=&`k6E="%GT];xUP
RPEHL\{윞2^3NΚt/9A7dnlWF8Xfƞ*5V.aZ",(B2V(tFχy|Qg(QLZAN;+z%*'MHk a*5<w'Z!nO걘k( k~":yڡԏ<ވ"6 \`:lB޼н/އuDLNy-+RMmBq;mM< KlYA\A0`b<RGnl.K#wb?p__]vDaeΙ/C[ ؅hPK" PKͺDR2 Themes/com.stream_pi.defaulthighcontrast/theme.xmlUT Z4`+`w+`ux uP10 ܑC 40 x)n&(qR|w>O]n輶,chJ{֦.Ŋ3V,t;  #x4S+IFm*Pm%u6֐OlwJs)x RD |" >9H}H>(ЋK0:ҟPKGzKPKϮPRqT
RPEHL\{윞2^3NΚt/9A7dnlWF8Xfƞ*5V.aZ",(B2V(tFχy|Qg(QLZAN;+z%*'MHk a*5<w'Z!nO걘k( k~":yڡԏ<ވ"6 \`:lB޼н/އuDLNy-+RMmBq;mM< KlYA\A0`b<RGnl.K#wb?p__]vDaeΙ/C[ ؅hPK" PKͺDR2 Themes/com.stream_pi.defaulthighcontrast/theme.xmlUT Z4`+`w+`ux uP10 ܑC 40 x)n&(qR|w>O]n輶,chJ{֦.Ŋ3V,t;  #x4S+IFm*Pm%u6֐OlwJs)x RD |" >9H}H>(ЋK0:ҟPKGzKPKϮPRqT
config.xmlUT +`+`+`ux PK霟Q APlugins/UT _w+`w+`ux PK霟QTXm Plugins/config.xmlUT _u`w+`ux PKPR AThemes/UT +`+`+`ux PKDR! AThemes/com.stream_pi.defaultdark/UT k`+`+`ux PKDR% ANThemes/com.stream_pi.defaultdark/res/UT 2`w+`w+`ux PKDRЛE$ . Themes/com.stream_pi.defaultdark/res/style.cssUT 2`7`w+`ux PKDR}* QThemes/com.stream_pi.defaultdark/theme.xmlUT k`+`w+`ux PKDR" AThemes/com.stream_pi.defaultlight/UT k`+`+`ux PKDR|+ Themes/com.stream_pi.defaultlight/theme.xmlUT k`+`w+`ux PK#DR& A& Themes/com.stream_pi.defaultlight/res/UT ;1`w+`w+`ux PK#DRF; / Themes/com.stream_pi.defaultlight/res/style.cssUT ;1`7`w+`ux PKͺDR) A& Themes/com.stream_pi.defaulthighcontrast/UT Z4`+`+`ux PKѸDR- A Themes/com.stream_pi.defaulthighcontrast/res/UT 0`w+`w+`ux PKѸDR" 6 Themes/com.stream_pi.defaulthighcontrast/res/style.cssUT 0`7`w+`ux PKͺDRGzK2 jThemes/com.stream_pi.defaulthighcontrast/theme.xmlUT Z4`+`w+`ux PK 
config.xmlUT +`+`+`ux PK霟Q APlugins/UT _w+`w+`ux PK霟QTXm Plugins/config.xmlUT _u`w+`ux PKPR AThemes/UT +`+`+`ux PKDR! AThemes/com.stream_pi.defaultdark/UT k`+`+`ux PKDR% ANThemes/com.stream_pi.defaultdark/res/UT 2`w+`w+`ux PKDRЛE$ . Themes/com.stream_pi.defaultdark/res/style.cssUT 2`7`w+`ux PKDR}* QThemes/com.stream_pi.defaultdark/theme.xmlUT k`+`w+`ux PKDR" AThemes/com.stream_pi.defaultlight/UT k`+`+`ux PKDR|+ Themes/com.stream_pi.defaultlight/theme.xmlUT k`+`w+`ux PK#DR& A& Themes/com.stream_pi.defaultlight/res/UT ;1`w+`w+`ux PK#DRF; / Themes/com.stream_pi.defaultlight/res/style.cssUT ;1`7`w+`ux PKͺDR) A& Themes/com.stream_pi.defaulthighcontrast/UT Z4`+`+`ux PKѸDR- A Themes/com.stream_pi.defaulthighcontrast/res/UT 0`w+`w+`ux PKѸDR" 6 Themes/com.stream_pi.defaulthighcontrast/res/style.cssUT 0`7`w+`ux PKͺDRGzK2 jThemes/com.stream_pi.defaulthighcontrast/theme.xmlUT Z4`+`w+`ux PK