Add option for coloured edges on progress page

This commit is contained in:
2021-10-03 17:43:22 +01:00
parent aec4c8efcf
commit 4c2f1613ff
9 changed files with 83 additions and 23 deletions

View File

@@ -61,11 +61,12 @@ service cloud.firestore {
function verifyFieldTypes() { function verifyFieldTypes() {
return verifyBoolType("sound") && return verifyBoolType("sound") &&
verifyBoolType("coloredEdges") &&
verifyThemeValue(); verifyThemeValue();
} }
function getPossibleFields() { function getPossibleFields() {
let requiredFields = ["sound", "theme"]; let requiredFields = ["sound", "theme", "coloredEdges"];
let optionalFields = []; let optionalFields = [];
let allFields = requiredFields.concat(optionalFields); let allFields = requiredFields.concat(optionalFields);
return [requiredFields, allFields]; return [requiredFields, allFields];

View File

@@ -33,6 +33,7 @@ exports.userCreated = functions.auth.user().onCreate((user) => {
return db.collection("users").doc(user.uid).set({ return db.collection("users").doc(user.uid).set({
sound: true, sound: true,
theme: "default", theme: "default",
coloredEdges: false,
}); });
}); });
}); });

View File

@@ -121,6 +121,7 @@ class App extends React.Component {
userDataPresent: false, userDataPresent: false,
sound: true, sound: true,
theme: "default", theme: "default",
coloredEdges: false,
pageLoading: true, pageLoading: true,
}; };
@@ -161,9 +162,11 @@ class App extends React.Component {
.then((userDoc) => { .then((userDoc) => {
newState.sound = userDoc.data().sound; newState.sound = userDoc.data().sound;
newState.theme = userDoc.data().theme; newState.theme = userDoc.data().theme;
newState.coloredEdges = userDoc.data().coloredEdges;
}).catch((error) => { }).catch((error) => {
newState.sound = true; newState.sound = true;
newState.theme = "default"; newState.theme = "default";
newState.coloredEdges = false;
}); });
} }
@@ -234,6 +237,17 @@ class App extends React.Component {
}); });
} }
handleColoredEdgesChange = (newColoredEdges, globalChange = false) => {
if (globalChange) firebase.firestore().collection("users")
.doc(this.state.user.uid)
.update({
coloredEdges: newColoredEdges,
});
this.setState({
coloredEdges: newColoredEdges,
});
}
acceptCookies = () => { acceptCookies = () => {
window.removeEventListener('resize', this.updateCookieNoticeMargins); window.removeEventListener('resize', this.updateCookieNoticeMargins);
this.cookieNoticeHeight = this.cookieNotice.offsetHeight; this.cookieNoticeHeight = this.cookieNotice.offsetHeight;
@@ -285,10 +299,14 @@ class App extends React.Component {
<GroupPage db={db} functions={functions} user={this.state.user} logEvent={analytics.logEvent} page={this.page} /> <GroupPage db={db} functions={functions} user={this.state.user} logEvent={analytics.logEvent} page={this.page} />
</Route> </Route>
<Route path="/settings"> <Route path="/settings">
<Settings db={db} user={this.state.user} sound={this.state.sound} handleSoundChange={this.handleSoundChange} theme={this.state.theme} handleThemeChange={this.handleThemeChange} themes={themes} logEvent={analytics.logEvent} page={this.page} /> <Settings db={db} user={this.state.user} sound={this.state.sound} coloredEdges={this.state.coloredEdges} handleColoredEdgesChange={this.handleColoredEdgesChange} handleSoundChange={this.handleSoundChange} theme={this.state.theme} handleThemeChange={this.handleThemeChange} themes={themes} logEvent={analytics.logEvent} page={this.page} />
</Route> </Route>
<Route path="/progress/:progressId" exact> <Route path="/progress/:progressId" exact>
<Progress db={db} functions={functions} user={this.state.user} sound={this.state.sound} handleSoundChange={this.handleSoundChange} theme={this.state.theme} handleThemeChange={this.handleThemeChange} themes={themes} logEvent={analytics.logEvent} page={this.page} /> <Progress db={db} functions={functions} user={this.state.user} sound={this.state.sound} coloredEdges={this.state.coloredEdges} handleColoredEdgesChange={this.handleColoredEdgesChange} handleSoundChange={this.handleSoundChange} theme={this.state.theme} handleThemeChange={this.handleThemeChange} themes={themes} logEvent={analytics.logEvent} page={this.page} />
{
this.state.coloredEdges &&
<div className="colored-edges"></div>
}
</Route> </Route>
<Route path="/create-set" exact> <Route path="/create-set" exact>
<CreateSet db={db} user={this.state.user} logEvent={analytics.logEvent} page={this.page} /> <CreateSet db={db} user={this.state.user} logEvent={analytics.logEvent} page={this.page} />

View File

@@ -61,6 +61,7 @@ export default withRouter(class Progress extends React.Component {
showSettings: false, showSettings: false,
soundInput: this.props.sound, soundInput: this.props.sound,
themeInput: this.props.theme, themeInput: this.props.theme,
coloredEdgesInput: this.props.coloredEdges,
setIds: [], setIds: [],
attemptNumber: 1, attemptNumber: 1,
attemptHistory: {}, attemptHistory: {},
@@ -232,9 +233,16 @@ export default withRouter(class Progress extends React.Component {
}); });
} }
handleColoredEdgesInputChange = (event) => {
this.setState({
coloredEdgesInput: event.target.checked,
});
}
saveSettings = (globalChange) => { saveSettings = (globalChange) => {
this.props.handleSoundChange(this.state.soundInput, globalChange); this.props.handleSoundChange(this.state.soundInput, globalChange);
this.props.handleThemeChange(this.state.themeInput, globalChange); this.props.handleThemeChange(this.state.themeInput, globalChange);
this.props.handleColoredEdgesChange(this.state.coloredEdgesInput, globalChange);
this.hideSettings(); this.hideSettings();
} }
@@ -702,9 +710,11 @@ export default withRouter(class Progress extends React.Component {
saveSettings={this.saveSettings} saveSettings={this.saveSettings}
handleSoundInputChange={this.handleSoundInputChange} handleSoundInputChange={this.handleSoundInputChange}
handleThemeInputChange={this.handleThemeInputChange} handleThemeInputChange={this.handleThemeInputChange}
handleColoredEdgesInputChange={this.handleColoredEdgesInputChange}
themes={this.props.themes} themes={this.props.themes}
soundInput={this.state.soundInput} soundInput={this.state.soundInput}
themeInput={this.state.themeInput} themeInput={this.state.themeInput}
coloredEdgesInput={this.state.coloredEdgesInput}
/> />

View File

@@ -22,6 +22,7 @@ export default withRouter(class Settings extends Component {
], ],
soundInput: this.props.sound, soundInput: this.props.sound,
themeInput: this.props.theme, themeInput: this.props.theme,
coloredEdgesInput: this.props.coloredEdges,
}; };
let isMounted = true; let isMounted = true;
@@ -60,9 +61,16 @@ export default withRouter(class Settings extends Component {
}); });
} }
handleColoredEdgesInputChange = (event) => {
this.setState({
coloredEdgesInput: event.target.checked,
});
}
saveSettings = (globalChange) => { saveSettings = (globalChange) => {
this.props.handleSoundChange(this.state.soundInput, globalChange); this.props.handleSoundChange(this.state.soundInput, globalChange);
this.props.handleThemeChange(this.state.themeInput, globalChange); this.props.handleThemeChange(this.state.themeInput, globalChange);
this.props.handleColoredEdgesChange(this.state.coloredEdgesInput, globalChange);
this.props.history.push("/"); this.props.history.push("/");
} }
@@ -77,9 +85,11 @@ export default withRouter(class Settings extends Component {
saveSettings={this.saveSettings} saveSettings={this.saveSettings}
handleSoundInputChange={this.handleSoundInputChange} handleSoundInputChange={this.handleSoundInputChange}
handleThemeInputChange={this.handleThemeInputChange} handleThemeInputChange={this.handleThemeInputChange}
handleColoredEdgesInputChange={this.handleColoredEdgesInputChange}
themes={this.props.themes} themes={this.props.themes}
soundInput={this.state.soundInput} soundInput={this.state.soundInput}
themeInput={this.state.themeInput} themeInput={this.state.themeInput}
coloredEdgesInput={this.state.coloredEdgesInput}
/> />
<div className="settings-save-container"> <div className="settings-save-container">

View File

@@ -10,17 +10,27 @@ export default class SettingsContent extends Component {
return ( return (
<> <>
<h1 className="settings-header">Settings</h1> <h1 className="settings-header">Settings</h1>
<label className="settings-sound-container"> <div className="settings-options-container">
<Checkbox <label>
checked={this.props.soundInput} <Checkbox
onChange={this.props.handleSoundInputChange} checked={this.props.soundInput}
inputProps={{ 'aria-label': 'checkbox' }} onChange={this.props.handleSoundInputChange}
/> inputProps={{ 'aria-label': 'checkbox' }}
<span>Sound</span> />
</label> <span>Sound</span>
</label>
<label>
<Checkbox
checked={this.props.coloredEdgesInput}
onChange={this.props.handleColoredEdgesInputChange}
inputProps={{ 'aria-label': 'checkbox' }}
/>
<span>Coloured edges</span>
</label>
</div>
<h2 className="settings-theme-header">Theme</h2> <h2 className="settings-theme-header">Theme</h2>
<div className="settings-themes-container"> <div className="settings-options-container">
{ {
this.props.themes.map((theme) => this.props.themes.map((theme) =>
<Button <Button

View File

@@ -6,7 +6,8 @@ html {
--background-color: #111111; --background-color: #111111;
--background-color-dark: #000000; --background-color-dark: #000000;
--overlay-color: #333333; --overlay-color: #333333;
background-color: var(--background-color);
height: 100%;
color: var(--text-color); color: var(--text-color);
--default: #2a8c8c; --default: #2a8c8c;
@@ -112,10 +113,6 @@ html {
--primary-color-dark: var(--orange-dark); --primary-color-dark: var(--orange-dark);
} }
html {
height: 100%;
}
body { body {
max-width: 1080px; max-width: 1080px;
margin: auto; margin: auto;
@@ -126,6 +123,7 @@ body, #root, #root > div, #root > div > div:first-child {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
background-color: var(--background-color);
} }
main { main {
@@ -409,6 +407,18 @@ label .MuiIconButton-label > input {
opacity: 0 !important; opacity: 0 !important;
} }
.colored-edges {
z-index: -5;
background-color: var(--primary-color-dark);
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
opacity: 0.7;
}
@media screen and (max-width: 420px) { @media screen and (max-width: 420px) {
.progress-history-container > div > *:nth-child(2), .progress-history-container--complete > div > *:nth-last-child(3), .progress-history-container--incomplete > div > *:nth-last-child(4) { .progress-history-container > div > *:nth-child(2), .progress-history-container--complete > div > *:nth-last-child(3), .progress-history-container--incomplete > div > *:nth-last-child(4) {
display: none; display: none;

View File

@@ -1,4 +1,4 @@
.settings-themes-container { .settings-options-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
column-gap: 16px; column-gap: 16px;
@@ -7,7 +7,7 @@
flex-wrap: wrap; flex-wrap: wrap;
} }
.settings-header, .settings-sound-container, .settings-themes-container { .settings-header, .settings-options-container {
margin-bottom: 36px; margin-bottom: 36px;
margin-top: 0; margin-top: 0;
} }

View File

@@ -51,20 +51,20 @@ describe("Parandum Firestore database", () => {
it("Can update current user's user collection", async () => { it("Can update current user's user collection", async () => {
const admin = getAdminFirestore(); const admin = getAdminFirestore();
await admin.collection("users").doc(myId).set({ sound: true }); await admin.collection("users").doc(myId).set({ sound: true, theme: "default", coloredEdges: false });
const db = getFirestore(myAuth); const db = getFirestore(myAuth);
const myTestDoc = db.collection("users").doc(myId); const myTestDoc = db.collection("users").doc(myId);
await firebase.assertSucceeds(myTestDoc.update({ sound: false })); await firebase.assertSucceeds(myTestDoc.update({ sound: false, theme: "pink", coloredEdges: true }));
}); });
it("Can't update current user's user collection with invalid data types", async () => { it("Can't update current user's user collection with invalid data types", async () => {
const admin = getAdminFirestore(); const admin = getAdminFirestore();
await admin.collection("users").doc(myId).set({ sound: true, theme: "default" }); await admin.collection("users").doc(myId).set({ sound: true, theme: "default", coloredEdges: false });
const db = getFirestore(myAuth); const db = getFirestore(myAuth);
const myTestDoc = db.collection("users").doc(myId); const myTestDoc = db.collection("users").doc(myId);
await firebase.assertFails(myTestDoc.update({ sound: 0, theme: 0 })); await firebase.assertFails(myTestDoc.update({ sound: 0, theme: 0, coloredEdges: 0 }));
}); });
it("Can't update current user's user collection with invalid fields", async () => { it("Can't update current user's user collection with invalid fields", async () => {