diff --git a/app/components/Puzzle.tsx b/app/components/Puzzle.tsx
index 344a1e21..9d944920 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 { SolverPreferencesList } from './SolverPreferencesList';
const ModeratingOverlay = dynamic(
() => import('./ModerateOverlay').then((mod) => mod.ModeratingOverlay),
@@ -392,7 +395,7 @@ 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',
@@ -679,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;
}
}
@@ -696,7 +699,6 @@ export const Puzzle = ({
[
dispatch,
loadingPlayState,
- state.currentTimeWindowStart,
state.success,
state.dismissedSuccess,
]
@@ -1030,7 +1032,8 @@ export const Puzzle = ({
),
[state.autocheck, isSlate]
);
-
+
+ const user = props.user;
const moreMenu = useMemo(
() => (
<>
@@ -1038,7 +1041,7 @@ export const Puzzle = ({
icon={isSlate ? : }
text={t`More`}
>
- {() => (
+ {(closeDropdown) => (
<>
{!state.success ? (
) : null}
+ {user !== undefined ? (
+ }
+ text={"Solver Preferences"}
+ >
+ {() =>
+
+ }
+
+ ) : (''
+ )}
}
@@ -1172,7 +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/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 5447c5e5..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;
-}
-
-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,40 +175,10 @@ export const AccountPage = ({ user, constructorPage, prefs }: AuthProps) => {
padding: '0 0',
}}
>
-
-
-
-
-
-
-
-
-
-
-
-
+
Browser-specific Settings
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 };
}