Skip to content

Commit

Permalink
fix: local user setting change (#4584)
Browse files Browse the repository at this point in the history
  • Loading branch information
Schwehn42 authored Nov 13, 2024
1 parent 77202a0 commit 5b2325c
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 28 deletions.
17 changes: 8 additions & 9 deletions src/components/SettingsDialog/Components/AvatarSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {Avatar, generateRandomProps} from "components/Avatar";
import {Fragment, useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import {useAppDispatch, useAppSelector} from "store";
import {isEqual} from "underscore";
import {AVATAR_CONFIG} from "constants/avatar";
import {AvataaarProps, AvatarGroup} from "types/avatar";
import {editSelf} from "store/features";
Expand All @@ -19,14 +18,9 @@ export interface AvatarSettingsProps {
export const AvatarSettings = (props: AvatarSettingsProps) => {
const dispatch = useAppDispatch();
const {t} = useTranslation();
const state = useAppSelector(
(applicationState) => ({
participant: applicationState.participants!.self!,
}),
isEqual
);
const self = useAppSelector((state) => state.auth.user!);

let initialState = state.participant?.user.avatar;
let initialState = self.avatar;
if (initialState === null || initialState === undefined) {
initialState = generateRandomProps(props.id ?? "");
}
Expand All @@ -46,7 +40,12 @@ export const AvatarSettings = (props: AvatarSettingsProps) => {
};

useEffect(() => {
dispatch(editSelf({...state.participant.user, avatar: properties}));
dispatch(
editSelf({
auth: {...self, avatar: properties},
applyOptimistically: true,
})
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [properties]);

Expand Down
20 changes: 7 additions & 13 deletions src/components/SettingsDialog/ProfileSettings/ProfileSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {useAppDispatch, useAppSelector} from "store";
import {editSelf, setHotkeyState} from "store/features";
import {Info} from "components/Icon";
import {Toggle} from "components/Toggle";
import {isEqual} from "underscore";
import {useOutletContext} from "react-router";
import {MenuItemConfig} from "constants/settings";
import {getColorClassName} from "constants/colors";
Expand All @@ -20,16 +19,11 @@ export const ProfileSettings = () => {

const activeMenuItem: MenuItemConfig = useOutletContext();

const state = useAppSelector(
(applicationState) => ({
participant: applicationState.participants.self!,
hotkeysAreActive: applicationState.view.hotkeysAreActive,
}),
isEqual
);
const self = useAppSelector((state) => state.auth.user!);
const hotkeysAreActive = useAppSelector((state) => state.view.hotkeysAreActive);

const [userName, setUserName] = useState<string>(state.participant?.user.name);
const [id] = useState<string | undefined>(state.participant?.user.id);
const [userName, setUserName] = useState<string>(self.name);
const [id] = useState<string | undefined>(self.id);

return (
<div className={classNames("settings-dialog__container", getColorClassName(activeMenuItem?.color))}>
Expand All @@ -44,7 +38,7 @@ export const ProfileSettings = () => {
value={userName}
maxLength={64}
onChange={(e) => setUserName(e.target.value)}
submit={() => dispatch(editSelf({...state.participant.user, name: userName}))}
submit={() => dispatch(editSelf({auth: {...self, name: userName}, applyOptimistically: true}))}
/>

<AvatarSettings id={id} />
Expand All @@ -53,10 +47,10 @@ export const ProfileSettings = () => {
className="profile-settings__toggle-hotkeys-button"
label={t("Hotkeys.hotkeyToggle")}
onClick={() => {
dispatch(setHotkeyState(!state.hotkeysAreActive));
dispatch(setHotkeyState(!hotkeysAreActive));
}}
>
<Toggle active={state.hotkeysAreActive} />
<Toggle active={hotkeysAreActive} />
</SettingsButton>
<a className="profile-settings__open-cheat-sheet-button" href={`${process.env.PUBLIC_URL}/hotkeys.pdf`} target="_blank" rel="noopener noreferrer">
<p>{t("Hotkeys.cheatSheet")}</p>
Expand Down
2 changes: 1 addition & 1 deletion src/components/SettingsDialog/SettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const SettingsDialog = (props: SettingsDialogProps) => {
const {t} = useTranslation();
const location = useLocation();
const navigate = useNavigate();
const me = useAppSelector((applicationState) => applicationState.participants?.self?.user)!;
const me = useAppSelector((state) => state.auth.user!);
const isBoardModerator = useAppSelector((state) => state.participants?.self?.role === "MODERATOR" || state.participants?.self?.role === "OWNER");

const [activeMenuItem, setActiveMenuItem] = useState<MenuItemConfig>();
Expand Down
3 changes: 3 additions & 0 deletions src/store/features/auth/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ import {Auth} from "./types";
export const signIn = createAction<Auth>("auth/signIn");

export const userCheckCompleted = createAction<boolean>("auth/userCheckCompleted");

// allow changes to user auth without being part of a board
export const editUserOptimistically = createAction<Auth>("auth/editUserOptimistically");
5 changes: 4 additions & 1 deletion src/store/features/auth/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {createReducer} from "@reduxjs/toolkit";
import {AuthState} from "./types";
import {signIn, userCheckCompleted} from "./actions";
import {editUserOptimistically, signIn, userCheckCompleted} from "./actions";
import {signOut} from "./thunks";

const initialState: AuthState = {user: undefined, initializationSucceeded: null};
Expand All @@ -18,4 +18,7 @@ export const authReducer = createReducer(initialState, (builder) =>
.addCase(userCheckCompleted, (state, action) => {
state.initializationSucceeded = action.payload;
})
.addCase(editUserOptimistically, (state, action) => {
state.user = action.payload;
})
);
20 changes: 16 additions & 4 deletions src/store/features/participants/thunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,23 @@ import {API} from "api";
import {ApplicationState, retryable} from "store";
import {Toast} from "utils/Toast";
import i18n from "i18next";
import {Auth} from "../auth";
import {Auth, editUserOptimistically} from "store/features";

export const editSelf = createAsyncThunk<Auth, Auth>("participants/editSelf", async (payload) => {
await API.editUser(payload);
return payload;
export const editSelf = createAsyncThunk<
Auth,
{
auth: Auth;
applyOptimistically?: boolean;
},
{state: ApplicationState}
>("participants/editSelf", async (payload, {dispatch}) => {
if (payload.applyOptimistically) {
// instantly apply changes (required when not in a board, since no event is retrieved)
dispatch(editUserOptimistically(payload.auth));
}

await API.editUser(payload.auth);
return payload.auth;
});

export const changePermission = createAsyncThunk<void, {userId: string; moderator: boolean}, {state: ApplicationState}>(
Expand Down

0 comments on commit 5b2325c

Please sign in to comment.