mirror of
https://github.com/sechan100/daily-routine-2.git
synced 2026-07-22 05:37:51 +00:00
various feat, fix, debug
- task가 없을 때 보이는 note 화면을 제작 - note folder가 존재하지 않는 경우 자동으로 생성 - task, group이 없을 때 에러가 나던 현상을 해결 - group에 task가 없을 때, 완료로 표시되던 것을 해결 - 다양한 modal 창에서 enter를 누르면 save되도록 단축키 추가 - activate-view 함수에서 바로 leaf가 튀어나오지 않도록 수정 - open routine view command 추가 - .env 파일을 사용하여 환경 변수를 받을 수 있도록 추가가
This commit is contained in:
parent
0f86b2dd62
commit
a574beef46
12 changed files with 89 additions and 35 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -5,6 +5,9 @@
|
|||
*.iml
|
||||
.idea
|
||||
|
||||
# env
|
||||
.env
|
||||
|
||||
# npm
|
||||
node_modules
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import fs from "node:fs";
|
|||
import path from "path";
|
||||
import { dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
const banner = `/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
|
|
@ -104,9 +105,8 @@ async function copyPluginFilesTo_iCloud() {
|
|||
'styles.css',
|
||||
];
|
||||
|
||||
const destinationDir = '/Users/sechan/Library/Mobile Documents/iCloud~md~obsidian/Documents/main/.obsidian/plugins/daily-routine-2/';
|
||||
// const destinationDir = '/Users/sechan/Library/Mobile Documents/iCloud~md~obsidian/Documents/cloud-test/.obsidian/plugins/daily-routine-2/';
|
||||
|
||||
dotenv.config();
|
||||
const destinationDir = process.env.ICLOUD_DIRECTORY;
|
||||
|
||||
// 현재 파일의 URL을 파일 경로로 변환
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
|
|
|
|||
13
package-lock.json
generated
13
package-lock.json
generated
|
|
@ -15,6 +15,7 @@
|
|||
"@popperjs/core": "^2.11.8",
|
||||
"clsx": "^2.1.1",
|
||||
"dedent": "^1.5.3",
|
||||
"dotenv": "^16.4.7",
|
||||
"eslint-plugin-react": "^7.37.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"lodash": "^4.17.21",
|
||||
|
|
@ -3374,6 +3375,18 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.4.7",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
|
||||
"integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/ejs": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
"@popperjs/core": "^2.11.8",
|
||||
"clsx": "^2.1.1",
|
||||
"dedent": "^1.5.3",
|
||||
"dotenv": "^16.4.7",
|
||||
"eslint-plugin-react": "^7.37.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"lodash": "^4.17.21",
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
import { doConfirm } from "@shared/components/modal/confirm-modal"
|
||||
|
||||
export const devRunner = () => {
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { ensureArchive } from "@entities/archives";
|
||||
import { fileAccessor } from "@shared/file/file-accessor";
|
||||
import { Day } from "@shared/period/day";
|
||||
import { TAbstractFile, TFile } from "obsidian";
|
||||
import { Notice, TAbstractFile, TFile } from "obsidian";
|
||||
import { DR_SETTING } from "@app/settings/setting-provider";
|
||||
import { doConfirm } from "@shared/components/modal/confirm-modal";
|
||||
import { RoutineNote } from "../domain/note.type";
|
||||
|
|
@ -16,7 +16,12 @@ const parseNote = async (day: Day, file: TFile): Promise<RoutineNote> => {
|
|||
|
||||
export const ROUTINE_NOTE_FILE = (day: Day): TFile | null => {
|
||||
const path = ROUTINE_ARCHIVE_PATH(day);
|
||||
return fileAccessor.loadFile(path);
|
||||
try {
|
||||
return fileAccessor.loadFile(path);
|
||||
} catch (e) {
|
||||
new Notice(`Error while loading note file. Please check the path: ${path}`);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const ROUTINE_ARCHIVE_PATH = (day: Day) => {
|
||||
|
|
@ -86,7 +91,12 @@ export const noteRepository: NoteRepository = {
|
|||
const file = ROUTINE_NOTE_FILE(day);
|
||||
if(!file){
|
||||
const path = ROUTINE_ARCHIVE_PATH(day);
|
||||
await fileAccessor.createFile(path, serializeRoutineNote(routineNote));
|
||||
try {
|
||||
await fileAccessor.createFile(path, serializeRoutineNote(routineNote));
|
||||
} catch (e) {
|
||||
await fileAccessor.createFolder(DR_SETTING.noteFolderPath());
|
||||
await fileAccessor.createFile(path, serializeRoutineNote(routineNote));
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -76,9 +76,15 @@ const parseTask = (line: string): Task => {
|
|||
}
|
||||
|
||||
export const parseRoutineNote = (day: Day, content: string): RoutineNote => {
|
||||
const formatCheckRegex = /# Tasks\s*.*/;
|
||||
if(!formatCheckRegex.test(content)) throw new Error('invalid-note-format');
|
||||
|
||||
const regex = /##\s+.*(?:\n(?!##|$).*)*/g;
|
||||
const blocks = content.match(regex);
|
||||
if(!blocks) throw new Error('no task blocks found');
|
||||
if(!blocks) return {
|
||||
day,
|
||||
children: []
|
||||
};
|
||||
|
||||
const root: NoteElement[] = blocks.flatMap(b => {
|
||||
if(b.startsWith("## UNGROUPED")){
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export const BaseTaskGroupFeature = React.memo(({
|
|||
const [groupMode, setGroupMode] = useState<GroupMode>("idle");
|
||||
const bgColor = useLeaf(s=>s.leafBgColor);
|
||||
const { note } = useRoutineNote();
|
||||
const isAllSubTasksChecked = group.children.every(t => t.state !== "un-checked")
|
||||
const isAllSubTasksChecked = group.children.length !== 0 && group.children.every(t => t.state !== "un-checked")
|
||||
|
||||
const [open, _setOpen] = useState(group.isOpen);
|
||||
|
||||
|
|
|
|||
14
src/main.ts
14
src/main.ts
|
|
@ -5,7 +5,7 @@ import { DailyRoutinePluginSettings, DailyRoutineSettingTab, DEFAULT_SETTINGS }
|
|||
import { DailyRoutineObsidianView } from './app';
|
||||
import { activateView } from '@shared/view/activate-view';
|
||||
import { updateMomentConfig } from '@app/settings/moment-config';
|
||||
import { devRunner } from './dev-runner';
|
||||
import { DAILY_ROUTINE_ICON_NAME } from '@app/ui/daily-routine-icon';
|
||||
|
||||
|
||||
export default class DailyRoutinePlugin extends Plugin {
|
||||
|
|
@ -31,16 +31,16 @@ export default class DailyRoutinePlugin extends Plugin {
|
|||
);
|
||||
|
||||
this.addCommand({
|
||||
id: "daily-routine-dev-only-mobile-view-toggle",
|
||||
name: "Toggle Mobile View",
|
||||
id: "daily-routine-open-routine-view",
|
||||
icon: DAILY_ROUTINE_ICON_NAME,
|
||||
name: "Open Routine View",
|
||||
callback: () => {
|
||||
// @ts-ignore
|
||||
this.app.emulateMobile(!this.app.isMobile);
|
||||
activateView(DailyRoutineObsidianView.VIEW_TYPE, 1);
|
||||
}
|
||||
});
|
||||
// this.app.emulateMobile(!this.app.isMobile);
|
||||
|
||||
devRunner();
|
||||
setTimeout(() => activateView(DailyRoutineObsidianView.VIEW_TYPE, 1), 500);
|
||||
setTimeout(() => activateView(DailyRoutineObsidianView.VIEW_TYPE, 1), 0);
|
||||
}
|
||||
|
||||
onunload() {
|
||||
|
|
|
|||
|
|
@ -115,19 +115,38 @@ export const RoutineNoteContent = () => {
|
|||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
<TaskDndContext> {note.children.map(el => {
|
||||
if(isTaskGroup(el)) {
|
||||
<TaskDndContext>
|
||||
{(() => {
|
||||
if(note.children.length === 0) {
|
||||
return (
|
||||
<TaskGroupWidget
|
||||
key={`${el.elementType}-${el.name}`}
|
||||
group={el}
|
||||
/>)
|
||||
} else if(isTask(el)) {
|
||||
return renderTask(el, null);
|
||||
} else {
|
||||
return null;
|
||||
<div css={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: "100%",
|
||||
color: "var(--text-muted)",
|
||||
fontSize: "1.2em",
|
||||
}}>
|
||||
No Tasks.. Add some todos or routines 🤗
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})}</TaskDndContext>
|
||||
|
||||
return note.children.map(el => {
|
||||
if(isTaskGroup(el)) {
|
||||
return (
|
||||
<TaskGroupWidget
|
||||
key={`${el.elementType}-${el.name}`}
|
||||
group={el}
|
||||
/>)
|
||||
} else if(isTask(el)) {
|
||||
return renderTask(el, null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
})()}
|
||||
</TaskDndContext>
|
||||
</div>
|
||||
<AddTodoModal />
|
||||
<StartRoutineModal />
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
/** @jsxImportSource @emotion/react */
|
||||
import { ToggleComponent } from "@shared/components/ToggleComponent";
|
||||
import { TEXT_CSS } from '../text-style';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { ModalApi } from './create-modal';
|
||||
import { TextEditComponent } from "@shared/components/TextEditComponent"
|
||||
import { Button } from "@shared/components/Button"
|
||||
|
|
@ -172,6 +172,15 @@ export const SaveBtn = ({
|
|||
onSaveBtnClick,
|
||||
name,
|
||||
}: SaveBtnProps) => {
|
||||
|
||||
const handleEnterKeyDown = useCallback((e: KeyboardEvent) => {
|
||||
if(e.key === "Enter" && !disabled) onSaveBtnClick?.();
|
||||
}, [disabled, onSaveBtnClick]);
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('keydown', handleEnterKeyDown, true);
|
||||
return () => document.removeEventListener('keydown', handleEnterKeyDown);
|
||||
}, [handleEnterKeyDown]);
|
||||
|
||||
return (
|
||||
<div css={{
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ export const activateView = async (viewTypeName: string, pos = 0) => {
|
|||
|
||||
if(!leaf) {
|
||||
leaf = getLeaf() as WorkspaceLeaf;
|
||||
await leaf.setViewState({ type: viewTypeName });
|
||||
await leaf.setViewState({ type: viewTypeName, active: false });
|
||||
}
|
||||
|
||||
app.workspace.revealLeaf(leaf);
|
||||
}
|
||||
Loading…
Reference in a new issue