Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Announce custom crossjigs #47

Merged
merged 2 commits into from
Sep 8, 2024
Merged
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
2 changes: 0 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ For screenshots:

// todo later PR:

- Use the hasVisited state to announce
- add some custom daily puzzles

- // todo put screenshots of lexlet and blobble and wordfall ()as webp/compressed images? in MoreGames.js
- add link to sponsors?
- relocate to new file:
- getWordValidityGrids
Expand Down
12 changes: 10 additions & 2 deletions src/common/getInitialState.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
export function getInitialState(savedDisplay, hasVisited) {
if (!hasVisited) {
export function getInitialState(
savedDisplay,
hasVisitedEver,
hasVisitedRecently,
) {
if (!hasVisitedEver) {
return "rules";
}

if (!hasVisitedRecently) {
return "whatsNew";
}

if (savedDisplay === "game" || savedDisplay === "daily") {
return savedDisplay;
}
Expand Down
22 changes: 14 additions & 8 deletions src/common/getInitialState.test.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import {getInitialState} from "./getInitialState";

describe("getInitialState", () => {
test("returns 'rules' if hasVisited is false", () => {
expect(getInitialState("game", false)).toBe("rules");
test("returns 'rules' if hasVisitedEver is false", () => {
expect(getInitialState("game", false, true)).toBe("rules");

expect(getInitialState("game", false, false)).toBe("rules");
});

test("returns 'whatsNew' if hasVisitedRecently is false", () => {
expect(getInitialState("game", true, false)).toBe("whatsNew");
});

test("returns 'game' if hasVisited is true and savedDisplay is 'game", () => {
expect(getInitialState("game", true)).toBe("game");
test("returns 'game' if hasVisitedEver and hasVisitedRecently are true and savedDisplay is 'game", () => {
expect(getInitialState("game", true, true)).toBe("game");
});

test("returns 'daily' if hasVisited is true and savedDisplay is 'daily", () => {
expect(getInitialState("daily", true)).toBe("daily");
test("returns 'daily' if hasVisitedEver and hasVisitedRecently are true and savedDisplay is 'daily", () => {
expect(getInitialState("daily", true, true)).toBe("daily");
});

test("returns 'game' if hasVisited is true and savedDisplay is not 'game' or 'daily", () => {
expect(getInitialState("rules", true)).toBe("game");
test("returns 'game' if hasVisitedEver and hasVisitedRecently are and savedDisplay is not 'game' or 'daily", () => {
expect(getInitialState("rules", true, true)).toBe("game");
});
});
15 changes: 10 additions & 5 deletions src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ControlBar from "./ControlBar";
import FallbackInstall from "./FallbackInstall";
import CustomError from "./CustomError";
import CustomLookup from "./CustomLookup";
import WhatsNew from "./WhatsNew";
import {
handleAppInstalled,
handleBeforeInstallPrompt,
Expand All @@ -37,7 +38,9 @@ export default function App() {

// Determine when the player last visited the game
// This is used to determine whether to show the rules or an announcement instead of the game
const hasVisited = hasVisitedSince("crossjigLastVisited", "20240429");
const hasVisitedEver = hasVisitedSince("crossjigLastVisited", "20240429");
const hasVisitedRecently = hasVisitedSince("crossjigLastVisited", "20240908");

const [lastVisited] = React.useState(getDailySeed());
React.useEffect(() => {
window.localStorage.setItem(
Expand All @@ -49,7 +52,7 @@ export default function App() {
// Determine what view to show the user
const savedDisplay = JSON.parse(localStorage.getItem("crossjigDisplay"));
const [display, setDisplay] = React.useState(
getInitialState(savedDisplay, hasVisited),
getInitialState(savedDisplay, hasVisitedEver, hasVisitedRecently),
);

// Determine the opacity for the validity indicator
Expand Down Expand Up @@ -84,8 +87,7 @@ export default function App() {
customInit,
);

// todo consolidate lastVisited and setLastOpened?
const [, setLastOpened] = React.useState(Date.now());
const [, setLastVisible] = React.useState(Date.now());

function handleCustomGeneration() {
// If there is nothing to share, display a message with errors
Expand Down Expand Up @@ -131,7 +133,7 @@ export default function App() {
// This is to help the daily challenge refresh if the app has
// been open in the background since an earlier challenge.
if (!document.hidden) {
setLastOpened(Date.now());
setLastVisible(Date.now());
}
}

Expand Down Expand Up @@ -374,6 +376,9 @@ export default function App() {
></ExtendedMenu>
);

case "whatsNew":
return <WhatsNew setDisplay={setDisplay}></WhatsNew>;

default:
return (
<div className="App" id="crossjig">
Expand Down
12 changes: 6 additions & 6 deletions src/components/Rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ export default function Rules({setDisplay}) {
<b>Long press and drag</b> to move a group of touching pieces.
</p>
<p>
Click <div id="hintIcon" className="rulesIcon"></div> to get a hint. A
hint will move all pieces that are on the board to their correct
Click <span id="hintIcon" className="rulesIcon"></span> to get a hint.
A hint will move all pieces that are on the board to their correct
location. If all pieces are already in the correct location, a new
piece will be added to the board.
</p>
<p>
Click <div id="settingsIcon" className="rulesIcon"></div> to change
Click <span id="settingsIcon" className="rulesIcon"></span> to change
the number of pieces in the puzzle or the validity indication.
</p>
<p>
Click <div id="calendarIconSolved" className="rulesIcon"></div> to
Click <span id="calendarIconSolved" className="rulesIcon"></span> to
play the daily challenge. The daily challenge is easiest on Monday and
gets harder over the week.
</p>
<p>
Click <div id="customIcon" className="rulesIcon"></div> to build your
own crossjig to share with friends.
Click <span id="customIcon" className="rulesIcon"></span> to build
your own crossjig to share with friends.
</p>
</div>
<button
Expand Down
29 changes: 29 additions & 0 deletions src/components/WhatsNew.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";

export default function WhatsNew({setDisplay}) {
return (
<div className="App info">
<div id="rulesText">
<p>You can now create and share custom crossjigs!</p>
<p>
Click{" "}
<button
id="customIcon"
className="rulesIcon"
onClick={() => {
setDisplay("custom");
}}
></button>{" "}
to build your own crossjig to share with friends.
</p>
</div>
<button
onClick={() => {
setDisplay("game");
}}
>
{"Back to game"}
</button>
</div>
);
}
8 changes: 8 additions & 0 deletions src/styles/Rules.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
height: calc(var(--default-font-size) * 0.75);
}

/* What's new uses the rules styling, and this is used for what's new */
button.rulesIcon {
background-color: transparent;
border: none;
margin: 0;
padding: 0;
}

#rulesHeader {
grid-area: header;
}
Expand Down