Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ module.exports = {
"plugin:react/recommended",
"plugin:react-hooks/recommended",
],
overrides: [],
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
Expand All @@ -20,13 +19,35 @@ module.exports = {
},
},
plugins: ["react"],
rules: {
"react/prop-types": "off",
},
ignorePatterns: ["dist/*"],
settings: {
react: {
version: "detect",
},
},
overrides: [
{
files: ["*.ts", "*.tsx"],
extends: [
"eslint:recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
],
plugins: ["@typescript-eslint"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json",
tsconfigRootDir: __dirname,
},
rules: {
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/explicit-module-boundary-types": "warn",
"@typescript-eslint/consistent-type-imports": "warn",
"@typescript-eslint/prefer-readonly": "warn",
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/prefer-optional-chain": "warn",
},
},
],
};
3 changes: 2 additions & 1 deletion babel.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
}
}
],
"@babel/preset-react"
"@babel/preset-react",
"@babel/preset-typescript"
]
}
5,078 changes: 1,435 additions & 3,643 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"dev": "webpack-dev-server --mode development",
"start": "webpack-dev-server",
"eslint": "npx eslint --ignore-path .gitignore . --fix",
"tslint": "npx tsc --noEmit",
"prettier": "npx prettier --write .",
"style": "npx stylelint '**/*.css' --fix",
"lint": "npm run eslint && npm run prettier && npm run style"
"lint": "npm run eslint && npm run tslint && npm run prettier && npm run style"
},
"repository": {
"type": "git",
Expand All @@ -36,6 +37,14 @@
"@babel/core": "^7.16.12",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "^7.27.1",
"@types/jest": "^29.5.14",
"@types/lodash.clonedeep": "^4.5.9",
"@types/react": "^19.1.4",
"@types/react-dom": "^19.1.5",
"@types/seedrandom": "^3.0.8",
"@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.32.1",
"babel-jest": "^29.7.0",
"babel-loader": "^8.2.3",
"copy-webpack-plugin": "^10.2.4",
Expand All @@ -49,6 +58,8 @@
"style-loader": "^3.3.1",
"stylelint": "^14.6.0",
"stylelint-config-standard": "^25.0.0",
"ts-loader": "^9.5.2",
"typescript": "^5.8.3",
"webpack": "^5.68.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4",
Expand Down
104 changes: 104 additions & 0 deletions src/Types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Since the beforeinstallprompt event is experimental/nonstandard, the TS library doesn't have a type for it.
export interface BeforeInstallPromptEvent extends Event {
readonly platforms: Array<string>;

readonly userChoice: Promise<{
outcome: "accepted" | "dismissed";
platform: string;
}>;

prompt: () => Promise<void>;
}

export type PrimaryColor = "red" | "yellow" | "blue";
export type Letter =
| "A"
| "B"
| "C"
| "D"
| "E"
| "F"
| "G"
| "H"
| "I"
| "J"
| "K"
| "L"
| "M"
| "N"
| "O"
| "P"
| "QU"
| "R"
| "S"
| "T"
| "U"
| "V"
| "W"
| "X"
| "Y"
| "Z";

export type Stats = {
lastDatePlayed: string;
streak: number;
maxStreak: number;
collectedSwatchIndexes: number[];
};

export type GameState = {
seed: string;
letters: Letter[];
colors: PrimaryColor[];
clueIndexes: number[][];
clueMatches: boolean[];
playedIndexes: number[];
hints: boolean[][];
result: string;
newPaletteIndexes: number[];
difficultyLevel: number;
wordInProgress?: boolean;
};

export type GameReducerPayload =
| {
action: "startWord";
letterIndex: number;
}
| {
action: "hint";
clueIndex: number;
boxIndex: number;
}
| {
action: "addLetter";
letterIndex: number;
}
| {
action: "removeLetter";
letterIndex: number;
}
| {
action: "endWord";
collectedSwatchIndexes: number[];
}
| {
action: "newGame";
difficultyLevel?: number;
isDaily?: boolean;
};

export type PatternSimilarityDatum = {
sumSimilarityScore: number;
indexes: number[][];
words: Set<string>;
};

export type DisplayState =
| "rules"
| "announcement"
| "game"
| "daily"
| "settings"
| "heart"
| "stats";
7 changes: 0 additions & 7 deletions src/common/convertYYYYMMDDToDate.js

This file was deleted.

7 changes: 7 additions & 0 deletions src/common/convertYYYYMMDDToDate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function convertYYYYMMDDToDate(YYYYMMDD: string): Date {
return new Date(
parseInt(YYYYMMDD.slice(0, 4)),
parseInt(YYYYMMDD.slice(4, 6)) - 1, // months are 0-indexed
parseInt(YYYYMMDD.slice(6, 8)),
);
}
2 changes: 1 addition & 1 deletion src/common/getDailySeed.js → src/common/getDailySeed.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function getDailySeed() {
export default function getDailySeed(): string {
// Get a seed based on today's date 'YYYYMMDD'
const currentDate = new Date();
const seed = `${currentDate.getFullYear()}${(currentDate.getMonth() + 1)
Expand Down
4 changes: 2 additions & 2 deletions src/common/getDifficultyLevelForDay.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import {getDifficultyLevelForDay} from "./getDifficultyLevelForDay";
describe("Testing with mocked dates", () => {
let actualDate;

function mockDate(desiredValue) {
function mockDate(desiredDay) {
actualDate = Date;
global.Date = jest.fn(() => ({
...actualDate.prototype,
getDay: jest.fn(() => desiredValue),
getDay: jest.fn(() => desiredDay),
}));
global.Date.now = jest.fn(() => actualDate.now());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function getDifficultyLevelForDay() {
export function getDifficultyLevelForDay(): number {
const today = new Date().getDay();

// Sunday is 0, but we want it to be 7 instead
Expand Down
10 changes: 6 additions & 4 deletions src/common/getInitialState.js → src/common/getInitialState.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type {DisplayState} from "../Types";

export function getInitialState(
savedDisplayState,
hasVisitedEver,
hasVisitedSinceLastAnnouncement,
) {
savedDisplayState: DisplayState,
hasVisitedEver: boolean,
hasVisitedSinceLastAnnouncement: boolean,
): DisplayState {
if (!hasVisitedEver) {
return "rules";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function getRandomSeed() {
export default function getRandomSeed(): string {
// Gets a seed based on the current time, which
// should effectively give the impression of a
// "random" game each time a new game is generated based on the seed
Expand Down
29 changes: 0 additions & 29 deletions src/common/handleInstall.js

This file was deleted.

42 changes: 42 additions & 0 deletions src/common/handleInstall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type {BeforeInstallPromptEvent} from "../Types";
import sendAnalytics from "./sendAnalytics";

async function handleInstall(
installPromptEvent: BeforeInstallPromptEvent,
setInstallPromptEvent: React.Dispatch<
React.SetStateAction<BeforeInstallPromptEvent | null>
>,
): Promise<void> {
console.log("handling install");
console.log(installPromptEvent);
installPromptEvent.prompt();
const result = await installPromptEvent.userChoice;
console.log(result);
setInstallPromptEvent(null);
sendAnalytics("install");
}

function handleBeforeInstallPrompt(
event: BeforeInstallPromptEvent,
setInstallPromptEvent: React.Dispatch<
React.SetStateAction<BeforeInstallPromptEvent | null>
>,
setShowInstallButton: React.Dispatch<React.SetStateAction<boolean>>,
): void {
console.log("handleBeforeInstallPrompt");
if (event) setInstallPromptEvent(event);
setShowInstallButton(true);
}

function handleAppInstalled(
setInstallPromptEvent: React.Dispatch<
React.SetStateAction<BeforeInstallPromptEvent | null>
>,
setShowInstallButton: React.Dispatch<React.SetStateAction<boolean>>,
): void {
console.log("handleAppInstalled");
setInstallPromptEvent(null);
setShowInstallButton(false);
}

export {handleInstall, handleBeforeInstallPrompt, handleAppInstalled};
34 changes: 31 additions & 3 deletions src/common/handleShare.js → src/common/handleShare.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
import sendAnalytics from "./sendAnalytics";

export function assembleShareLink({url, seed, query = "id"}) {
export function assembleShareLink({
url,
seed,
query = "id",
}: {
url: string;
seed?: string;
query?: string;
}): string {
const fullUrl = seed ? `${url}?${query}=${seed}` : url;
return fullUrl;
}

export function handleShare({appName, text, url, seed, query}) {
export function handleShare({
appName,
text,
url,
seed,
query,
}: {
appName: string;
text: string;
url: string;
seed?: string;
query?: string;
}): void {
const fullUrl = assembleShareLink({url, seed, query});

navigator
Expand All @@ -21,7 +41,15 @@ export function handleShare({appName, text, url, seed, query}) {
sendAnalytics("share");
}

export function handleCopy({text, url, seed}) {
export function handleCopy({
text,
url,
seed,
}: {
text: string;
url: string;
seed?: string;
}): void {
const fullUrl = assembleShareLink({url, seed});

try {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import {convertYYYYMMDDToDate} from "./convertYYYYMMDDToDate";

export function hasVisitedSince(lastVisitedYYYYMMDD, cutoffYYYYMMDD) {
export function hasVisitedSince(
lastVisitedYYYYMMDD: string | null,
cutoffYYYYMMDD: string,
): boolean {
if (!lastVisitedYYYYMMDD) {
return false;
}
Expand Down
1 change: 1 addition & 0 deletions src/common/sendAnalytics.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function sendAnalytics(eventName: string, data?: object): void;
Loading
Loading