Skip to content

Commit c803f97

Browse files
author
Mikael Turøy
committed
Marker online update
1 parent 9e549d7 commit c803f97

File tree

14 files changed

+12943
-12799
lines changed

14 files changed

+12943
-12799
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@types/react": "^16.9.48",
5050
"@types/react-dom": "^16.9.8",
5151
"class-transformer": "^0.4.0",
52+
"cross-fetch": "^3.1.5",
5253
"electron-updater": "^4.3.9",
5354
"js-yaml": "^3.13.1",
5455
"lodash.isequal": "^4.5.0",

src/components/Configuration.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ class App extends React.Component<IProps, IState> {
4949
</Section>
5050
<Section title="Overlay">
5151
<Checkbox setting={getSetting(this.state.settings, 'Check for new versions', "overlaySettings.checkForUpdates", true)} />
52-
<Checkbox setting={getSetting(this.state.settings, 'Automatically update to new versions', "overlaySettings.autoUpdate", true)}/>
52+
<Checkbox setting={getSetting(this.state.settings, 'Automatically update to new versions', "overlaySettings.autoUpdate", true)} />
53+
<Checkbox setting={getSetting(this.state.settings, 'Automatically update markers to new versions on start', "overlaySettings.checkForMarkerUpdates", true)}/>
5354
</Section>
5455
<Section title="Development" expanded={false}>
5556
<Section title="Dev tools">

src/components/Markers.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class App extends React.Component<IProps, IState>{
2929
}
3030

3131
componentWillUnmount() {
32-
ipcRenderer.removeAllListeners([IPC.Settings.Set]);
32+
ipcRenderer.removeAllListeners(IPC.Settings.Set);
3333
}
3434

3535
settingsListener(event: any, data: ISettings) {

src/components/SearchMarkers.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class App extends React.Component<IProps, IState> {
7171
};
7272
this.settingsListener = this.settingsListener.bind(this);
7373
this.search = this.search.bind(this);
74+
this.handleSelect = this.handleSelect.bind(this);
7475
ipcRenderer.on(IPC.Settings.Set, this.settingsListener);
7576
ipcRenderer.send(IPC.Settings.Get, true);
7677
}

src/components/window/CheckBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function IconCheckbox(props: IProps) {
1919
let icon = props.checked ? checkedIcon : unCheckedIcon;
2020

2121
return (
22-
<span className="button" onClick={() => props.toggleCheck(!props.checked)} title={props.popup}>
22+
<span className="button text-nowrap" onClick={() => props.toggleCheck(!props.checked)} title={props.popup}>
2323
<FontAwesomeIcon icon={icon} className="mr-2" style={{width: "1em"}}/>
2424
{props.name}
2525
{props.children}

src/shared/interfaces/settings/IMarkerGroupSettings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export interface IMarkerGroupSettings {
99
color: string;
1010
description: string;
1111
id: string;
12+
version?: string;
13+
updateurl?: string;
1214
markers: IMarkerMapSettings;
1315
defaultNamePlate: INamePlateSetting;
1416

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export interface IOverlaySettings {
22
checkForUpdates: boolean;
33
autoUpdate: boolean;
4+
checkForMarkerUpdates: boolean;
45
}

src/shared/models/settings/MarkerGroupSettings.ts

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,23 @@ import { IMarkerMapSettings } from "../../interfaces/settings/IMarkerMapSettings
33
import { IMarkerSettings } from "../../interfaces/settings/IMarkerSettings";
44
import { INamePlateSetting } from "../../interfaces/settings/INamePlateSetting";
55
import { NamePlateSetting } from "./NamePlateSetting";
6-
import { Type } from 'class-transformer';
6+
import { Type, deserialize } from 'class-transformer';
7+
import fetch from 'cross-fetch'
78

89
const { v4: uuidv4 } = require('uuid');
910

11+
export interface IUpdateAvailable {
12+
version?: string;
13+
url?: string;
14+
updateAvailable: boolean;
15+
markerid: string;
16+
}
17+
1018
export class MarkerGroupSettings implements IMarkerGroupSettings {
19+
static fromJson(json: string) {
20+
return deserialize(MarkerGroupSettings, json);
21+
}
22+
1123
AddMarker(marker: IMarkerSettings, map: string): void {
1224
if (!this.markers[map]) {
1325
this.markers[map] = [];
@@ -22,26 +34,64 @@ export class MarkerGroupSettings implements IMarkerGroupSettings {
2234
delete this.markers[map];
2335
}
2436
}
25-
2637
}
2738

2839
name: string = "New Marker Group";
2940
active: boolean = true;
3041
icon: string = "marker1.webp";
3142
color: string = "#ffffff";
32-
id: string;
43+
id!: string;
44+
updateurl?: string | undefined;
45+
version?: string | undefined;
3346
markers: IMarkerMapSettings = {};
3447
description: string = "";
3548

3649
@Type(() => NamePlateSetting)
3750
defaultNamePlate: INamePlateSetting = new NamePlateSetting();
3851

3952
ToJSON(): string {
53+
this.version = new Date().toISOString();
4054
return JSON.stringify(this);
4155
}
4256

43-
constructor() {
57+
createId(): void {
4458
this.id = uuidv4();
4559
}
60+
61+
constructor() {
62+
this.createId();
63+
}
4664

65+
async CheckForUpdates(): Promise<IUpdateAvailable> {
66+
if (this.updateurl) {
67+
console.log("Checking for updates for " + this.id + " at " + this.updateurl);
68+
try {
69+
var response = await fetch(this.updateurl);
70+
} catch (error) {
71+
console.log("Error fetching update url for " + this.id + ": " + error);
72+
return { updateAvailable: false, markerid: this.id };
73+
}
74+
75+
if (!response?.ok) {
76+
console.log("Failed to check for updates for " + this.id + " at " + this.updateurl);
77+
const message = `An error has occured: ${response?.status}`;
78+
throw new Error(message);
79+
}
80+
var json = (await response.json()) as any;
81+
if (json.url && json.version && json.version !== this.version) {
82+
console.log("Update found for " + this.id + " at " + json.url);
83+
return {
84+
updateAvailable: true,
85+
version: json.version,
86+
url: json.url,
87+
markerid: this.id
88+
}
89+
} else {
90+
console.log("No update found for " + this.id);
91+
return {updateAvailable: false, markerid: this.id};
92+
}
93+
}
94+
return {updateAvailable: false, markerid: this.id};
95+
}
96+
4797
}

src/shared/models/settings/OverlaySettings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ import { IOverlaySettings } from "../../interfaces/settings/IOverlaySettings";
33
export class OverlaySettings implements IOverlaySettings {
44
checkForUpdates: boolean = true;
55
autoUpdate: boolean = true;
6+
checkForMarkerUpdates: boolean = true;
67
}

src/shared/models/settings/Settings.ts

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { IRuntimeSettings, ISettings } from "../../interfaces/settings";
22
import { IRenderSettings } from "../../interfaces/settings/IRenderSettings";
33
import { IRenderData } from "../../interfaces/render/renderdata";
4-
import { MarkerGroupSettings } from "./MarkerGroupSettings";
4+
import { IUpdateAvailable, MarkerGroupSettings } from "./MarkerGroupSettings";
55
import { RenderSettings } from "./RenderSettings";
66
import { deserialize, Type } from 'class-transformer';
77
import { IPositionMarker, MarkerType } from "../../interfaces/render/marker";
88
import { IVideoData } from "../../interfaces/datatransfer/IVideoData";
99
import { IOverlaySettings } from "../../interfaces/settings/IOverlaySettings";
1010
import { OverlaySettings } from "./OverlaySettings";
11+
import fetch from 'cross-fetch'
1112

1213
const fs = require('fs');
1314

@@ -38,11 +39,6 @@ export class Settings implements ISettings {
3839
}));
3940
}
4041

41-
addMarkerGroupFromJson(json: string): void {
42-
var instance = deserialize(MarkerGroupSettings, json);
43-
this.addMarkerGroup(instance);
44-
}
45-
4642
static loadConfig(filename: string): Settings {
4743
if (fs.existsSync(filename)) {
4844
let data = fs.readFileSync(filename);
@@ -58,8 +54,25 @@ export class Settings implements ISettings {
5854
this.runtimeData.map = mapId;
5955
}
6056

61-
addMarkerGroup(markerGroup: MarkerGroupSettings): void {
57+
getMarkerGroupIndexById(id: string): number | null {
58+
let markid = this.marks.findIndex(m => m.id === id);
59+
if (markid === -1) {
60+
return null;
61+
}
62+
return markid;
63+
}
64+
65+
addMarkerGroup(markerGroup: MarkerGroupSettings, forceReplace: boolean = false): boolean {
66+
var existing = this.getMarkerGroupIndexById(markerGroup.id);
67+
if ( existing !== null) {
68+
if (forceReplace) {
69+
this.removeMarkerGroup(existing);
70+
} else {
71+
return false;
72+
}
73+
}
6274
this.marks.push(markerGroup);
75+
return true;
6376
}
6477

6578
removeMarkerGroup(index: number): void {
@@ -70,6 +83,37 @@ export class Settings implements ISettings {
7083
return this.marks[index];
7184
}
7285

86+
getMarkerGroupById(id: string): MarkerGroupSettings | null {
87+
let markid = this.marks.findIndex(m => m.id === id);
88+
if (markid === -1) {
89+
return null;
90+
}
91+
return this.marks[markid];
92+
}
93+
94+
async CheckForMarkerUpdates() {
95+
console.log("Checking for marker updates");
96+
const asyncRes = await Promise.allSettled(this.marks.map(async (markerGroup) => { return await markerGroup.CheckForUpdates(); }));
97+
(asyncRes.filter(res => res.status === 'fulfilled') as PromiseFulfilledResult<IUpdateAvailable>[]).map(res => res.value).forEach(async res => {
98+
if (res.updateAvailable && res.url) {
99+
try {
100+
var response = await fetch(res.url);
101+
} catch (e) {
102+
console.log("Error fetching marker update! "+ e);
103+
return;
104+
}
105+
if (!response?.ok) {
106+
console.log("Failed to fetch update for " + res.markerid + " at " + res.url);
107+
const message = `An error has occured: ${response?.status}`;
108+
throw new Error(message);
109+
}
110+
var json = MarkerGroupSettings.fromJson(await response.text());
111+
this.addMarkerGroup(json, true);
112+
console.log("Updated marker " + res.markerid);
113+
}
114+
});
115+
}
116+
73117
// Translate marker data from settings to render ready data
74118
createRenderData(MapId: string): IRenderData {
75119
let data: IRenderData = { markers: [] };

0 commit comments

Comments
 (0)