Skip to content

Commit a451c02

Browse files
migrate all usages of UserDataContext
1 parent 952ce1e commit a451c02

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+411
-310
lines changed

src/components/ButtonGroup.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import classNames from 'classnames';
22
import * as React from 'react';
33

4-
export default function ButtonGroup({
4+
export default function ButtonGroup<T extends string>({
55
options,
66
value,
77
onChange,
88
labelMap,
99
disabled,
1010
}: {
11-
options: string[];
12-
value: string;
13-
onChange: (string) => void;
14-
labelMap?: { [key: string]: string };
11+
options: T[];
12+
value: T | null;
13+
onChange: (newValue: T) => void;
14+
labelMap?: { [key in T]: string };
1515
disabled?: boolean;
1616
}): JSX.Element {
1717
const leftButtonClasses = 'rounded-l-md';

src/components/ContactUsSlideover/ContactUsSlideover.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import * as React from 'react';
22
import { useContext, useEffect, useState } from 'react';
33
import { SECTION_LABELS } from '../../../content/ordering';
44
import MarkdownLayoutContext from '../../context/MarkdownLayoutContext';
5-
import UserDataContext from '../../context/UserDataContext/UserDataContext';
5+
import { useUserLangSetting } from '../../context/UserDataContext/properties/simpleProperties';
6+
import { useFirebaseUser } from '../../context/UserDataContext/UserDataContext';
67
import useContactFormAction from '../../hooks/useContactFormAction';
78
import useStickyState from '../../hooks/useStickyState';
89
import { ModuleInfo } from '../../models/module';
@@ -72,7 +73,6 @@ export default function ContactUsSlideover({
7273
onClose: () => void;
7374
defaultLocation?: string;
7475
}): JSX.Element {
75-
const userSettings = useContext(UserDataContext);
7676
const [name, setName] = useState('');
7777
const [email, setEmail] = useState('');
7878
const [location, setLocation] = useState(defaultLocation);
@@ -92,6 +92,7 @@ export default function ContactUsSlideover({
9292
const [showErrors, setShowErrors] = useState(false);
9393

9494
const markdownContext = useContext(MarkdownLayoutContext);
95+
const userLang = useUserLangSetting();
9596
const submitForm = useContactFormAction();
9697

9798
React.useEffect(() => {
@@ -105,7 +106,7 @@ export default function ContactUsSlideover({
105106
}
106107
}, [markdownContext?.markdownLayoutInfo]);
107108

108-
const { firebaseUser } = useContext(UserDataContext);
109+
const firebaseUser = useFirebaseUser();
109110
useEffect(() => {
110111
if (!firebaseUser) return;
111112
if (email === '') {
@@ -144,7 +145,7 @@ export default function ContactUsSlideover({
144145
email,
145146
moduleName: location,
146147
url: window.location.href,
147-
lang: userSettings.lang,
148+
lang: userLang,
148149
topic,
149150
message,
150151
});

src/components/Dashboard/Activity.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import * as React from 'react';
2-
import { useContext } from 'react';
32
import CalendarHeatmap from 'react-calendar-heatmap';
43
import 'react-calendar-heatmap/dist/styles.css';
5-
import UserDataContext from '../../context/UserDataContext/UserDataContext';
4+
import {
5+
useUserProgressOnModulesActivity,
6+
useUserProgressOnProblemsActivity,
7+
} from '../../context/UserDataContext/properties/userProgress';
68
import './heatmap-styles.css';
79

810
export default function Activity() {
@@ -15,8 +17,8 @@ export default function Activity() {
1517
setStartDate(d);
1618
}, []);
1719

18-
const { userProgressOnModulesActivity, userProgressOnProblemsActivity } =
19-
useContext(UserDataContext);
20+
const userProgressOnModulesActivity = useUserProgressOnModulesActivity();
21+
const userProgressOnProblemsActivity = useUserProgressOnProblemsActivity();
2022

2123
if (!startDate) return null;
2224

src/components/Dashboard/DailyStreak.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { graphql, useStaticQuery } from 'gatsby';
22
import { GatsbyImage } from 'gatsby-plugin-image';
33
import * as React from 'react';
4-
import { useContext, useState } from 'react';
5-
import UserDataContext from '../../context/UserDataContext/UserDataContext';
4+
import { useState } from 'react';
5+
import { useLastVisitInfo } from '../../context/UserDataContext/properties/lastVisit';
66

77
// note: cows will be unlocked in lexicographical order
88

@@ -91,7 +91,7 @@ export default function DailyStreak({ streak }) {
9191
({ node }) => node.childImageSharp.gatsbyImageData
9292
);
9393
}, []);
94-
const { lastVisitDate } = useContext(UserDataContext);
94+
const { lastVisitDate } = useLastVisitInfo();
9595

9696
// we don't want to render streaks during Server-Side Generation
9797
const [firstRender, setFirstRender] = useState(true);

src/components/Dashboard/ModuleLink.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import * as React from 'react';
33
import { useContext } from 'react';
44
import styled, { css } from 'styled-components';
55
import tw from 'twin.macro';
6-
import { LANGUAGE_LABELS } from '../../context/UserDataContext/properties/userLang';
7-
import UserDataContext from '../../context/UserDataContext/UserDataContext';
6+
import { useUserProgressOnModules } from '../../context/UserDataContext/properties/userProgress';
87
import { ModuleLinkInfo } from '../../models/module';
98
import { FrequencyLabels } from '../Frequency';
109
import ModuleFrequencyDots from '../MarkdownLayout/ModuleFrequencyDots';
@@ -168,7 +167,7 @@ function timeAgoString(time): string {
168167
}
169168

170169
const ModuleLink = ({ link }: { link: ModuleLinkInfo }): JSX.Element => {
171-
const { userProgressOnModules } = useContext(UserDataContext);
170+
const userProgressOnModules = useUserProgressOnModules();
172171
const progress = userProgressOnModules[link.id] || 'Not Started';
173172

174173
let lineColorStyle = tw`bg-gray-200`;

src/components/Editor/EditorTopNav.tsx

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
import { InformationCircleIcon } from '@heroicons/react/outline';
22
import classNames from 'classnames';
33
import { useAtomValue, useUpdateAtom } from 'jotai/utils';
4-
import React, { useContext } from 'react';
4+
import React from 'react';
55
import { activeFileAtom, saveFileAtom } from '../../atoms/editor';
66
import { useDarkMode } from '../../context/DarkModeContext';
77
import {
8-
Language,
98
LANGUAGE_LABELS,
10-
} from '../../context/UserDataContext/properties/userLang';
11-
import UserDataContext from '../../context/UserDataContext/UserDataContext';
9+
useSetThemeSetting,
10+
useSetUserLangSetting,
11+
useUserLangSetting,
12+
} from '../../context/UserDataContext/properties/simpleProperties';
1213
import LogoSquare from '../LogoSquare';
1314
import { fetchFileContent } from './editorUtils';
1415

1516
export const EditorTopNav = (): JSX.Element => {
1617
const activeFile = useAtomValue(activeFileAtom);
1718
const saveFile = useUpdateAtom(saveFileAtom);
18-
const userSettings = useContext(UserDataContext);
1919
const isDarkMode = useDarkMode();
20+
const userLang = useUserLangSetting();
21+
const setUserLang = useSetUserLangSetting();
22+
const setTheme = useSetThemeSetting();
2023

2124
const handleReloadContent = async () => {
25+
if (!activeFile) return;
2226
if (confirm('Reload file from Github? Your local changes will be lost.')) {
2327
const data = await fetchFileContent(activeFile.path);
2428
// note: we can't use setMarkdown / setProblems in sequence because setProblems would override setMarkdown
@@ -101,16 +105,16 @@ export const EditorTopNav = (): JSX.Element => {
101105
</div>
102106
<div className="flex items-center">
103107
<nav className="flex space-x-1" aria-label="Tabs">
104-
{['cpp', 'java', 'py'].map((tab: Language) => (
108+
{(['cpp', 'java', 'py'] as const).map(tab => (
105109
<button
106110
key={tab}
107111
className={classNames(
108-
tab === userSettings.lang
112+
tab === userLang
109113
? 'bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300'
110114
: 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300',
111115
'px-3 py-2 font-medium text-sm rounded-md focus:outline-none transition'
112116
)}
113-
onClick={() => userSettings.setLang(tab)}
117+
onClick={() => setUserLang(tab)}
114118
>
115119
{LANGUAGE_LABELS[tab]}
116120
</button>
@@ -132,7 +136,7 @@ export const EditorTopNav = (): JSX.Element => {
132136
<div className="mx-4 block border-l border-gray-200 dark:border-gray-700 h-6 self-center" />
133137

134138
<button
135-
onClick={() => userSettings.setTheme(isDarkMode ? 'light' : 'dark')}
139+
onClick={() => setTheme(isDarkMode ? 'light' : 'dark')}
136140
className="-mx-1 p-1 border-2 border-transparent text-gray-400 dark:text-gray-400 rounded-full hover:text-gray-300 dark:hover:text-dark-high-emphasis focus:outline-none focus:text-gray-500 focus:bg-gray-100 dark:focus:bg-gray-700 transition"
137141
>
138142
{isDarkMode ? (

src/components/Groups/Feedback.tsx

+4-6
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@ import {
77
setDoc,
88
updateDoc,
99
} from 'firebase/firestore';
10-
import React, { useContext, useEffect, useState } from 'react';
10+
import React, { useEffect, useState } from 'react';
1111
import toast from 'react-hot-toast';
12-
import UserDataContext from '../../context/UserDataContext/UserDataContext';
12+
import { useFirebaseUser } from '../../context/UserDataContext/UserDataContext';
1313
import { useFirebaseApp } from '../../hooks/useFirebase';
1414

1515
export default function Feedback({ videoId }): JSX.Element {
1616
const firebaseApp = useFirebaseApp();
1717
const db = getFirestore(firebaseApp);
18-
const {
19-
firebaseUser: { uid },
20-
} = useContext(UserDataContext);
18+
const { uid } = useFirebaseUser()!;
2119
const baseClasses =
2220
'rounded-full border h-8 w-8 text-xl transform transition focus:outline-none';
2321
const unselectedClasses = 'hover:scale-110 border-gray-200';
@@ -64,7 +62,7 @@ export default function Feedback({ videoId }): JSX.Element {
6462
([emoji, key, name]: [
6563
string,
6664
'very_bad' | 'bad' | 'good' | 'great',
67-
string,
65+
string
6866
]) => (
6967
<button
7068
key={key}

src/components/Groups/GroupPage/GroupPageHeader.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Transition } from '@headlessui/react';
22
import { Link, navigate } from 'gatsby';
33
import * as React from 'react';
44
import { useRef, useState } from 'react';
5-
import UserDataContext from '../../../context/UserDataContext/UserDataContext';
5+
import { useFirebaseUser } from '../../../context/UserDataContext/UserDataContext';
66
import { useActiveGroup } from '../../../hooks/groups/useActiveGroup';
77
import { useGroupActions } from '../../../hooks/groups/useGroupActions';
88
import { usePostActions } from '../../../hooks/groups/usePostActions';
@@ -13,7 +13,7 @@ export default function GroupPageHeader(props: { group: GroupData }) {
1313
const { createNewPost } = usePostActions(props.group?.id);
1414
const [isActionsOpen, setIsActionsOpen] = useState(false);
1515
const { showAdminView, setInStudentView } = useActiveGroup();
16-
const { firebaseUser } = React.useContext(UserDataContext);
16+
const firebaseUser = useFirebaseUser();
1717
const ref = useRef<HTMLDivElement>();
1818

1919
React.useEffect(() => {

src/components/Groups/GroupPage/PostExportModal.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ import {
1010
serverTimestamp,
1111
writeBatch,
1212
} from 'firebase/firestore';
13-
import React, { Fragment, useContext, useState } from 'react';
14-
import UserDataContext from '../../../context/UserDataContext/UserDataContext';
13+
import React, { Fragment, useState } from 'react';
14+
import {
15+
useFirebaseUser,
16+
useIsUserDataLoaded,
17+
} from '../../../context/UserDataContext/UserDataContext';
1518
import { useUserGroups } from '../../../hooks/groups/useUserGroups';
1619
import { useFirebaseApp } from '../../../hooks/useFirebase';
1720
import { GroupData } from '../../../models/groups/groups';
@@ -25,7 +28,8 @@ export default function PostExportModal(props: {
2528
group: GroupData;
2629
}) {
2730
const firebaseApp = useFirebaseApp();
28-
const { firebaseUser, isLoaded } = useContext(UserDataContext);
31+
const firebaseUser = useFirebaseUser();
32+
const isLoaded = useIsUserDataLoaded();
2933
const groups = useUserGroups();
3034
const [problems, setProblems] = React.useState<GroupProblemData[]>([]);
3135
const [groupsUsedMap, setGroupsUsedMap] = useState(new Map());

src/components/Groups/GroupSelectPage/AdminViewAllGroups.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import {
44
getDocs,
55
getFirestore,
66
} from '@firebase/firestore';
7-
import React, { useContext, useState } from 'react';
8-
import UserDataContext from '../../../context/UserDataContext/UserDataContext';
7+
import React, { useState } from 'react';
8+
import { useFirebaseUser } from '../../../context/UserDataContext/UserDataContext';
99
import { useFirebaseApp } from '../../../hooks/useFirebase';
1010
import { GroupData } from '../../../models/groups/groups';
1111
import { GroupCard } from './GroupCard';
1212

1313
export default function AdminViewAllGroups(): JSX.Element {
14-
const { firebaseUser } = useContext(UserDataContext);
14+
const firebaseUser = useFirebaseUser();
1515
const [groups, setGroups] = useState<GroupData[] | null>(null);
1616

1717
useFirebaseApp(

src/components/Groups/GroupSelectPage/GroupSelectPage.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { navigate } from 'gatsby';
22
import * as React from 'react';
3-
import { useContext } from 'react';
4-
import UserDataContext from '../../../context/UserDataContext/UserDataContext';
3+
import {
4+
useFirebaseUser,
5+
useIsUserDataLoaded,
6+
} from '../../../context/UserDataContext/UserDataContext';
57
import { useUserPermissions } from '../../../context/UserDataContext/UserPermissionsContext';
68
import { useGroupActions } from '../../../hooks/groups/useGroupActions';
79
import { useUserGroups } from '../../../hooks/groups/useUserGroups';
@@ -12,7 +14,8 @@ import AdminViewAllGroups from './AdminViewAllGroups';
1214
import { GroupCard } from './GroupCard';
1315

1416
const GroupSelectPage = () => {
15-
const { firebaseUser, isLoaded } = useContext(UserDataContext);
17+
const firebaseUser = useFirebaseUser();
18+
const isLoaded = useIsUserDataLoaded();
1619
const groups = useUserGroups();
1720
const { createNewGroup } = useGroupActions();
1821
const permissions = useUserPermissions();

src/components/Groups/JoinGroupPage.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import { RouteComponentProps } from '@reach/router';
22
import { getFunctions, httpsCallable } from 'firebase/functions';
33
import { navigate } from 'gatsby';
44
import * as React from 'react';
5-
import { useContext } from 'react';
65
import { SignInContext } from '../../context/SignInContext';
7-
import UserDataContext from '../../context/UserDataContext/UserDataContext';
6+
import {
7+
useFirebaseUser,
8+
useIsUserDataLoaded,
9+
} from '../../context/UserDataContext/UserDataContext';
810
import { useUserGroups } from '../../hooks/groups/useUserGroups';
911
import { useFirebaseApp } from '../../hooks/useFirebase';
1012
import Layout from '../layout';
@@ -22,7 +24,8 @@ const getQuery = name => {
2224
};
2325

2426
const JoinGroupPage = (props: RouteComponentProps) => {
25-
const { firebaseUser, isLoaded } = useContext(UserDataContext);
27+
const firebaseUser = useFirebaseUser();
28+
const isLoaded = useIsUserDataLoaded();
2629
const { signIn } = React.useContext(SignInContext);
2730
const [groupName, setGroupName] = React.useState<string>(null);
2831
const [error, setError] = React.useState(null);

src/components/Groups/MembersPage/MemberDetail.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { navigate } from 'gatsby-link';
22
import * as React from 'react';
3-
import { useContext } from 'react';
43
import toast from 'react-hot-toast';
5-
import UserDataContext from '../../../context/UserDataContext/UserDataContext';
4+
import { useFirebaseUser } from '../../../context/UserDataContext/UserDataContext';
65
import getPermissionLevel from '../../../functions/src/groups/utils/getPermissionLevel';
76
import { useActiveGroup } from '../../../hooks/groups/useActiveGroup';
87
import { useGroupActions } from '../../../hooks/groups/useGroupActions';
@@ -11,9 +10,7 @@ import { MemberInfo } from '../../../hooks/groups/useMemberInfoForGroup';
1110
export default function MemberDetail({ member }: { member: MemberInfo }) {
1211
const activeGroup = useActiveGroup();
1312
const { removeMemberFromGroup, updateMemberPermissions } = useGroupActions();
14-
const {
15-
firebaseUser: { uid: userId },
16-
} = useContext(UserDataContext);
13+
const { uid: userId } = useFirebaseUser();
1714
const userLeaderboardData = useUserLeaderboardData(
1815
activeGroup.activeGroupId,
1916
member.uid

src/components/Groups/ProblemPage/ProblemSubmissionInterface.tsx

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as React from 'react';
22
import { useReducer } from 'react';
33
import { useDropzone } from 'react-dropzone';
4-
import { LANGUAGE_LABELS } from '../../../context/UserDataContext/properties/userLang';
5-
import UserDataContext from '../../../context/UserDataContext/UserDataContext';
4+
import { useUserLangSetting } from '../../../context/UserDataContext/properties/simpleProperties';
5+
import { useFirebaseUser } from '../../../context/UserDataContext/UserDataContext';
66
import { useActiveGroup } from '../../../hooks/groups/useActiveGroup';
77
import {
88
ProblemSubmissionRequestData,
@@ -32,15 +32,16 @@ export default function ProblemSubmissionInterface({
3232
}: {
3333
problem: GroupProblemData;
3434
}) {
35-
const { lang, firebaseUser } = React.useContext(UserDataContext);
35+
const firebaseUser = useFirebaseUser();
36+
const lang = useUserLangSetting();
3637
const emptySubmission: Partial<ProblemSubmissionRequestData> = {
3738
problemID: problem.id,
3839
sourceCode: '',
3940
language: lang === 'showAll' ? 'cpp' : lang,
4041
};
4142
const [submission, editSubmission] = useReducer(
4243
(
43-
oldSubmission,
44+
oldSubmission: Partial<ProblemSubmissionRequestData>,
4445
updates: Partial<ProblemSubmissionRequestData>
4546
): Partial<ProblemSubmissionRequestData> => ({
4647
...oldSubmission,
@@ -51,7 +52,7 @@ export default function ProblemSubmissionInterface({
5152
const [submissionLink, setSubmissionLink] = React.useState('');
5253
const activeGroup = useActiveGroup();
5354
const { submitSolution, submitSubmissionLink } = usePostActions(
54-
activeGroup.activeGroupId
55+
activeGroup.activeGroupId!
5556
);
5657

5758
const { getRootProps, getInputProps, open, isDragActive } = useDropzone({

0 commit comments

Comments
 (0)