Skip to content

Commit

Permalink
Merge branch 'dev'. Bump to v4.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
joneugster committed Feb 2, 2024
2 parents 36bc52c + ebb8c98 commit 3b660c5
Show file tree
Hide file tree
Showing 22 changed files with 779 additions and 660 deletions.
28 changes: 6 additions & 22 deletions client/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,24 @@ import '@fontsource/roboto/700.css';

import './css/reset.css';
import './css/app.css';
import { MobileContext } from './components/infoview/context';
import { useMobile } from './hooks';
import { AUTO_SWITCH_THRESHOLD, getWindowDimensions} from './state/preferences';
import { PreferencesContext} from './components/infoview/context';
import UsePreferences from "./state/hooks/use_preferences"

export const GameIdContext = React.createContext<string>(undefined);

function App() {
const { mobile, setMobile, lockMobile, setLockMobile } = useMobile();

const params = useParams()
const gameId = "g/" + params.owner + "/" + params.repo

const automaticallyAdjustLayout = () => {
const {width} = getWindowDimensions()
setMobile(width < AUTO_SWITCH_THRESHOLD)
}

React.useEffect(()=>{
if (!lockMobile){
void automaticallyAdjustLayout()
window.addEventListener('resize', automaticallyAdjustLayout)

return () => {
window.removeEventListener('resize', automaticallyAdjustLayout)
}
}
}, [lockMobile])
const {mobile, layout, isSavePreferences, setLayout, setIsSavePreferences} = UsePreferences()

return (
<div className="app">
<GameIdContext.Provider value={gameId}>
<MobileContext.Provider value={{mobile, setMobile, lockMobile, setLockMobile}}>
<Outlet />
</MobileContext.Provider>
<PreferencesContext.Provider value={{mobile, layout, isSavePreferences, setLayout, setIsSavePreferences}}>
<Outlet />
</PreferencesContext.Provider>
</GameIdContext.Provider>
</div>
)
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/app_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { faDownload, faUpload, faEraser, faBook, faBookOpen, faGlobe, faHome,
faArrowRight, faArrowLeft, faXmark, faBars, faCode,
faCircleInfo, faTerminal, faMobileScreenButton, faDesktop, faGear } from '@fortawesome/free-solid-svg-icons'
import { GameIdContext } from "../app"
import { InputModeContext, MobileContext, WorldLevelIdContext } from "./infoview/context"
import { InputModeContext, PreferencesContext, WorldLevelIdContext } from "./infoview/context"
import { GameInfo, useGetGameInfoQuery } from '../state/api'
import { changedOpenedIntro, selectCompleted, selectDifficulty, selectProgress } from '../state/progress'
import { useAppDispatch, useAppSelector } from '../hooks'
Expand Down Expand Up @@ -162,7 +162,7 @@ export function WelcomeAppBar({pageNumber, setPageNumber, gameInfo, toggleImpres
}) {
const gameId = React.useContext(GameIdContext)
const gameProgress = useAppSelector(selectProgress(gameId))
const {mobile, setMobile} = React.useContext(MobileContext)
const {mobile} = React.useContext(PreferencesContext)
const [navOpen, setNavOpen] = React.useState(false)

return <div className="app-bar">
Expand Down Expand Up @@ -212,7 +212,7 @@ export function LevelAppBar({isLoading, levelTitle, toggleImpressum, pageNumber=
}) {
const gameId = React.useContext(GameIdContext)
const {worldId, levelId} = React.useContext(WorldLevelIdContext)
const {mobile} = React.useContext(MobileContext)
const {mobile} = React.useContext(PreferencesContext)
const [navOpen, setNavOpen] = React.useState(false)
const gameInfo = useGetGameInfoQuery({game: gameId})
const completed = useAppSelector(selectCompleted(gameId, worldId, levelId))
Expand Down
19 changes: 10 additions & 9 deletions client/src/components/infoview/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as React from 'react';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
import { InteractiveDiagnostic, InteractiveTermGoal } from '@leanprover/infoview-api';
import { GameHint, InteractiveGoal, InteractiveGoals } from './rpc_api';
import { PreferencesState } from '../../state/preferences';

export const MonacoEditorContext = React.createContext<monaco.editor.IStandaloneCodeEditor>(
null as any)
Expand Down Expand Up @@ -62,18 +63,18 @@ export const ProofStateContext = React.createContext<{
setProofState: () => {},
})

export interface IMobileContext {
mobile : boolean,
setMobile: React.Dispatch<React.SetStateAction<Boolean>>,
lockMobile: boolean,
setLockMobile: React.Dispatch<React.SetStateAction<Boolean>>,
export interface IPreferencesContext extends PreferencesState{
mobile: boolean, // The variables that actually control the page 'layout' can only be changed through layout.
setLayout: React.Dispatch<React.SetStateAction<PreferencesState["layout"]>>;
setIsSavePreferences: React.Dispatch<React.SetStateAction<Boolean>>;
}

export const MobileContext = React.createContext<IMobileContext>({
export const PreferencesContext = React.createContext<IPreferencesContext>({
mobile: false,
setMobile: () => {},
lockMobile: false,
setLockMobile: () => {}
layout: "auto",
isSavePreferences: false,
setLayout: () => {},
setIsSavePreferences: () => {}
})

export const WorldLevelIdContext = React.createContext<{
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/infoview/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import Markdown from '../markdown';
import { Infos } from './infos';
import { AllMessages, Errors, WithLspDiagnosticsContext } from './messages';
import { Goal } from './goals';
import { DeletedChatContext, InputModeContext, MobileContext, MonacoEditorContext, ProofContext, ProofStep, SelectionContext, WorldLevelIdContext } from './context';
import { DeletedChatContext, InputModeContext, PreferencesContext, MonacoEditorContext, ProofContext, ProofStep, SelectionContext, WorldLevelIdContext } from './context';
import { Typewriter, hasErrors, hasInteractiveErrors } from './typewriter';
import { InteractiveDiagnostic } from '@leanprover/infoview/*';
import { Button } from '../button';
Expand Down Expand Up @@ -349,7 +349,7 @@ export function TypewriterInterface({props}) {
const [disableInput, setDisableInput] = React.useState<boolean>(false)
const [loadingProgress, setLoadingProgress] = React.useState<number>(0)
const { setDeletedChat, showHelp, setShowHelp } = React.useContext(DeletedChatContext)
const {mobile} = React.useContext(MobileContext)
const {mobile} = React.useContext(PreferencesContext)
const { proof } = React.useContext(ProofContext)
const { setTypewriterInput } = React.useContext(InputModeContext)
const { selectedStep, setSelectedStep } = React.useContext(SelectionContext)
Expand Down
10 changes: 5 additions & 5 deletions client/src/components/level.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { Button } from './button'
import Markdown from './markdown'
import {InventoryPanel} from './inventory'
import { hasInteractiveErrors } from './infoview/typewriter'
import { DeletedChatContext, InputModeContext, MobileContext, MonacoEditorContext,
import { DeletedChatContext, InputModeContext, PreferencesContext, MonacoEditorContext,
ProofContext, ProofStep, SelectionContext, WorldLevelIdContext } from './infoview/context'
import { DualEditor } from './infoview/main'
import { GameHint } from './infoview/rpc_api'
Expand Down Expand Up @@ -74,7 +74,7 @@ function Level() {

function ChatPanel({lastLevel}) {
const chatRef = useRef<HTMLDivElement>(null)
const {mobile} = useContext(MobileContext)
const {mobile} = useContext(PreferencesContext)
const gameId = useContext(GameIdContext)
const {worldId, levelId} = useContext(WorldLevelIdContext)
const level = useLoadLevelQuery({game: gameId, world: worldId, level: levelId})
Expand Down Expand Up @@ -215,7 +215,7 @@ function PlayableLevel({impressum, setImpressum}) {
const codeviewRef = useRef<HTMLDivElement>(null)
const gameId = React.useContext(GameIdContext)
const {worldId, levelId} = useContext(WorldLevelIdContext)
const {mobile} = React.useContext(MobileContext)
const {mobile} = React.useContext(PreferencesContext)

const dispatch = useAppDispatch()

Expand Down Expand Up @@ -441,7 +441,7 @@ function PlayableLevel({impressum, setImpressum}) {
function IntroductionPanel({gameInfo}) {
const gameId = React.useContext(GameIdContext)
const {worldId} = useContext(WorldLevelIdContext)
const {mobile} = React.useContext(MobileContext)
const {mobile} = React.useContext(PreferencesContext)

let text: Array<string> = gameInfo.data?.worlds.nodes[worldId].introduction.split(/\n(\s*\n)+/)

Expand All @@ -468,7 +468,7 @@ export default Level
/** The site with the introduction text of a world */
function Introduction({impressum, setImpressum}) {
const gameId = React.useContext(GameIdContext)
const {mobile} = useContext(MobileContext)
const {mobile} = useContext(PreferencesContext)

const inventory = useLoadInventoryOverviewQuery({game: gameId})

Expand Down
81 changes: 58 additions & 23 deletions client/src/components/popup/preferences.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,86 @@
import * as React from 'react'
import { Input, Typography } from '@mui/material'
import Markdown from '../markdown'
import Switch from '@mui/material/Switch';
import { Switch, Button, ButtonGroup } from '@mui/material';
import Box from '@mui/material/Box';
import Slider from '@mui/material/Slider';

import FormControlLabel from '@mui/material/FormControlLabel';

import { IMobileContext } from "../infoview/context"
import { IPreferencesContext } from "../infoview/context"

interface PreferencesPopupProps extends IMobileContext{
interface PreferencesPopupProps extends Omit<IPreferencesContext, 'mobile'> {
handleClose: () => void
}
}

export function PreferencesPopup({ layout, setLayout, isSavePreferences, setIsSavePreferences, handleClose }: PreferencesPopupProps) {

const marks = [
{
value: 0,
label: 'Mobile',
key: "mobile"
},
{
value: 1,
label: 'Auto',
key: "auto"
},
{
value: 2,
label: 'Desktop',
key: "desktop"
},
];

const handlerChangeLayout = (_: Event, value: number) => {
setLayout(marks[value].key as IPreferencesContext["layout"])
}

export function PreferencesPopup({ mobile, setMobile, lockMobile, setLockMobile, handleClose }: PreferencesPopupProps) {
return <div className="modal-wrapper">
<div className="modal-backdrop" onClick={handleClose} />
<div className="modal">
<div className="codicon codicon-close modal-close" onClick={handleClose}></div>
<Typography variant="body1" component="div" className="settings">
<div className='preferences-category'>
<div className='category-title'>
<h3>Mobile layout</h3>
<h3>Layout</h3>
</div>
<div className='preferences-item'>
<div className='preferences-item first leave-left-gap'>
<FormControlLabel
control={
<Switch
checked={mobile}
onChange={() => setMobile(!mobile)}
name="checked"
color="primary"
/>
<Box sx={{ width: 300 }}>
<Slider
aria-label="Always visible"
value={marks.find(item => item.key === layout).value}
step={1}
marks={marks}
max={2}
sx={{
'& .MuiSlider-track': { display: 'none', },
}}
onChange={handlerChangeLayout}
/>
</Box>
}
label="Enable"
labelPlacement="start"
label=""
/>
</div>
</div>

<div className='preferences-category tail-category'>
<div className='preferences-item'>
<FormControlLabel
control={
<Switch
checked={!lockMobile}
onChange={() => setLockMobile(!lockMobile)}
name="checked"
color="primary"
/>
<Switch
checked={isSavePreferences}
onChange={() => setIsSavePreferences(!isSavePreferences)}
name="checked"
color="primary"
/>
}
label="Auto"
labelPlacement="start"
label="Save my settings (in the browser store)"
labelPlacement="end"
/>
</div>
</div>
Expand Down
10 changes: 6 additions & 4 deletions client/src/components/welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useAppDispatch, useAppSelector } from '../hooks'
import { changedOpenedIntro, selectOpenedIntro } from '../state/progress'
import { useGetGameInfoQuery, useLoadInventoryOverviewQuery } from '../state/api'
import { Button } from './button'
import { MobileContext } from './infoview/context'
import { PreferencesContext } from './infoview/context'
import { InventoryPanel } from './inventory'
import { ErasePopup } from './popup/erase'
import { InfoPopup } from './popup/game_info'
Expand All @@ -27,7 +27,7 @@ import { Hint } from './hints'

/** the panel showing the game's introduction text */
function IntroductionPanel({introduction, setPageNumber}: {introduction: string, setPageNumber}) {
const {mobile} = React.useContext(MobileContext)
const {mobile} = React.useContext(PreferencesContext)
const gameId = React.useContext(GameIdContext)
const dispatch = useAppDispatch()

Expand Down Expand Up @@ -64,7 +64,9 @@ function IntroductionPanel({introduction, setPageNumber}: {introduction: string,
/** main page of the game showing among others the tree of worlds/levels */
function Welcome() {
const gameId = React.useContext(GameIdContext)
const {mobile, setMobile, lockMobile, setLockMobile} = React.useContext(MobileContext)
const {mobile} = React.useContext(PreferencesContext)
const {layout, isSavePreferences, setLayout, setIsSavePreferences} = React.useContext(PreferencesContext)

const gameInfo = useGetGameInfoQuery({game: gameId})
const inventory = useLoadInventoryOverviewQuery({game: gameId})

Expand Down Expand Up @@ -134,7 +136,7 @@ function Welcome() {
{eraseMenu? <ErasePopup handleClose={closeEraseMenu}/> : null}
{uploadMenu? <UploadPopup handleClose={closeUploadMenu}/> : null}
{info ? <InfoPopup info={gameInfo.data?.info} handleClose={closeInfo}/> : null}
{preferencesPopup ? <PreferencesPopup mobile={mobile} setMobile={setMobile} lockMobile={lockMobile} setLockMobile={setLockMobile} handleClose={closePreferencesPopup}/> : null}
{preferencesPopup ? <PreferencesPopup layout={layout} isSavePreferences={isSavePreferences} setLayout={setLayout} setIsSavePreferences={setIsSavePreferences} handleClose={closePreferencesPopup}/> : null}
</>
}

Expand Down
5 changes: 3 additions & 2 deletions client/src/components/world_tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faXmark, faCircleQuestion } from '@fortawesome/free-solid-svg-icons'

import { GameIdContext } from '../app'
import { useAppDispatch, useMobile } from '../hooks'
import { useAppDispatch } from '../hooks'
import { selectDifficulty, changedDifficulty, selectCompleted } from '../state/progress'
import { store } from '../state/store'

import '../css/world_tree.css'
import { PreferencesContext } from './infoview/context'

// Settings for the world tree
cytoscape.use( klay )
Expand Down Expand Up @@ -197,7 +198,7 @@ export function WorldSelectionMenu({rulesHelp, setRulesHelp}) {
const gameId = React.useContext(GameIdContext)
const difficulty = useSelector(selectDifficulty(gameId))
const dispatch = useAppDispatch()
const { mobile } = useMobile()
const { mobile } = React.useContext(PreferencesContext)


function label(x : number) {
Expand Down
12 changes: 12 additions & 0 deletions client/src/css/welcome.css
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,15 @@ h5, h6 {
margin-left: 0.3rem;
margin-right: 0.3rem;
}

.preferences-category.tail-category{
margin-top: 2em;
}

.preferences-item.first{
margin-top: 1em;
}

.preferences-item.leave-left-gap{
margin-left: 3em;
}
24 changes: 0 additions & 24 deletions client/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,6 @@
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './state/store'

import { setMobile as setMobileState, setLockMobile as setLockMobileState} from "./state/preferences"

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

export const useMobile = () => {
const dispatch = useAppDispatch();

const mobile = useAppSelector((state) => state.preferences.mobile);
const lockMobile = useAppSelector((state) => state.preferences.lockMobile);

const setMobile = (val: boolean) => {
dispatch(setMobileState(val));
};

const setLockMobile = (val: boolean) => {
dispatch(setLockMobileState(val));
};

return {
mobile,
setMobile,
lockMobile,
setLockMobile,
};
};
Loading

0 comments on commit 3b660c5

Please sign in to comment.