Skip to content

Commit 3492d2f

Browse files
committed
Merged PR 320: v1.33.2 - mACF default, stay signed into Google Sheets
- Use "mACF with powers" as the standard game format - Automatically sign back into Google Sheets after the initial token expires. This fixes the issue where users had to refresh MODAQ after an hour to keep using Google Sheets - Bump version to 1.33.2
1 parent 8160b17 commit 3492d2f

File tree

5 files changed

+62
-29
lines changed

5 files changed

+62
-29
lines changed

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "modaq",
3-
"version": "1.33.1",
3+
"version": "1.33.2",
44
"description": "Quiz Bowl Reader using TypeScript, React, and MobX",
55
"repository": {
66
"type": "git",
@@ -21,9 +21,9 @@
2121
"devDependencies": {
2222
"@babel/core": "^7.25.2",
2323
"@types/chai": "^4.2.15",
24-
"@types/google.accounts": "^0.0.2",
25-
"@types/gapi.client.sheets": "^4.0.20201030",
26-
"@types/gapi.client": "^1.0.5",
24+
"@types/google.accounts": "^0.0.15",
25+
"@types/gapi.client.sheets": "^4.0.20201031",
26+
"@types/gapi.client": "^1.0.8",
2727
"@types/he": "^1.1.2",
2828
"@types/mocha": "^8.2.1",
2929
"@types/react": "^17.0.3",

src/sheets/SheetsApi.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,37 @@ const timedOutMessage = "Timed out signing into Google Sheets";
77

88
export const SheetsApi: ISheetsApi = {
99
initializeIfNeeded: async (uiState: UIState): Promise<void> => {
10-
if (
11-
uiState.sheetsState.apiInitialized === LoadingState.Loading ||
12-
uiState.sheetsState.apiInitialized === LoadingState.Loaded
10+
// If it's loaded and the token has expired, prompt again
11+
if (uiState.sheetsState.apiInitialized === LoadingState.Loading) {
12+
return;
13+
} else if (
14+
uiState.sheetsState.apiInitialized === LoadingState.Loaded &&
15+
uiState.sheetsState.expiresAt != undefined &&
16+
uiState.sheetsState.expiresAt > Date.now()
1317
) {
1418
return;
1519
}
1620

21+
const initialState: LoadingState = uiState.sheetsState.apiInitialized;
22+
1723
// Bit of a hacky wait to wait until the callback is done
1824
// Need to follow this approach: https://developers.google.com/identity/oauth2/web/guides/migration-to-gis#gapi-asyncawait
1925
uiState.sheetsState.setSheetsApiInitialized(LoadingState.Loading);
2026

2127
const promise: Promise<void> = new Promise<void>(async (resolve, reject) => {
2228
try {
23-
// Load gapi first, then load the GIS client
24-
await new Promise<void>((resolve) => {
25-
gapi.load("client", resolve);
26-
});
29+
// Load gapi first, then load the GIS client. Only load gapi stuff the first time we're through, however.
30+
if (initialState === LoadingState.Unloaded) {
31+
await new Promise<void>((resolve) => {
32+
gapi.load("client", resolve);
33+
});
2734

28-
// Typings issue, init isn't listed as a method
29-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
30-
await (gapi.client as any).init({});
35+
// Typings issue, init isn't listed as a method
36+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
37+
await (gapi.client as any).init({});
3138

32-
await gapi.client.load("https://sheets.googleapis.com/$discovery/rest?version=v4");
39+
await gapi.client.load("https://sheets.googleapis.com/$discovery/rest?version=v4");
40+
}
3341

3442
const clientId: string | undefined = uiState.sheetsState.clientId;
3543
if (clientId == undefined) {
@@ -53,8 +61,13 @@ export const SheetsApi: ISheetsApi = {
5361
}
5462
}, 2 * 60 * 1000);
5563

64+
// If the user already signed in, don't make them pick the account again
65+
const prompt: "none" | "select_account" =
66+
initialState === LoadingState.Loaded ? "none" : "select_account";
67+
5668
const tokenClient = google.accounts.oauth2.initTokenClient({
5769
client_id: clientId,
70+
prompt,
5871
scope: "https://www.googleapis.com/auth/spreadsheets",
5972
callback: (tokenResponse) => {
6073
clearTimeout(cancelSignIn);
@@ -65,9 +78,17 @@ export const SheetsApi: ISheetsApi = {
6578
return;
6679
}
6780

81+
const expiresAt: number = Date.now() + parseInt(tokenResponse.expires_in) * 1000;
82+
uiState.sheetsState.setExpiresAt(expiresAt);
6883
uiState.sheetsState.setSheetsApiInitialized(LoadingState.Loaded);
6984
resolve();
7085
},
86+
error_callback: (error) => {
87+
clearTimeout(cancelSignIn);
88+
uiState.sheetsState.setSheetsApiInitialized(LoadingState.Error);
89+
reject(error.message);
90+
return;
91+
},
7192
});
7293

7394
tokenClient.requestAccessToken();

src/state/SheetState.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ import { IStatus } from "../IStatus";
55

66
export class SheetState {
77
@ignore
8-
apiInitialized: LoadingState;
8+
public apiInitialized: LoadingState;
99

1010
public clientId: string | undefined;
1111

12+
@ignore
13+
public expiresAt: number | undefined;
14+
1215
@ignore
1316
public exportStatus: IStatus | undefined;
1417

@@ -35,6 +38,7 @@ export class SheetState {
3538

3639
this.apiInitialized = LoadingState.Unloaded;
3740
this.clientId = undefined;
41+
this.expiresAt = undefined;
3842
this.exportStatus = undefined;
3943
this.exportState = undefined;
4044
this.rosterLoadStatus = undefined;
@@ -44,6 +48,10 @@ export class SheetState {
4448
this.sheetType = undefined;
4549
}
4650

51+
public clearExpiresAt(): void {
52+
this.expiresAt = undefined;
53+
}
54+
4755
public clearExportStatus(): void {
4856
this.exportStatus = undefined;
4957
this.exportState = undefined;
@@ -61,6 +69,10 @@ export class SheetState {
6169
this.clientId = clientId;
6270
}
6371

72+
public setExpiresAt(expiresAt: number): void {
73+
this.expiresAt = expiresAt;
74+
}
75+
6476
public setExportStatus(status: IStatus, state: ExportState | undefined = undefined): void {
6577
this.exportStatus = status;
6678

src/state/UIState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export class UIState {
202202
this.pendingNewGame = {
203203
packet: new PacketState(),
204204
type: PendingGameType.Manual,
205-
gameFormat: GameFormats.ACFGameFormat,
205+
gameFormat: GameFormats.StandardPowersMACFGameFormat,
206206
manual: {
207207
firstTeamPlayers,
208208
secondTeamPlayers,

yarn.lock

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -774,10 +774,10 @@
774774
dependencies:
775775
"@maxim_mazurok/gapi.client.discovery-v1" latest
776776

777-
"@types/gapi.client.sheets@^4.0.20201030":
778-
version "4.0.20201030"
779-
resolved "https://registry.yarnpkg.com/@types/gapi.client.sheets/-/gapi.client.sheets-4.0.20201030.tgz#792160242b06441962de017f33c58b3413832a0a"
780-
integrity sha512-U6sBNFNbIV8Z18jKDpK3m5ehyHXbAJKfT3kM84hb57/tkcWvfXFu84xg4PFKHHxTSUlL0arF1ikesNdM3hRrjw==
777+
"@types/gapi.client.sheets@^4.0.20201031":
778+
version "4.0.20201031"
779+
resolved "https://registry.yarnpkg.com/@types/gapi.client.sheets/-/gapi.client.sheets-4.0.20201031.tgz#2d11a6805385c4bcfc9d147ab5eb288a87547953"
780+
integrity sha512-1Aiu11rNNoyPDHW6v8TVcSmlDN+MkxSuafwiawaK5YqZ+uYA+O63vjUvkK+3qNduSLh7D9qBJc/8GGwgN6gsTw==
781781
dependencies:
782782
"@maxim_mazurok/gapi.client.sheets-v4" latest
783783

@@ -786,15 +786,15 @@
786786
resolved "https://registry.npmjs.org/@types/gapi.client/-/gapi.client-1.0.3.tgz"
787787
integrity sha512-XhJ45zhedkqXln75Y0XZAFmHFHNu6zCGe9EyPiu5a20Q7XnsEENR3dnUqbYvp7w9e6vjXW+uKGqb3z/ezZijDg==
788788

789-
"@types/gapi.client@^1.0.5":
790-
version "1.0.5"
791-
resolved "https://registry.yarnpkg.com/@types/gapi.client/-/gapi.client-1.0.5.tgz#a6eb97e664fe51656c5b52258bd0afef28c76308"
792-
integrity sha512-OTpbBMuzfC4lkvaomxqskI/iWRGW3zOZbDXZLNSyiuswTiSSGgILRLkg0POuZ4EgzEdaYaTlXpnXiCp07ri/Yw==
789+
"@types/gapi.client@^1.0.8":
790+
version "1.0.8"
791+
resolved "https://registry.yarnpkg.com/@types/gapi.client/-/gapi.client-1.0.8.tgz#8e02c57493b014521f2fa3359166c01dc2861cd7"
792+
integrity sha512-qJQUmmumbYym3Amax0S8CVzuSngcXsC1fJdwRS2zeW5lM63zXkw4wJFP+bG0jzgi0R6EsJKoHnGNVTDbOyG1ng==
793793

794-
"@types/google.accounts@^0.0.2":
795-
version "0.0.2"
796-
resolved "https://registry.yarnpkg.com/@types/google.accounts/-/google.accounts-0.0.2.tgz#4e03bd249fe490f004f4f8d6423343fc51f5614a"
797-
integrity sha512-wmnbDIiGZNr3dJ+NCGiWme78rhsf5gn1YJM6uRjf3FCb8lrRptybQeAnHQ+GDfKSo+z2hRxhS32VRDXJEAvCmg==
794+
"@types/google.accounts@^0.0.15":
795+
version "0.0.15"
796+
resolved "https://registry.yarnpkg.com/@types/google.accounts/-/google.accounts-0.0.15.tgz#88c6ceba6ecd8f54ae42891393d2fff0fcdb4ee2"
797+
integrity sha512-NiydIuJzwdpnWNqTPOeDzGXhzz46Ll6T4rN3YWSm9Zfx/8ZfbwFbzyPSw1Tkz4uE3gQiU+fRj4KvBVUuHmk+KQ==
798798

799799
"@types/he@^1.1.2":
800800
version "1.1.2"

0 commit comments

Comments
 (0)