Skip to content

Commit c19a2ad

Browse files
committed
Merge pull request #2 from rpitv/sync
1 parent a21658e commit c19a2ad

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+4064
-620
lines changed

apps/glimpse-graphics/docker-compose-dev.yml

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ services:
55
ports:
66
- "9090:80"
77
- "3000:3000"
8+
environment:
9+
- NODE_ENV=development
10+
- LOG_LEVEL=trace
811
volumes:
912
- ./.nodecg/cfg:/usr/src/app/cfg
1013
- ./.nodecg/db:/usr/src/app/db

apps/glimpse-graphics/docker-compose.yml

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ services:
44
build: .
55
ports:
66
- "9090:80"
7+
environment:
8+
- NODE_ENV=production
79
volumes:
810
- ./.nodecg/cfg:/usr/src/app/cfg
911
- ./.nodecg/db:/usr/src/app/db

apps/glimpse-graphics/package-lock.json

+1,521-62
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/glimpse-graphics/package.json

+25-6
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,22 @@
1313
"license": "MIT",
1414
"scripts": {
1515
"start": "node ../..",
16+
"start-dev": "npx nodemon ../.. | npx pino-pretty -c",
1617
"clean": "rm -rf node_modules/.cache && rm -rf shared/dist && rm -rf dashboard && rm -rf graphics && rm -rf extension",
1718
"build": "run-s clean build:*",
1819
"build:browser": "vite build",
1920
"build:extension": "tsc -b tsconfig.extension.json",
20-
"dev": "run-p start watch:*",
21+
"dev": "run-p watch:* start-dev",
2122
"watch:browser": "vite --host=0.0.0.0",
2223
"watch:extension": "tsc -b tsconfig.extension.json -w"
2324
},
2425
"dependencies": {
26+
"@vueuse/core": "^9.5.0",
2527
"animejs": "^3.2.1",
2628
"module-alias": "^2.2.2",
29+
"pinia": "^2.0.23",
30+
"pino": "^8.7.0",
31+
"serialport": "^10.4.0",
2732
"uuid": "^8.3.2"
2833
},
2934
"devDependencies": {
@@ -34,7 +39,9 @@
3439
"naive-ui": "^2.32.1",
3540
"nodecg-cli": "^8.0.1",
3641
"nodecg-types": "^1.9.0",
42+
"nodemon": "^2.0.20",
3743
"npm-run-all": "^4.1.5",
44+
"pino-pretty": "^9.1.1",
3845
"sass": "^1.54.4",
3946
"typescript": "^4.7.4",
4047
"vite": "^2.9.14",
@@ -50,9 +57,16 @@
5057
"name": "game-settings",
5158
"title": "Game Settings",
5259
"file": "game-settings.html",
53-
"workspace": "General",
60+
"workspace": "Settings",
5461
"width": "8"
5562
},
63+
{
64+
"name": "sync-settings",
65+
"title": "Sync Settings",
66+
"file": "sync-settings.html",
67+
"workspace": "Settings",
68+
"width": "4"
69+
},
5670
{
5771
"name": "command-palette",
5872
"title": "Command Palette",
@@ -61,9 +75,9 @@
6175
"width": "2"
6276
},
6377
{
64-
"name": "score",
65-
"title": "Score",
66-
"file": "score.html",
78+
"name": "teams",
79+
"title": "Teams",
80+
"file": "teams.html",
6781
"workspace": "Scoreboard",
6882
"width": "6"
6983
},
@@ -100,7 +114,12 @@
100114
{
101115
"name": "images",
102116
"title": "Images",
103-
"allowedTypes": ["jpg", "jpeg", "gif", "png"]
117+
"allowedTypes": [
118+
"jpg",
119+
"jpeg",
120+
"gif",
121+
"png"
122+
]
104123
}
105124
]
106125
}

apps/glimpse-graphics/src/browser-common/replicant.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,20 @@ import {ReplicantOptions} from "nodecg-types/types/lib/replicant";
44
export async function replicant<T = any>(name: string, namespace?: string, options?: ReplicantOptions<T>): Promise<Ref<T>> { // @ts-ignore
55
const realReplicant = nodecg.Replicant<T>(name, namespace, options);
66

7-
let value: Ref<T|undefined> = ref(undefined);
7+
let value: Ref<T|null|undefined> = ref(undefined);
88
realReplicant.on('change', () => {
99
// FIXME updating the value directly does not trigger the computed property to recompute for some reason.
10-
if(Array.isArray(realReplicant.value)) {
11-
value.value = <T><unknown>[...realReplicant.value];
10+
// This is a workaround for now.
11+
if(typeof realReplicant.value === "object") {
12+
if(realReplicant.value === null) {
13+
value.value = null;
14+
} else if(Array.isArray(realReplicant.value)) {
15+
value.value = <T><unknown>[...realReplicant.value];
16+
} else {
17+
value.value = <T><unknown>{...realReplicant.value};
18+
}
1219
} else {
13-
value.value = <T>realReplicant.value; // Will not be undefined
20+
value.value = <T>realReplicant.value;
1421
}
1522
});
1623

apps/glimpse-graphics/src/browser-common/replicants.ts

+55-30
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,82 @@ import {DisplayableMessage} from "../common/DisplayableMessage";
33

44
export async function loadReplicants() {
55
return {
6+
sync: {
7+
availablePorts: await replicant<string[]>("availablePorts", "glimpse-graphics.sync-settings", {
8+
defaultValue: [],
9+
persistent: false
10+
}),
11+
selectedPort: await replicant<string | null>("selectedPort", "glimpse-graphics.sync-settings", {defaultValue: null}),
12+
selectedSport: await replicant<string>("selectedSport", "glimpse-graphics.sync-settings", {defaultValue: 'Hockey/Lacrosse'}),
13+
status: await replicant<{ connected: boolean, bitrate: number }>("status", "glimpse-graphics.sync-settings", {
14+
defaultValue: {
15+
connected: false,
16+
bitrate: 0
17+
}, persistent: false
18+
}),
19+
values: {
20+
clock: await replicant<boolean>("clock", "glimpse-graphics.sync-settings.values", {defaultValue: false}),
21+
period: await replicant<boolean>("period", "glimpse-graphics.sync-settings.values", {defaultValue: false}),
22+
teams: [
23+
{
24+
score: await replicant<boolean>("score", "glimpse-graphics.sync-settings.values.team1", {defaultValue: false}),
25+
name: await replicant<boolean>("name", "glimpse-graphics.sync-settings.values.team1", {defaultValue: false}),
26+
abbreviation: await replicant<boolean>("abbreviation", "glimpse-graphics.sync-settings.values.team1", {defaultValue: false}),
27+
}, {
28+
score: await replicant<boolean>("score", "glimpse-graphics.sync-settings.values.team2", {defaultValue: false}),
29+
name: await replicant<boolean>("name", "glimpse-graphics.sync-settings.values.team2", {defaultValue: false}),
30+
abbreviation: await replicant<boolean>("abbreviation", "glimpse-graphics.sync-settings.values.team2", {defaultValue: false}),
31+
}
32+
],
33+
baseball: {
34+
bottomTop: await replicant<boolean>("bottomTop", "glimpse-graphics.sync-settings.values.baseball", {defaultValue: false}),
35+
outsStrikesBalls: await replicant<boolean>("outsStrikesBall", "glimpse-graphics.sync-settings.values.baseball", {defaultValue: false}),
36+
},
37+
football: {
38+
downs: await replicant<boolean>("downs", "glimpse-graphics.sync-settings.values.football", {defaultValue: false}),
39+
possession: await replicant<boolean>("possession", "glimpse-graphics.sync-settings.values.football", {defaultValue: false}),
40+
yardsToGo: await replicant<boolean>("yardsToGo", "glimpse-graphics.sync-settings.values.football", {defaultValue: false}),
41+
playClock: await replicant<boolean>("playClock", "glimpse-graphics.sync-settings.values.football", {defaultValue: false}),
42+
}
43+
}
44+
},
645
gameSettings: {
7-
style: await replicant<'espn'|'rpitv-modern'|'rpitv-classic'>('style', 'glimpse-graphics.game-settings.style', {defaultValue: 'rpitv-modern'}),
46+
style: await replicant<'espn' | 'rpitv-modern' | 'rpitv-classic'>('style', 'glimpse-graphics.game-settings.style', {defaultValue: 'rpitv-modern'}),
847
clock: {
948
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.clock", {defaultValue: true}),
10-
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.clock", {defaultValue: false})
1149
},
1250
periods: {
1351
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.periods", {defaultValue: true}),
14-
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.periods", {defaultValue: false}),
1552
count: await replicant<number>('count', 'glimpse-graphics.game-settings.periods', {defaultValue: 3}),
1653
length: await replicant<number>('length', 'glimpse-graphics.game-settings.periods', {defaultValue: 1200_000}),
1754
overtime: {
18-
enabled: await replicant<boolean>('enabled', 'glimpse-graphics.game-settings.periods.overtime', {defaultValue: false}),
1955
count: await replicant<number>('count', 'glimpse-graphics.game-settings.periods.overtime', {defaultValue: 0}),
56+
isInfinite: await replicant<boolean>('isInfinite', 'glimpse-graphics.game-settings.periods.overtime', {defaultValue: false}),
2057
length: await replicant<number>('length', 'glimpse-graphics.game-settings.periods.overtime', {defaultValue: 300_000}),
21-
}
58+
},
59+
shootouts: await replicant<boolean>('shootouts', 'glimpse-graphics.game-settings.periods', {defaultValue: false}),
2260
},
61+
2362
baseball: {
24-
bases: {
25-
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.baseball.bases", {defaultValue: false}),
26-
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.baseball.bases", {defaultValue: false}),
27-
},
28-
bottomTop: {
29-
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.baseball.bottomTop", {defaultValue: false}),
30-
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.baseball.bottomTop", {defaultValue: false}),
31-
},
32-
outsStrikesBalls: {
33-
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.baseball.outsStrikesBalls", {defaultValue: false}),
34-
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.baseball.outsStrikesBalls", {defaultValue: false}),
35-
}
63+
bases: await replicant<boolean>("bases", "glimpse-graphics.game-settings.baseball", {defaultValue: false}),
64+
bottomTop: await replicant<boolean>("bottomTop", "glimpse-graphics.game-settings.baseball", {defaultValue: false}),
65+
outsStrikesBalls: await replicant<boolean>("outsStrikesBalls", "glimpse-graphics.game-settings.baseball", {defaultValue: false}),
3666
},
3767
football: {
38-
downs: {
39-
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.football.downs", {defaultValue: false}),
40-
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.football.downs", {defaultValue: false}),
41-
},
42-
possession: {
43-
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.football.possession", {defaultValue: false}),
44-
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.football.possession", {defaultValue: false}),
45-
},
46-
playClock: {
47-
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.football.playClock", {defaultValue: false}),
48-
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.football.playClock", {defaultValue: false}),
49-
}
68+
downs: await replicant<boolean>("downs", "glimpse-graphics.game-settings.football", {defaultValue: false}),
69+
possession: await replicant<boolean>("possession", "glimpse-graphics.game-settings.football", {defaultValue: false}),
70+
yardsToGo: await replicant<boolean>("yardsToGo", "glimpse-graphics.game-settings.football", {defaultValue: false}),
71+
playClock: await replicant<boolean>("playClock", "glimpse-graphics.game-settings.football", {defaultValue: false}),
5072
}
5173
},
5274
scoreboard: {
5375
visible: await replicant<boolean>('visible', 'glimpse-graphics.scoreboard', {defaultValue: true}),
5476
clock: {
5577
time: await replicant<number>('time', 'glimpse-graphics.scoreboard.clock', {defaultValue: 1200_000}),
56-
isRunning: await replicant<boolean>('isRunning', 'glimpse-graphics.scoreboard.clock', {defaultValue: false, persistent: false}),
78+
isRunning: await replicant<boolean>('isRunning', 'glimpse-graphics.scoreboard.clock', {
79+
defaultValue: false,
80+
persistent: false
81+
}),
5782
},
5883
period: await replicant<number>('period', 'glimpse-graphics.scoreboard', {defaultValue: 1})
5984
},
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,33 @@
1+
type ListenerFn = (argument?: any, ack?: (error: Error, returnVal: any) => void) => void;
2+
13
export class MessageComposable {
24

35
public channel: string;
46
public namespace: string;
57

8+
private listeners: ListenerFn[] = [];
9+
610
public constructor(channel: string, namespace?: string) {
711
this.channel = channel;
812
this.namespace = namespace ?? "";
913
}
1014

11-
public async send(argument?: any): Promise<void> {
15+
public async send(argument?: any): Promise<any> {
1216
// @ts-ignore
13-
await nodecg.sendMessage(this.namespace + '.' + this.channel, argument)
17+
return await nodecg.sendMessage(this.namespace + '.' + this.channel, argument);
18+
}
19+
20+
public listen(callback: ListenerFn): void {
21+
this.listeners.push(callback);
22+
// @ts-ignore
23+
nodecg.listenFor(this.namespace + '.' + this.channel, callback)
24+
}
25+
26+
public destroy(): void {
27+
for(const listener of this.listeners) {
28+
// @ts-ignore
29+
nodecg.unlisten(this.namespace + '.' + this.channel, listener);
30+
}
31+
this.listeners = [];
1432
}
1533
}

0 commit comments

Comments
 (0)