From 1b128a5ffd7ca443564b6a68d4d57447726b271a Mon Sep 17 00:00:00 2001 From: adamthedog Date: Wed, 31 Jan 2024 19:29:58 -0500 Subject: [PATCH 1/4] Copy solving preferences to solver more menu --- app/components/Puzzle.tsx | 61 ++++++++++++++++++++++++++++++++++++++- app/pages/account.tsx | 2 +- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/app/components/Puzzle.tsx b/app/components/Puzzle.tsx index 344a1e21..2e54f15c 100644 --- a/app/components/Puzzle.tsx +++ b/app/components/Puzzle.tsx @@ -30,6 +30,7 @@ import { FaEdit, FaRegFile, FaMoon, + FaCog, } from 'react-icons/fa'; import { ClueText } from './ClueText'; import { IoMdStats } from 'react-icons/io'; @@ -91,6 +92,7 @@ import { TopBarDropDownLinkA, TopBarDropDown, TopBarDropDownLinkSimpleA, + NestedDropDown, } from './TopBar'; import { SLATE_PADDING_LARGE, @@ -148,6 +150,7 @@ import { SlateColorTheme } from './SlateColorTheme'; import { Check, Clues, Grid, More, Pause, Reveal, Timer } from './SlateIcons'; import { removeSpoilers } from '../lib/markdown/markdown'; import { SlateBegin, SlatePause, SlateSuccess } from './SlateOverlays'; +import { PrefSetting } from '../pages/account'; const ModeratingOverlay = dynamic( () => import('./ModerateOverlay').then((mod) => mod.ModeratingOverlay), @@ -1038,7 +1041,7 @@ export const Puzzle = ({ icon={isSlate ? : } text={t`More`} > - {() => ( + {(closeDropdown) => ( <> {!state.success ? ( ) : null} + {props.user ? ( + } + text={"Solver Preferences"} + > + {() => +
    { + e.stopPropagation(); + }} + > +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • + +
+ } +
+ ) : ('' + )} } @@ -1173,6 +1231,7 @@ export const Puzzle = ({ muted, props.isAdmin, props.user?.uid, + props.prefs, puzzle, setMuted, state.success, diff --git a/app/pages/account.tsx b/app/pages/account.tsx index 5447c5e5..cd5bac14 100644 --- a/app/pages/account.tsx +++ b/app/pages/account.tsx @@ -89,7 +89,7 @@ interface PrefSettingProps { invert?: boolean; } -const PrefSetting = (props: PrefSettingProps) => { +export const PrefSetting = (props: PrefSettingProps) => { const { showSnackbar } = useSnackbar(); const prefSet = props.prefs?.[props.flag] ?? false; return ( From b2e0179611eecbcfcc039065d76f93b4b875ffee Mon Sep 17 00:00:00 2001 From: adamthedog Date: Wed, 31 Jan 2024 20:09:54 -0500 Subject: [PATCH 2/4] Add a pref for pausing on losing page focus (Closes #389) --- app/components/Puzzle.tsx | 13 +++++++++++-- app/lib/prefs.ts | 1 + app/pages/account.tsx | 9 +++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/components/Puzzle.tsx b/app/components/Puzzle.tsx index 2e54f15c..bce1ab8d 100644 --- a/app/components/Puzzle.tsx +++ b/app/components/Puzzle.tsx @@ -395,7 +395,8 @@ export const Puzzle = ({ // Pause when page goes out of focus function prodPause() { - if (process.env.NODE_ENV !== 'development') { + if (process.env.NODE_ENV !== 'development' && !props.prefs?.dontPauseOnLostFocus) { + window.parent.postMessage( { type: 'pause', @@ -1204,7 +1205,15 @@ export const Puzzle = ({ text="Start puzzles in downs-only mode" /> - +
  • + +
  • } diff --git a/app/lib/prefs.ts b/app/lib/prefs.ts index 9f5fe573..3513b54b 100644 --- a/app/lib/prefs.ts +++ b/app/lib/prefs.ts @@ -14,6 +14,7 @@ const AccountPrefsFlagsV = t.partial({ dontAdvanceWordAfterCompletion: t.boolean, solveDownsOnly: t.boolean, disableCommentsByDefault: t.boolean, + dontPauseOnLostFocus: t.boolean }); export type AccountPrefsFlagsT = t.TypeOf; diff --git a/app/pages/account.tsx b/app/pages/account.tsx index cd5bac14..4012084d 100644 --- a/app/pages/account.tsx +++ b/app/pages/account.tsx @@ -243,6 +243,15 @@ export const AccountPage = ({ user, constructorPage, prefs }: AuthProps) => { text="Start puzzles in downs-only mode" /> +
  • + +

  • Browser-specific Settings

    From fcf1116093793c2e6c48a42aedc1d1a234876d3d Mon Sep 17 00:00:00 2001 From: adamthedog Date: Thu, 1 Feb 2024 13:54:55 -0500 Subject: [PATCH 3/4] Added ability to unpause with Esc --- app/components/Puzzle.tsx | 5 ++--- app/reducers/reducer.ts | 13 +++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/components/Puzzle.tsx b/app/components/Puzzle.tsx index bce1ab8d..f7917b14 100644 --- a/app/components/Puzzle.tsx +++ b/app/components/Puzzle.tsx @@ -396,7 +396,6 @@ export const Puzzle = ({ // Pause when page goes out of focus function prodPause() { if (process.env.NODE_ENV !== 'development' && !props.prefs?.dontPauseOnLostFocus) { - window.parent.postMessage( { type: 'pause', @@ -683,9 +682,9 @@ export const Puzzle = ({ const physicalKeyboardHandler = useCallback( (e: KeyboardEvent) => { - // Disable keyboard when paused / loading play + // Disable keyboard when loading play if (!(state.success && state.dismissedSuccess)) { - if (loadingPlayState || !state.currentTimeWindowStart) { + if (loadingPlayState) { return; } } diff --git a/app/reducers/reducer.ts b/app/reducers/reducer.ts index 72496507..fe9d574e 100644 --- a/app/reducers/reducer.ts +++ b/app/reducers/reducer.ts @@ -814,6 +814,19 @@ export function gridInterfaceReducer( } if (isKeypressAction(action)) { const key = action.key; + // Resume on Esc, but only during midgame pause + if (isPuzzleState(state) && !state.currentTimeWindowStart) { + if (state.bankedSeconds === 0) { + return state; + } + if (key.k === KeyK.Escape) { + return { + ...state, + currentTimeWindowStart: new Date().getTime() + } + } + return state; + } if (key.k === KeyK.NumLayout || key.k === KeyK.AbcLayout) { return { ...state, showExtraKeyLayout: !state.showExtraKeyLayout }; } From 6d79523d8b153d3624057163ad7b81b3205490ac Mon Sep 17 00:00:00 2001 From: adamthedog Date: Thu, 1 Feb 2024 18:38:26 -0500 Subject: [PATCH 4/4] Address lints, extract list of PrefSettings to a SolverPreferencesList component --- app/components/Puzzle.tsx | 64 +++------------- app/components/SolverPreferencesList.tsx | 95 ++++++++++++++++++++++++ app/pages/account.tsx | 83 ++------------------- 3 files changed, 112 insertions(+), 130 deletions(-) create mode 100644 app/components/SolverPreferencesList.tsx diff --git a/app/components/Puzzle.tsx b/app/components/Puzzle.tsx index f7917b14..9d944920 100644 --- a/app/components/Puzzle.tsx +++ b/app/components/Puzzle.tsx @@ -150,7 +150,7 @@ import { SlateColorTheme } from './SlateColorTheme'; import { Check, Clues, Grid, More, Pause, Reveal, Timer } from './SlateIcons'; import { removeSpoilers } from '../lib/markdown/markdown'; import { SlateBegin, SlatePause, SlateSuccess } from './SlateOverlays'; -import { PrefSetting } from '../pages/account'; +import { SolverPreferencesList } from './SolverPreferencesList'; const ModeratingOverlay = dynamic( () => import('./ModerateOverlay').then((mod) => mod.ModeratingOverlay), @@ -699,7 +699,6 @@ export const Puzzle = ({ [ dispatch, loadingPlayState, - state.currentTimeWindowStart, state.success, state.dismissedSuccess, ] @@ -1033,7 +1032,8 @@ export const Puzzle = ({ ), [state.autocheck, isSlate] ); - + + const user = props.user; const moreMenu = useMemo( () => ( <> @@ -1155,64 +1155,23 @@ export const Puzzle = ({ }} /> ) : null} - {props.user ? ( + {user !== undefined ? ( } text={"Solver Preferences"} > {() => -
      { - e.stopPropagation(); - }} > -
    • - -
    • -
    • - -
    • -
    • - -
    • -
    • - -
    • -
    • - -
    • +
    }
    @@ -1238,8 +1197,9 @@ export const Puzzle = ({ [ muted, props.isAdmin, - props.user?.uid, + props.user, props.prefs, + user, puzzle, setMuted, state.success, diff --git a/app/components/SolverPreferencesList.tsx b/app/components/SolverPreferencesList.tsx new file mode 100644 index 00000000..bf303435 --- /dev/null +++ b/app/components/SolverPreferencesList.tsx @@ -0,0 +1,95 @@ +import { setDoc } from "firebase/firestore"; +import { AccountPrefsFlagsT, AccountPrefsT } from "../lib/prefs"; +import { logAsyncErrors } from "../lib/utils"; +import { useSnackbar } from "./Snackbar"; +import { getDocRef } from "../lib/firebaseWrapper"; + +interface PrefSettingProps { + prefs: AccountPrefsT | undefined; + userId: string; + flag: keyof AccountPrefsFlagsT; + text: string; + invert?: boolean; +} + +export const PrefSetting = (props: PrefSettingProps) => { + const { showSnackbar } = useSnackbar(); + const prefSet = props.prefs?.[props.flag] ?? false; + return ( + +); +}; + +export const SolverPreferencesList = ({prefs, userId}: {prefs?: AccountPrefsT, userId: string}) => { + if (!prefs) { + return null; // or some default content + } + return ( + <> +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • + + ); +}; \ No newline at end of file diff --git a/app/pages/account.tsx b/app/pages/account.tsx index 4012084d..6d58edf2 100644 --- a/app/pages/account.tsx +++ b/app/pages/account.tsx @@ -12,7 +12,6 @@ import { PROFILE_PIC, COVER_PIC } from '../lib/style'; import { UnsubscribeFlags, AccountPrefsT, - AccountPrefsFlagsT, } from '../lib/prefs'; import dynamic from 'next/dynamic'; @@ -36,6 +35,7 @@ import { import { signOut } from 'firebase/auth'; import { BioEditor } from '../components/BioEditor'; import { logAsyncErrors } from '../lib/utils'; +import { PrefSetting, SolverPreferencesList } from '../components/SolverPreferencesList'; export const getStaticProps = withStaticTranslation(() => { return { props: {} }; @@ -81,40 +81,6 @@ const UnsubSetting = (props: UnsubSettingProps) => { ); }; -interface PrefSettingProps { - prefs: AccountPrefsT | undefined; - userId: string; - flag: keyof AccountPrefsFlagsT; - text: string; - invert?: boolean; -} - -export const PrefSetting = (props: PrefSettingProps) => { - const { showSnackbar } = useSnackbar(); - const prefSet = props.prefs?.[props.flag] ?? false; - return ( - - ); -}; - export const AccountPage = ({ user, constructorPage, prefs }: AuthProps) => { const [settingProfilePic, setSettingProfilePic] = useState(false); const [settingCoverPic, setSettingCoverPic] = useState(false); @@ -209,49 +175,10 @@ export const AccountPage = ({ user, constructorPage, prefs }: AuthProps) => { padding: '0 0', }} > -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • +

    Browser-specific Settings