Skip to content

Commit 8d529b7

Browse files
authored
Merge pull request #18 from doubleSlashde/release/v1.0.0
Release/v1.0.0
2 parents 2738f3d + c3bda63 commit 8d529b7

21 files changed

+425
-316
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ Main view (when you hover over the app):\
1717
**You need to close the application manualy before you shutdown your PC. Otherwise the last running project is not saved to database.**
1818

1919
# Install
20-
Download and execute .jar file (see [releases](https://github.com/doubleSlashde/KeepTime/releases)). You should put the .jar in an extra folder as a *logs* and a *db* folder will be created next to it.\
21-
It is recommended to run the application at windows start.
20+
Download and execute .jar file (see [releases](https://github.com/doubleSlashde/KeepTime/releases)). The start may take up to one minute. You should put the .jar in an extra folder as a *logs* and a *db* folder will be created next to it.\
21+
It is recommended to run the application at windows start so you do not forget to track your time. To do this follow these steps:
2222
* Copy the keeptime.bat file from this repo next to the *.jar*. Adapt the path inside the *keeptime.bat* to the name of the *.jar* file (if needed). Try starting the application by executing the *keeptime.bat* file. Close the app
2323
* Open the autostart folder: Press *Windows+R*, execute *shell:startup*
2424
* Create a shortcut to the *.bat* in the autostart folder
2525

2626
**migrate from old version**
2727
If you used this application before with a *config.xml* you can import your old projects in the settings dialog. Place your config.xml next to the jar and press "parse config.xml". Otherwise no steps are needed.
2828
## Requirements
29-
Only works correct for windows currently. Tested on 7 and 10.
29+
* Windows 7 or 10 (Linux is not yet supported)
30+
* Java 8

keeptime.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
start "" "javaw" -Dprism.order=sw -jar keeptime-1.0.0-SNAPSHOT.jar
1+
start "" "javaw" -Dprism.order=sw -jar keeptime-v1.0.0.jar

src/main/java/de/doubleslash/keeptime/DefaultExceptionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*/
1313
public class DefaultExceptionHandler implements UncaughtExceptionHandler {
1414

15-
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
15+
private static final Logger LOG = LoggerFactory.getLogger(DefaultExceptionHandler.class);
1616

1717
@Override
1818
public void uncaughtException(final Thread t, final Throwable e) {

src/main/java/de/doubleslash/keeptime/Main.java

Lines changed: 114 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package de.doubleslash.keeptime;
22

33
import java.io.IOException;
4+
import java.io.PrintWriter;
5+
import java.io.StringWriter;
46
import java.time.LocalDate;
57
import java.util.List;
68
import java.util.Optional;
@@ -27,7 +29,13 @@
2729
import javafx.fxml.FXMLLoader;
2830
import javafx.scene.Parent;
2931
import javafx.scene.Scene;
32+
import javafx.scene.control.Alert;
33+
import javafx.scene.control.Alert.AlertType;
34+
import javafx.scene.control.Label;
35+
import javafx.scene.control.TextArea;
36+
import javafx.scene.layout.GridPane;
3037
import javafx.scene.layout.Pane;
38+
import javafx.scene.layout.Priority;
3139
import javafx.scene.paint.Color;
3240
import javafx.stage.Stage;
3341
import javafx.stage.StageStyle;
@@ -36,9 +44,9 @@
3644
@SpringBootApplication
3745
public class Main extends Application {
3846

39-
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
47+
private static final Logger LOG = LoggerFactory.getLogger(Main.class);
4048

41-
public static final String VERSION = "v0.0.2";
49+
public static final String VERSION = "v1.0.0";
4250

4351
private ConfigurableApplicationContext springContext;
4452

@@ -47,6 +55,10 @@ public class Main extends Application {
4755
private Model model;
4856
private Controller controller;
4957

58+
private ViewController viewController;
59+
60+
private GlobalScreenListener globalScreenListener;
61+
5062
@Override
5163
public void init() throws Exception {
5264
LOG.info("Starting KeepTime {}", VERSION);
@@ -60,36 +72,49 @@ public void init() throws Exception {
6072
}
6173

6274
@Override
63-
public void start(final Stage primaryStage) throws Exception {
75+
public void start(final Stage primaryStage) {
76+
LOG.info("Initialising the UI");
77+
try {
78+
initUI(primaryStage);
79+
LOG.info("UI successfully initialised.");
80+
} catch (final Exception e) {
81+
LOG.error("There was an error while initialising the UI", e);
6482

65-
LOG.debug("Reading configuration");
83+
final Alert alert = new Alert(AlertType.ERROR);
84+
alert.setTitle("Error");
85+
alert.setHeaderText("Could not start application");
86+
alert.setContentText("Please send the error with your logs folder to a developer");
6687

67-
// TODO there should just be one instance of settings in the repo
68-
final List<Settings> settingsList = model.settingsRepository.findAll();
69-
final Settings settings;
70-
if (settingsList.isEmpty()) {
71-
settings = new Settings();
72-
settings.setTaskBarColor(model.taskBarColor.get());
88+
final StringWriter sw = new StringWriter();
89+
final PrintWriter pw = new PrintWriter(sw);
90+
e.printStackTrace(pw);
91+
final String exceptionText = sw.toString();
7392

74-
settings.setDefaultBackgroundColor(model.defaultBackgroundColor.get());
75-
settings.setDefaultFontColor(model.defaultFontColor.get());
93+
final Label label = new Label("The exception stacktrace was:");
7694

77-
settings.setHoverBackgroundColor(model.hoverBackgroundColor.get());
78-
settings.setHoverFontColor(model.hoverFontColor.get());
79-
settings.setUseHotkey(false);
80-
settings.setDisplayProjectsRight(false);
81-
model.settingsRepository.save(settings);
82-
} else {
83-
settings = settingsList.get(0);
95+
final TextArea textArea = new TextArea(exceptionText);
96+
textArea.setEditable(false);
97+
textArea.setWrapText(true);
98+
99+
textArea.setMaxWidth(Double.MAX_VALUE);
100+
textArea.setMaxHeight(Double.MAX_VALUE);
101+
GridPane.setVgrow(textArea, Priority.ALWAYS);
102+
GridPane.setHgrow(textArea, Priority.ALWAYS);
103+
104+
final GridPane expContent = new GridPane();
105+
expContent.setMaxWidth(Double.MAX_VALUE);
106+
expContent.add(label, 0, 0);
107+
expContent.add(textArea, 0, 1);
108+
109+
alert.getDialogPane().setExpandableContent(expContent);
110+
alert.showAndWait();
111+
System.exit(1);
84112
}
113+
}
85114

86-
model.defaultBackgroundColor.set(settings.getDefaultBackgroundColor());
87-
model.defaultFontColor.set(settings.getDefaultFontColor());
88-
model.hoverBackgroundColor.set(settings.getHoverBackgroundColor());
89-
model.hoverFontColor.set(settings.getHoverFontColor());
90-
model.taskBarColor.set(settings.getTaskBarColor());
91-
model.useHotkey.set(settings.isUseHotkey());
92-
model.displayProjectsRight.set(settings.isDisplayProjectsRight());
115+
private void initUI(final Stage primaryStage) throws Exception {
116+
117+
readSettings();
93118

94119
final List<Work> todaysWorkItems = model.workRepository.findByCreationDate(LocalDate.now());
95120
LOG.info("Found {} past work items", todaysWorkItems.size());
@@ -109,51 +134,63 @@ public void start(final Stage primaryStage) throws Exception {
109134
.addAll(model.allProjects.stream().filter(Project::isEnabled).collect(Collectors.toList()));
110135

111136
// set default project
112-
final Optional<Project> findAny = projects.stream().filter(p -> p.isDefault()).findAny();
137+
final Optional<Project> findAny = projects.stream().filter(Project::isDefault).findAny();
113138
if (findAny.isPresent()) {
114139
model.idleProject = findAny.get();
115140
LOG.debug("Using project '{}' as default project.", model.idleProject);
116141
}
117142

118143
primaryStage.setOnHiding((we) -> {
119-
// shutdown();
120144
popupViewStage.close();
121-
globalScreenListener.register(false); // deregister, as this will keep app running
145+
globalScreenListener.shutdown(); // deregister, as this will keep app running
122146
});
123147

124-
Runtime.getRuntime().addShutdownHook(new Thread() {
125-
@Override
126-
public void run() {
127-
// TODO this does not work - spring uses own hooks and may already be shutdown
128-
// shutdown();
129-
}
130-
});
148+
initialiseUI(primaryStage);
149+
initialisePopupUI(primaryStage);
150+
}
131151

132-
try {
133-
initialiseUI(primaryStage);
134-
} catch (final Exception e) {
135-
e.printStackTrace();
136-
}
152+
private void readSettings() {
153+
LOG.debug("Reading configuration");
137154

138-
try {
139-
initialisePopupUI(primaryStage);
140-
} catch (final Exception e) {
141-
e.printStackTrace();
155+
final List<Settings> settingsList = model.settingsRepository.findAll();
156+
final Settings settings;
157+
if (settingsList.isEmpty()) {
158+
settings = new Settings();
159+
settings.setTaskBarColor(model.taskBarColor.get());
160+
161+
settings.setDefaultBackgroundColor(model.defaultBackgroundColor.get());
162+
settings.setDefaultFontColor(model.defaultFontColor.get());
163+
164+
settings.setHoverBackgroundColor(model.hoverBackgroundColor.get());
165+
settings.setHoverFontColor(model.hoverFontColor.get());
166+
settings.setUseHotkey(false);
167+
settings.setDisplayProjectsRight(false);
168+
settings.setHideProjectsOnMouseExit(true);
169+
model.settingsRepository.save(settings);
170+
} else {
171+
settings = settingsList.get(0);
142172
}
143-
}
144173

145-
GlobalScreenListener globalScreenListener;
174+
model.defaultBackgroundColor.set(settings.getDefaultBackgroundColor());
175+
model.defaultFontColor.set(settings.getDefaultFontColor());
176+
model.hoverBackgroundColor.set(settings.getHoverBackgroundColor());
177+
model.hoverFontColor.set(settings.getHoverFontColor());
178+
model.taskBarColor.set(settings.getTaskBarColor());
179+
model.useHotkey.set(settings.isUseHotkey());
180+
model.displayProjectsRight.set(settings.isDisplayProjectsRight());
181+
model.hideProjectsOnMouseExit.set(settings.isHideProjectsOnMouseExit());
182+
}
146183

147184
private void initialisePopupUI(final Stage primaryStage) throws IOException {
148-
// TODO register only if it is enabled
185+
LOG.debug("Initialising popup UI.");
186+
149187
globalScreenListener = new GlobalScreenListener();
150-
// TODO stop and close stage when main stage is shutdown
188+
// stop and close stage when main stage is shutdown
151189
model.useHotkey.addListener((a, b, newValue) -> {
152190
globalScreenListener.register(newValue);
153191
});
154192
globalScreenListener.register(model.useHotkey.get());
155193

156-
// Platform.setImplicitExit(false); // TODO maybe not needed as other view will be available
157194
popupViewStage = new Stage();
158195
popupViewStage.initOwner(primaryStage);
159196
// Load root layout from fxml file.
@@ -172,61 +209,41 @@ private void initialisePopupUI(final Stage primaryStage) throws IOException {
172209
viewControllerPopupController.setStage(popupViewStage, popupScene);
173210
viewControllerPopupController.setController(controller, model);
174211
globalScreenListener.setViewController(viewControllerPopupController);
175-
176212
}
177213

178-
private void shutdown() {
179-
LOG.info("Shutting down");
180-
// viewController.changeProject(model.idleProject, 0); // TODO not so nice (view has the comments for the current
181-
// // job)
182-
controller.shutdown();
183-
}
184-
185-
ViewController viewController;
186-
187-
private void initialiseUI(final Stage primaryStage) {
188-
try {
189-
Pane mainPane;
190-
191-
// Load root layout from fxml file.
192-
final FXMLLoader loader = new FXMLLoader();
193-
loader.setLocation(Resources.getResource(RESOURCE.FXML_VIEW_LAYOUT));
194-
loader.setControllerFactory(springContext::getBean);
195-
mainPane = loader.load();
196-
primaryStage.initStyle(StageStyle.TRANSPARENT);
197-
// Show the scene containing the root layout.
198-
final Scene mainScene = new Scene(mainPane, Color.TRANSPARENT);
199-
200-
// Image(Resources.getResource(RESOURCE.ICON_MAIN).toString()));
214+
private void initialiseUI(final Stage primaryStage) throws IOException {
215+
LOG.debug("Initialising main UI.");
216+
Pane mainPane;
201217

202-
primaryStage.setTitle("KeepTime");
203-
primaryStage.setScene(mainScene);
204-
primaryStage.setAlwaysOnTop(true);
205-
primaryStage.setResizable(false);
206-
207-
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
208-
@Override
209-
public void handle(final WindowEvent event) {
210-
LOG.info("On close request");
211-
// shutdown();
212-
// Platform.exit();
213-
}
214-
});
218+
// Load root layout from fxml file.
219+
final FXMLLoader loader = new FXMLLoader();
220+
loader.setLocation(Resources.getResource(RESOURCE.FXML_VIEW_LAYOUT));
221+
loader.setControllerFactory(springContext::getBean);
222+
mainPane = loader.load();
223+
primaryStage.initStyle(StageStyle.TRANSPARENT);
224+
// Show the scene containing the root layout.
225+
final Scene mainScene = new Scene(mainPane, Color.TRANSPARENT);
215226

216-
viewController = loader.getController();
217-
// Give the controller access to the main app.
218-
viewController.setStage(primaryStage);
227+
// Image(Resources.getResource(RESOURCE.ICON_MAIN).toString())); // TODO use an app icon
219228

220-
// controller = springContext.getBean(Controller.class, model, new RealDateProvider());
229+
primaryStage.setTitle("KeepTime");
230+
primaryStage.setScene(mainScene);
231+
primaryStage.setAlwaysOnTop(true);
232+
primaryStage.setResizable(false);
221233

222-
viewController.setController(controller, model);
234+
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
235+
@Override
236+
public void handle(final WindowEvent event) {
237+
LOG.info("On close request");
238+
}
239+
});
223240

224-
primaryStage.show();
241+
viewController = loader.getController();
242+
// Give the controller access to the main app.
243+
viewController.setStage(primaryStage);
244+
viewController.setController(controller, model);
225245

226-
} catch (final Exception e) {
227-
LOG.error("Error: " + e.toString(), e);
228-
e.printStackTrace();
229-
}
246+
primaryStage.show();
230247
}
231248

232249
@Override

src/main/java/de/doubleslash/keeptime/common/ColorHelper.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
public class ColorHelper {
66

7+
private ColorHelper() {
8+
throw new IllegalStateException("Utility class");
9+
}
10+
711
public static Color randomColor() {
812
return Color.BLACK;
913
}

src/main/java/de/doubleslash/keeptime/common/ConfigParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import javafx.scene.paint.Color;
1818

1919
public class ConfigParser {
20-
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
20+
private static final Logger LOG = LoggerFactory.getLogger(ConfigParser.class);
2121

2222
private final Controller controller;
2323

src/main/java/de/doubleslash/keeptime/common/DateFormatter.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,22 @@ public class DateFormatter {
99
private static DateTimeFormatter dayDateFormatter = DateTimeFormatter.ofPattern("eeee dd.MM.yyyy");
1010
private static DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
1111

12+
private DateFormatter() {
13+
throw new IllegalStateException("Utility class");
14+
}
15+
1216
public static String secondsToHHMMSS(final long currentWorkSeconds) {
1317
final int hours = (int) (currentWorkSeconds / 3600);
1418
final int minutes = (int) ((currentWorkSeconds % 3600) / 60);
1519

1620
final int sec = (int) (((currentWorkSeconds % 3600) % 60));
1721

18-
final String a = (hours > 9 ? hours : "0" + hours) + ":" + (minutes > 9 ? minutes : "0" + minutes) + ":"
19-
+ (sec > 9 ? sec : "0" + sec);
20-
return a;
22+
final Object hoursString = hours > 9 ? hours : "0" + hours;
23+
final Object minutesString = minutes > 9 ? minutes : "0" + minutes;
24+
final Object secondsString = sec > 9 ? sec : "0" + sec;
25+
26+
final String timeString = hoursString + ":" + minutesString + ":" + secondsString;
27+
return timeString;
2128
}
2229

2330
public static long getSecondsBewtween(final LocalDateTime startDate, final LocalDateTime endDate) {

src/main/java/de/doubleslash/keeptime/common/Resources.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
public class Resources {
66

7+
private Resources() {
8+
throw new IllegalStateException("Utility class");
9+
}
10+
711
public enum RESOURCE {
812
/** LAYOUTS **/
913
// main
@@ -30,6 +34,5 @@ public String getResourceLocation() {
3034

3135
public static URL getResource(final RESOURCE resource) {
3236
return Resources.class.getResource(resource.getResourceLocation());
33-
// return ClassLoader.getSystemResource(resource.getResourceLocation());
3437
}
3538
}

0 commit comments

Comments
 (0)