fix: 设置界面不能按 esc 返回

This commit is contained in:
unanmed 2025-09-25 18:42:27 +08:00
parent e666b85ba3
commit 82d58756b7
5 changed files with 61 additions and 19 deletions

View File

@ -33,6 +33,8 @@ export interface ConfirmBoxProps extends DefaultProps, TextContentProps {
color?: CanvasStyle;
/** 对话框边框颜色,当未设置 winskin 时生效 */
border?: CanvasStyle;
/** 按键作用域,如果需要同作用域按键,那么需要传入 */
scope?: symbol;
}
export type ConfirmBoxEmits = {
@ -53,7 +55,8 @@ const confirmBoxProps = {
'winskin',
'defaultYes',
'color',
'border'
'border',
'scope'
],
emits: ['no', 'yes']
} satisfies SetupComponentOptions<
@ -143,7 +146,7 @@ export const ConfirmBox = defineComponent<
noSize.value = [width, height];
};
const [key] = useKey();
const [key] = useKey(false, props.scope);
key.realize('confirm', () => {
if (selected.value) emit('yes');
else emit('no');
@ -242,6 +245,8 @@ export interface ChoicesProps extends DefaultProps, TextContentProps {
interval?: number;
/** 默认选中的选项索引 */
selected?: number;
/** 按键作用域,如果需要同作用域按键,那么需要传入,例如系统设置 UI */
scope?: symbol;
}
export type ChoicesEmits = {
@ -265,7 +270,8 @@ const choicesProps = {
'titleFill',
'pad',
'interval',
'selected'
'selected',
'scope'
],
emits: ['choose']
} satisfies SetupComponentOptions<
@ -464,7 +470,7 @@ export const Choices = defineComponent<
selected.value = 0;
};
const [key] = useKey();
const [key] = useKey(false, props.scope);
key.realize('moveUp', () => {
if (selected.value === 0) {
if (pageCom.value?.now() !== 0) {

View File

@ -25,6 +25,7 @@ import { saveWithExist } from './save';
import { compressToBase64 } from 'lz-string';
import { ViewMapUI } from './viewmap';
import { CENTER_LOC, FULL_LOC, MAIN_HEIGHT, POP_BOX_WIDTH } from '../shared';
import { useKey } from '../use';
export interface MainSettingsProps
extends Partial<ChoicesProps>,
@ -62,6 +63,9 @@ export const MainSettings = defineComponent<MainSettingsProps>(props => {
[MainChoice.Back, '返回游戏']
];
const [key, scope] = useKey();
key.realize('exit', () => props.controller.close(props.instance));
const choose = async (key: ChoiceKey) => {
switch (key) {
case MainChoice.SystemSetting: {
@ -125,6 +129,7 @@ export const MainSettings = defineComponent<MainSettingsProps>(props => {
onChoose={choose}
maxHeight={MAIN_HEIGHT - 64}
interval={8}
scope={scope}
/>
);
}, mainSettingsProps);
@ -150,6 +155,9 @@ export const ReplaySettings = defineComponent<MainSettingsProps>(props => {
[ReplayChoice.Back, '返回游戏']
];
const [key, scope] = useKey();
key.realize('exit', () => props.controller.close(props.instance));
const choose = async (key: ChoiceKey) => {
switch (key) {
case ReplayChoice.Start: {
@ -237,6 +245,7 @@ export const ReplaySettings = defineComponent<MainSettingsProps>(props => {
width={POP_BOX_WIDTH}
onChoose={choose}
interval={8}
scope={scope}
/>
);
}, mainSettingsProps);
@ -260,6 +269,9 @@ export const GameInfo = defineComponent<MainSettingsProps>(props => {
[GameInfoChoice.Back, '返回主菜单']
];
const [key, scope] = useKey();
key.realize('exit', () => props.controller.close(props.instance));
const choose = async (key: ChoiceKey) => {
switch (key) {
case GameInfoChoice.Statistics: {
@ -324,6 +336,7 @@ export const GameInfo = defineComponent<MainSettingsProps>(props => {
width={POP_BOX_WIDTH}
onChoose={choose}
interval={8}
scope={scope}
/>
);
}, mainSettingsProps);
@ -351,6 +364,9 @@ export const SyncSave = defineComponent<MainSettingsProps>(props => {
[SyncSaveChoice.Back, '返回上一级']
];
const [key, scope] = useKey();
key.realize('exit', () => props.controller.close(props.instance));
const choose = async (key: ChoiceKey) => {
switch (key) {
case SyncSaveChoice.ToServer: {
@ -393,6 +409,7 @@ export const SyncSave = defineComponent<MainSettingsProps>(props => {
choices={choices}
onChoose={choose}
interval={8}
scope={scope}
/>
);
}, mainSettingsProps);
@ -404,6 +421,9 @@ export const SyncSaveSelect = defineComponent<MainSettingsProps>(props => {
[SyncSaveChoice.Back, '返回上一级']
];
const [key, scope] = useKey();
key.realize('exit', () => props.controller.close(props.instance));
const choose = async (key: ChoiceKey) => {
switch (key) {
case SyncSaveChoice.AllSaves: {
@ -446,6 +466,7 @@ export const SyncSaveSelect = defineComponent<MainSettingsProps>(props => {
choices={choices}
onChoose={choose}
interval={8}
scope={scope}
/>
);
}, mainSettingsProps);
@ -457,6 +478,9 @@ export const DownloadSaveSelect = defineComponent<MainSettingsProps>(props => {
[SyncSaveChoice.Back, '返回上一级']
];
const [key, scope] = useKey();
key.realize('exit', () => props.controller.close(props.instance));
const choose = async (key: ChoiceKey) => {
switch (key) {
case SyncSaveChoice.AllSaves: {
@ -515,6 +539,7 @@ export const DownloadSaveSelect = defineComponent<MainSettingsProps>(props => {
choices={choices}
onChoose={choose}
interval={8}
scope={scope}
/>
);
}, mainSettingsProps);
@ -526,6 +551,9 @@ export const ClearSaveSelect = defineComponent<MainSettingsProps>(props => {
[SyncSaveChoice.Back, '返回上一级']
];
const [key, scope] = useKey();
key.realize('exit', () => props.controller.close(props.instance));
const choose = async (key: ChoiceKey) => {
switch (key) {
case SyncSaveChoice.AllSaves: {
@ -624,6 +652,7 @@ export const ClearSaveSelect = defineComponent<MainSettingsProps>(props => {
choices={choices}
onChoose={choose}
interval={8}
scope={scope}
/>
);
}, mainSettingsProps);

View File

@ -73,17 +73,22 @@ type KeyUsing = [Hotkey, symbol];
/**
*
* @param noScope
* @param scope `noScope` `true`
*/
export function useKey(noScope: boolean = false): KeyUsing {
export function useKey(noScope: boolean = false, scope?: symbol): KeyUsing {
if (noScope) {
return [gameKey, gameKey.scope];
} else {
const sym = Symbol();
gameKey.use(sym);
onUnmounted(() => {
gameKey.dispose();
});
return [gameKey, sym];
const sym = scope ?? Symbol();
if (sym === gameKey.scope) {
return [gameKey, gameKey.scope];
} else {
gameKey.use(sym);
onUnmounted(() => {
gameKey.dispose();
});
return [gameKey, sym];
}
}
}

View File

@ -34,9 +34,8 @@ export function deleteWith<T>(arr: T[], ele: T): T[] {
export function spliceBy<T>(arr: T[], from: T): T[] {
const index = arr.indexOf(from);
if (index === -1) return arr;
arr.splice(index);
return arr;
if (index === -1) return [];
return arr.splice(index);
}
/**

View File

@ -179,7 +179,8 @@ export class Hotkey extends EventEmitter<HotkeyEvent> {
* @param symbol symbol
*/
use(symbol: symbol): void {
spliceBy(this.scopeStack, symbol);
if (symbol === this.scope) return;
this.dispose(symbol);
this.scopeStack.push(symbol);
this.scope = symbol;
this.conditionMap.set(symbol, () => true);
@ -190,10 +191,12 @@ export class Hotkey extends EventEmitter<HotkeyEvent> {
* @param symbol symbol
*/
dispose(symbol: symbol = this.scopeStack.at(-1) ?? Symbol()): void {
for (const key of Object.values(this.data)) {
key.emits.delete(symbol);
}
spliceBy(this.scopeStack, symbol);
const disposed = spliceBy(this.scopeStack, symbol);
disposed.forEach(v => {
for (const key of Object.values(this.data)) {
key.emits.delete(v);
}
});
this.scope = this.scopeStack.at(-1) ?? Symbol();
}