Skip to content

Commit

Permalink
refactor: optimize code of change language
Browse files Browse the repository at this point in the history
  • Loading branch information
mslxl committed Mar 19, 2024
1 parent f0da896 commit de1d1df
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 35 deletions.
3 changes: 0 additions & 3 deletions src/components/cplistener/index.ts

This file was deleted.

14 changes: 14 additions & 0 deletions src/components/cplistener/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Suspense, lazy } from "react"


const Inner = lazy(() => import("./competitive-companion"))
function Wrapper(){
return (
<Suspense>
<Inner/>
</Suspense>
)

}

export default Wrapper
21 changes: 17 additions & 4 deletions src/components/session/SessionContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import { ReactNode } from "react"
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger } from "../ui/context-menu"
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "../ui/context-menu"
import { useSetAtom } from "jotai"
import { deleteSourceAtom, duplicateSourceAtom } from "@/store/source"

interface SessionContextMenuProps {
id: string
children: ReactNode
onChangeLanguage: (id: string) => void
}
export default function SessionContextMenu(props: SessionContextMenuProps) {
const removeSource = useSetAtom(deleteSourceAtom)
const duplicateSource = useSetAtom(duplicateSourceAtom)

return (
<ContextMenu>
<ContextMenuTrigger>{props.children}</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem onClick={() => removeSource(props.id)}>Close</ContextMenuItem>
<ContextMenuSeparator/>
<ContextMenuItem onClick={() => duplicateSource(props.id, (name)=>`${name} - Copy`)}>Duplicate</ContextMenuItem>
<ContextMenuSeparator/>
<ContextMenuSeparator />
<ContextMenuItem onClick={() => duplicateSource(props.id, (name) => `${name} - Copy`)}>
Duplicate
</ContextMenuItem>
<ContextMenuItem onClick={() => props.onChangeLanguage(props.id)}>
Change Language
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem>Reopen with...</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
Expand Down
28 changes: 24 additions & 4 deletions src/components/session/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { useAtom, useAtomValue, useSetAtom } from "jotai"
import { isEmpty } from "lodash/fp"
import { VscClose, VscFile } from "react-icons/vsc"
import SessionContextMenu from "./SessionContextMenu"
import useChangeLanguageDialog from "@/hooks/useChangeLanguageDialog"

import * as log from 'tauri-plugin-log-api'

interface FileItemProps {
id: string
Expand Down Expand Up @@ -40,18 +43,35 @@ export default function SessionPanel(props: SessionPanelProps) {
const sourceIds = useAtomValue(sourceIdsAtom)
const [activedSourceId, setActivedSourceId] = useAtom(activedSourceIdAtom)
const removeSource = useSetAtom(deleteSourceAtom)
const sourceStore = useAtomValue(sourceAtom)

const [dialogChangeLanguage, showChangeLanguageDialog] = useChangeLanguageDialog()


async function changeLanguage(id: string){
const src = sourceStore.get(id)
if(!src) return
const newLanguage = await showChangeLanguageDialog(src.language)
if(newLanguage){
log.info(`change lang of ${id} to ${newLanguage}`)
src.language = newLanguage
}
}

const filesList = sourceIds.map((v) => (
<li key={v}>
<SessionContextMenu id={v}>
<SessionContextMenu id={v} onChangeLanguage={changeLanguage}>
<FileItem id={v} onClick={setActivedSourceId} actived={activedSourceId == v} onRemove={removeSource} />
</SessionContextMenu>
</li>
))

return (
<div className={clsx(props.className, "h-full select-none flex flex-col min-h-0 min-w-0")}>
<ul className="overflow-auto divide-transparent">{filesList}</ul>
</div>
<>
{dialogChangeLanguage}
<div className={clsx(props.className, "h-full select-none flex flex-col min-h-0 min-w-0")}>
<ul className="overflow-auto divide-transparent">{filesList}</ul>
</div>
</>
)
}
48 changes: 38 additions & 10 deletions src/hooks/useChangeLanguageDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,41 @@ import PrefSelect from "@/components/pref/Select"
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { LanguageMode } from "@/lib/ipc"
import { availableLanguageListAtom } from "@/store/setting/setup"
import { availableLanguageListAtom, defaultLanguageAtom } from "@/store/setting/setup"
import { useAtomValue } from "jotai"
import { ReactNode, useState } from "react"
import { ReactNode, useRef, useState } from "react"

export default function useChangeLanguageDialog(value: LanguageMode, onChange:(newValue:LanguageMode)=>void): [ReactNode, () => void, boolean] {
export default function useChangeLanguageDialog(): [
ReactNode,
(value: LanguageMode) => Promise<LanguageMode | undefined>,
] {
const [dialogOpen, setDialogOpen] = useState(false)
const defaultValue = useAtomValue(defaultLanguageAtom)
const [currentValue, setCurrentValue] = useState(defaultValue)
const available = useAtomValue(availableLanguageListAtom)
const resolveCallback = useRef<(value: LanguageMode | undefined) => void>()

function showDialog() {
function showDialog(value: LanguageMode): Promise<LanguageMode | undefined> {
setCurrentValue(value)
setDialogOpen(true)
return new Promise((resolve) => {
resolveCallback.current = resolve
})
}

function applyChange(v: string){
//TODO: narrow type here
onChange(v as any)
function confirm() {
setDialogOpen(false)
if (resolveCallback.current) {
resolveCallback.current(currentValue)
}
resolveCallback.current = undefined
}
function cancel() {
setDialogOpen(false)
if (resolveCallback.current) {
resolveCallback.current(undefined)
}
resolveCallback.current = undefined
}

let element = (
Expand All @@ -26,15 +46,23 @@ export default function useChangeLanguageDialog(value: LanguageMode, onChange:(n
<DialogTitle>Change Language</DialogTitle>
</DialogHeader>
<div className="grid flex-1 gap-2">
<PrefSelect leading="Language" value={value} onChange={applyChange} items={available.state == "hasData" ? available.data : []} />
<PrefSelect
leading="Language"
value={currentValue}
onChange={(v) => setCurrentValue(v as LanguageMode)}
items={available.state == "hasData" ? available.data : []}
/>
<span className="text-end">
<Button className="m-2 bg-green-600 hover:bg-green-500" onClick={() => setDialogOpen(false)}>
<Button className="m-2 bg-green-600 hover:bg-green-500" onClick={confirm}>
Ok
</Button>
<Button className="m-2" onClick={cancel}>
Cancel
</Button>
</span>
</div>
</DialogContent>
</Dialog>
)
return [element, showDialog, dialogOpen]
return [element, showDialog]
}
4 changes: 1 addition & 3 deletions src/pages/Main/event/menu-event.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useMitt } from "@/hooks/useMitt"
import { fromSource } from "@/lib/fs/model"
import { openProblem, saveProblem } from "@/lib/fs/problem"
import { LanguageMode } from "@/lib/ipc"
import { defaultLanguageAtom, defaultMemoryLimitsAtom, defaultTimeLimitsAtom } from "@/store/setting/setup"
import { activedSourceAtom, createSourceAtom, sourceAtom } from "@/store/source"
import { Source, SourceStore } from "@/store/source/model"
Expand Down Expand Up @@ -90,8 +89,7 @@ export default function MenuEventReceiver() {
"fileMenu",
async (event) => {
if (event == "new") {
//TODO: set default language
const src = createSource(LanguageMode.CXX, defaultTimeLimit, defaultMemoryLimit)
const src = createSource(defaultLanguage, defaultTimeLimit, defaultMemoryLimit)
src.name.insert(0, "Unamed")
} else if (event == "open") {
openFile(sourceStore, setSourceMeta)
Expand Down
18 changes: 10 additions & 8 deletions src/pages/Main/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,23 @@ import { useZoom } from "@/hooks/useZoom"
import { motion } from "framer-motion"
import { activedSourceAtom } from "@/store/source"
import SessionPanel from "@/components/session"
import { useNavigate } from "react-router-dom"
import { useEffect } from "react"
import { isCurrentDeviceSetupAtom } from "@/store/setting/setup"

export default function Main() {
useZoom()
// const hostname = useAtomValue(hostnameAtom)
// const setupHostname = useAtomValue(setupDeviceAtom)
// const navgiate = useNavigate()
const navgiate = useNavigate()
const [activePrimaryPanel] = useAtom(primaryPanelShowAtom)
const [showStatusBar] = useAtom(statusBarShowAtom)

// useEffect(() => {
// log.info(`hostname: ${hostname}`)
// log.info(`setupHostname: ${setupHostname}`)
// if (setupHostname != hostname) navgiate("/setup")
// }, [hostname, setupHostname])
const isSetup = useAtomValue(isCurrentDeviceSetupAtom)
useEffect(()=>{
if(!isSetup){
navgiate("/setup")
}

}, [isSetup])
const activedSource = useAtomValue(activedSourceAtom)

const editor = activedSource ? (
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Preference/language.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import PrefSelect from "@/components/pref/Select"
import SetupCXX from "@/components/setup/setup-cxx"
import SetupPy from "@/components/setup/setup-py"
import { LanguageMode } from "@/lib/ipc"
import { availableLanguageListAtom, defaultLanguageAtom } from "@/store/setting/setup"
import { useAtom, useAtomValue } from "jotai"

export default function Page() {
const availableLanguageList = useAtomValue(availableLanguageListAtom)
//TODO: type check here, maybe the best way is to wrap another component?
const [defaultLanguage, setDefaultLanguage] = useAtom(defaultLanguageAtom)
return (
<ul>
Expand All @@ -15,7 +15,7 @@ export default function Page() {
leading="Default Language:"
items={availableLanguageList.state == "hasData" ? availableLanguageList.data : []}
value={defaultLanguage!}
onChange={setDefaultLanguage as any}
onChange={(value) => setDefaultLanguage(value as LanguageMode)}
/>
</li>
<li>
Expand Down
7 changes: 6 additions & 1 deletion src/store/setting/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import { loadable } from "jotai/utils"

export const hostnameAtom = atom(() => getHostname())
export const setupDeviceAtom = atomWithSettings("setup", "")
export const isCurrentDeviceSetupAtom = atom(async(get)=>{
const currentHost = await get(hostnameAtom)
const setupHost = await get(setupDeviceAtom)
return currentHost == setupHost
})

const internalDefaultLanguageAtom = atomWithSettings("setup.language", LanguageMode.CXX)
export const defaultLanguageAtom = atom(async (get)=> {
Expand All @@ -18,7 +23,7 @@ export const defaultLanguageAtom = atom(async (get)=> {

if(lang == LanguageMode.CXX && cxxEnable) return LanguageMode.CXX
if(lang == LanguageMode.PY && pyEnable) return LanguageMode.PY
return null
return LanguageMode.UNKNOW
}, (_get, set, value: LanguageMode)=>{
set(internalDefaultLanguageAtom, value)
})
Expand Down

0 comments on commit de1d1df

Please sign in to comment.