debug: routine이 두번 생성되는 버그를 해결

- 한국어 입력의 경우 isComposing 속성으로 인해서 enter 이벤트가 두번 발생해서 routine 생성 이벤트가 2번 발생함
This commit is contained in:
sechan100 2025-02-26 13:34:18 +09:00
parent e3b567538a
commit 04a04b71bf
5 changed files with 54 additions and 15 deletions

View file

@ -8,8 +8,9 @@ import { RoutineGroupEntity } from "../domain/routine-group";
const parse = async (file: TFile): Promise<RoutineGroup> => {
const fm = await fileAccessor.loadFrontMatter(file);
const name = file.basename.startsWith(GROUP_PREFIX) ? file.basename.slice(GROUP_PREFIX.length) : file.basename;
const properties = RoutineGroupEntity.validateGroupProperties(fileAccessor.loadFrontMatter(file));
const properties = RoutineGroupEntity.validateGroupProperties(fm);
if(properties.isErr()) throw new Error(`[RoutineGroup '${name}' Parse Error] ${properties.error}`);
return {

View file

@ -8,8 +8,16 @@ import dedent from "dedent";
import { Routine } from "../domain/routine-type";
/**
* File을 Routine .
*
* .
* @param file
* @returns
*/
const parse = async (file: TFile): Promise<Routine> => {
const result = RoutineEntity.validateRoutineProperties(fileAccessor.loadFrontMatter(file));
const fm = await fileAccessor.loadFrontMatter(file);
const result = RoutineEntity.validateRoutineProperties(fm);
if(result.isErr()){
new Notice(`Routine '${file.basename}' frontmatter error: ${result.error}`);
throw new Error(`[Routine '${file.basename}' Parse Error] ${result.error}`);
@ -32,7 +40,7 @@ export interface RoutineQuery {
load(routineName: string): Promise<Routine>;
}
export interface RoutineRepository extends RoutineQuery {
persist(entity: Routine): Promise<boolean>;
create(entity: Routine): Promise<boolean>;
delete(routineName: string): Promise<void>;
changeName(originalName: string, newName: string): Promise<void>;
update(routine: Routine): Promise<Routine>;
@ -62,7 +70,7 @@ export const routineRepository: RoutineRepository = {
return await parse(file);
},
async persist(routine: Routine){
async create(routine: Routine){
const path = ROUTINE_PATH(routine.name);
const file = fileAccessor.loadFile(path);
if(!file){

View file

@ -8,6 +8,7 @@ import { useCallback, useEffect, useMemo } from 'react';
import { ModalApi } from './create-modal';
import { TextEditComponent } from "@shared/components/TextEditComponent"
import { Button } from "@shared/components/Button"
import { plugin } from "@shared/utils/plugin-service-locator";
type ModalProps = {
@ -173,14 +174,22 @@ export const SaveBtn = ({
name,
}: SaveBtnProps) => {
const handleEnterKeyDown = useCallback((e: KeyboardEvent) => {
if(e.key === "Enter" && !disabled) onSaveBtnClick?.();
}, [disabled, onSaveBtnClick]);
/**
* Enter Key로 Save Button을
*/
useEffect(() => {
const handleEnterKeyDown = ({ key, isComposing}: KeyboardEvent) => {
if(isComposing) return;
if(key === "Enter" && !disabled){
onSaveBtnClick?.();
}
}
document.addEventListener('keydown', handleEnterKeyDown);
return () => document.removeEventListener('keydown', handleEnterKeyDown);
}, [handleEnterKeyDown]);
}, [disabled, onSaveBtnClick]);
return (
<div css={{

View file

@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { plugin } from "@shared/utils/plugin-service-locator";
import { TFile, TFolder } from "obsidian";
import { TFile, TFolder, getFrontMatterInfo, parseYaml } from "obsidian";
export interface FileAccessor {
@ -58,7 +57,7 @@ export interface FileAccessor {
*/
writeFrontMatter: (file: TFile, frontMatterModifier: (frontmatter: any) => any) => Promise<void>;
loadFrontMatter: (file: TFile) => object | null;
loadFrontMatter: (file: TFile) => Promise<object>;
}
export const fileAccessor: FileAccessor = {
@ -116,8 +115,30 @@ export const fileAccessor: FileAccessor = {
});
},
loadFrontMatter: (file: TFile) => {
/**
* 1 metadataCache에서 frontmatter를 ,
* frontmatter를 .
* .
* @param file
* @returns
*/
loadFrontMatter: async (file: TFile): Promise<object> => {
const metadataCache = plugin().app.metadataCache.getFileCache(file);
return metadataCache?.frontmatter ?? null;
if(metadataCache && metadataCache.frontmatter){
return metadataCache.frontmatter;
} else {
const content = await fileAccessor.readFileAsReadonly(file);
return parseFrontmatterFromContent(content);
}
}
}
export const parseFrontmatterFromContent = (fileContent: string): object => {
const fmInfo = getFrontMatterInfo(fileContent);
if(!fmInfo.exists){
return {};
}
const yaml = fmInfo.frontmatter.replace('---', '').trim()
return parseYaml(yaml);
}

View file

@ -21,7 +21,7 @@ export const useStartRoutineModal = createModal(({ modal }: StartRoutineModalPro
const [routine, dispatch] = useReducer<RoutineReducer>(routineReducer, createNewRoutine());
const onSaveBtnClick = useCallback(async () => {
await routineRepository.persist(routine);
await routineRepository.create(routine);
mergeNotes();
modal.close();
new Notice(`Routine '${routine.name}' started! 🎉`);