Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/editors/stopwatch/actions.ts
1691 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
/*
7
The actions -- what you can do with a timer, and also the
8
underlying synchronized state.
9
*/
10
11
import { history_path } from "@cocalc/util/misc";
12
import { webapp_client } from "@cocalc/frontend/webapp-client";
13
import { Actions, Store, TypedMap } from "@cocalc/frontend/app-framework";
14
import { List } from "immutable";
15
16
export interface StopwatchEditorState {
17
name: string;
18
timers?: List<TimerRecord>;
19
error?: string;
20
}
21
22
export type TimerState = "paused" | "running" | "stopped";
23
24
interface Timer {
25
id: number;
26
label?: string;
27
total?: number;
28
state: TimerState;
29
time: number;
30
countdown?: number; // a countdown time is the same a stopwatch, but has this field, which is the number of seconds.
31
}
32
33
type TimerRecord = TypedMap<Timer>;
34
35
export class TimeActions extends Actions<StopwatchEditorState> {
36
private project_id: string;
37
private path: string;
38
public syncdb: any;
39
public store: Store<StopwatchEditorState>;
40
41
public _init(project_id: string, path: string): void {
42
this._syncdb_change = this._syncdb_change.bind(this);
43
this.project_id = project_id;
44
this.path = path;
45
// be explicit about exactly what state is in the store
46
this.setState({
47
timers: undefined,
48
});
49
}
50
51
public init_error(err): void {
52
this.setState({
53
error: err,
54
});
55
}
56
57
public _syncdb_change(): void {
58
this.setState({
59
timers: this.syncdb.get(),
60
});
61
62
if (this.syncdb.get_doc().size === 0) {
63
this.addStopwatch();
64
}
65
}
66
67
private _set(obj: Partial<Timer>): void {
68
this.syncdb.set(obj);
69
this.syncdb.commit();
70
this.syncdb.save_to_disk();
71
}
72
73
public addStopwatch(): void {
74
// make id equal to the largest current id (or 0 if none)
75
let id = 0;
76
this.syncdb.get().map((data) => {
77
id = Math.max(data.get("id"), id);
78
});
79
id += 1; // our new stopwatch has the largest id (so at the bottom)
80
this._set({
81
id,
82
label: "",
83
total: 0,
84
state: "stopped",
85
time: webapp_client.server_time() - 0,
86
});
87
}
88
89
public deleteStopwatch(id: number): void {
90
this.syncdb.delete({ id });
91
if (this.syncdb.get_doc().size === 0) {
92
this.addStopwatch();
93
}
94
this.syncdb.commit();
95
this.syncdb.save_to_disk();
96
}
97
98
public resetStopwatch(id: number): void {
99
this._set({
100
id,
101
total: 0,
102
state: "stopped",
103
time: webapp_client.server_time() - 0,
104
});
105
}
106
107
public startStopwatch(id: number): void {
108
this._set({
109
id,
110
time: webapp_client.server_time() - 0,
111
state: "running",
112
});
113
}
114
115
public pauseStopwatch(id: number): void {
116
const x = this.syncdb && this.syncdb.get_one({ id });
117
if (x == null) return;
118
this._set({
119
id,
120
time: webapp_client.server_time() - 0,
121
total: x.get("total") + (webapp_client.server_time() - x.get("time")),
122
state: "paused",
123
});
124
}
125
126
public setLabel(id: number, label: string): void {
127
const x = this.syncdb && this.syncdb.get_one({ id });
128
if (x == null) return;
129
this._set({ id, label, state: x.get("state"), time: x.get("time") });
130
}
131
132
// Set current displayed time on clock or starting value for timer (and reset timer to be at that value),
133
// where the input is the time in seconds.
134
public setCountdown(id: number, time: number): void {
135
const x = this.syncdb && this.syncdb.get_one({ id });
136
if (x == null) return;
137
this._set({
138
id,
139
countdown: time,
140
});
141
}
142
143
public time_travel(): void {
144
this.redux.getProjectActions(this.project_id).open_file({
145
path: history_path(this.path),
146
foreground: true,
147
});
148
}
149
150
public undo(): void {
151
if (this.syncdb) {
152
this.syncdb.undo();
153
}
154
}
155
156
public redo(): void {
157
if (this.syncdb) {
158
this.syncdb.redo();
159
}
160
}
161
162
public addTimer(): void {
163
// make id equal to the largest current id (or 0 if none)
164
let id = 0;
165
this.syncdb.get().map((data) => {
166
id = Math.max(data.get("id"), id);
167
});
168
id += 1; // our new timer has the largest id (so at the bottom)
169
this._set({
170
id,
171
label: "",
172
total: 0,
173
state: "stopped",
174
time: webapp_client.server_time() - 0,
175
countdown: 60,
176
});
177
}
178
}
179
180