Skip to content

Commit db6121f

Browse files
authored
Merge pull request #53 from Quorafind/feat/3-1-0
Feat/3 1 0
2 parents c6dcae1 + 8f7c6f6 commit db6121f

File tree

6 files changed

+780
-22
lines changed

6 files changed

+780
-22
lines changed

src/autoCompleteParent.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,16 @@ function findTaskCompletion(tr: Transaction): {
8686
) => {
8787
// If a change involves inserting an 'x' character
8888
const insertedText = inserted.toString();
89-
if (insertedText === "x" || insertedText === "X") {
89+
console.log(insertedText);
90+
if (
91+
insertedText === "x" ||
92+
insertedText === "X" ||
93+
insertedText.trim() === "- [x]"
94+
) {
9095
// Get the position context
9196
const pos = fromB;
9297
const line = tr.newDoc.lineAt(pos);
9398
const lineText = line.text;
94-
console.log(lineText);
9599

96100
// Check if this is a task being completed ([ ] to [x])
97101
// Matches the pattern where the cursor is between [ and ]

src/taskProgressBarIndex.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
import {
2-
App,
3-
debounce,
4-
Editor,
5-
editorEditorField,
62
editorInfoField,
73
HoverParent,
84
HoverPopover,
95
MarkdownRenderer,
106
Plugin,
11-
PluginSettingTab,
12-
Setting,
137
} from "obsidian";
14-
import { HTMLElementWithView, taskProgressBarExtension } from "./widget";
8+
import { taskProgressBarExtension } from "./widget";
159
import { updateProgressBarInElement } from "./readModeWidget";
1610
import {
1711
DEFAULT_SETTINGS,
@@ -20,6 +14,7 @@ import {
2014
} from "./taskProgressBarSetting";
2115
import { EditorView } from "@codemirror/view";
2216
import { autoCompleteParentExtension } from "./autoCompleteParent";
17+
import { taskStatusSwitcherExtension } from "./taskStatusSwitcher";
2318

2419
class TaskProgressBarPopover extends HoverPopover {
2520
plugin: TaskProgressBarPlugin;
@@ -106,8 +101,11 @@ export default class TaskProgressBarPlugin extends Plugin {
106101
this.addSettingTab(new TaskProgressBarSettingTab(this.app, this));
107102
this.registerEditorExtension([
108103
taskProgressBarExtension(this.app, this),
109-
110104
]);
105+
this.settings.enableTaskStatusSwitcher &&
106+
this.registerEditorExtension([
107+
taskStatusSwitcherExtension(this.app, this),
108+
]);
111109
this.registerMarkdownPostProcessor((el, ctx) => {
112110
updateProgressBarInElement({
113111
plugin: this,

src/taskProgressBarSetting.ts

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { App, PluginSettingTab, Setting, Modal } from "obsidian";
22
import TaskProgressBarPlugin from "./taskProgressBarIndex";
33
import { allStatusCollections } from "./task-status";
4+
import { STATE_MARK_MAP, TaskState } from "./taskStatusSwitcher";
45

56
export interface TaskProgressBarSettings {
7+
showProgressBar: boolean;
68
addTaskProgressBarToHeading: boolean;
79
enableHeadingProgressBar: boolean;
810
addNumberToProgressBar: boolean;
@@ -37,9 +39,15 @@ export interface TaskProgressBarSettings {
3739
max: number;
3840
text: string;
3941
}>;
42+
43+
// Task status switcher settings
44+
enableTaskStatusSwitcher: boolean;
45+
taskStatusCycle: string[];
46+
taskStatusMarks: Record<string, string>;
4047
}
4148

4249
export const DEFAULT_SETTINGS: TaskProgressBarSettings = {
50+
showProgressBar: false,
4351
addTaskProgressBarToHeading: false,
4452
enableHeadingProgressBar: false,
4553
addNumberToProgressBar: false,
@@ -76,6 +84,16 @@ export const DEFAULT_SETTINGS: TaskProgressBarSettings = {
7684
{ min: 60, max: 80, text: "Good progress {{PROGRESS}}%" },
7785
{ min: 80, max: 100, text: "Almost there {{PROGRESS}}%" },
7886
],
87+
88+
// Task status switcher settings
89+
enableTaskStatusSwitcher: false,
90+
taskStatusCycle: ["TODO", "DOING", "IN-PROGRESS", "DONE"],
91+
taskStatusMarks: {
92+
TODO: " ",
93+
DOING: "-",
94+
"IN-PROGRESS": ">",
95+
DONE: "x",
96+
},
7997
};
8098

8199
export class TaskProgressBarSettingTab extends PluginSettingTab {
@@ -102,6 +120,18 @@ export class TaskProgressBarSettingTab extends PluginSettingTab {
102120

103121
containerEl.createEl("h2", { text: "📍 Task Progress Bar" });
104122

123+
new Setting(containerEl)
124+
.setName("Show progress bar")
125+
.setDesc("Toggle this to show the progress bar.")
126+
.addToggle((toggle) =>
127+
toggle
128+
.setValue(this.plugin.settings.showProgressBar)
129+
.onChange(async (value) => {
130+
this.plugin.settings.showProgressBar = value;
131+
this.applySettingsUpdate();
132+
})
133+
);
134+
105135
new Setting(containerEl)
106136
.setName("Add progress bar to Heading")
107137
.setDesc(
@@ -501,6 +531,153 @@ export class TaskProgressBarSettingTab extends PluginSettingTab {
501531
);
502532
}
503533

534+
this.containerEl.createEl("h2", { text: "Task Status Switcher" });
535+
536+
new Setting(containerEl)
537+
.setName("Enable Task Status Switcher")
538+
.setDesc(
539+
"Enable/disable the ability to cycle through task states by clicking."
540+
)
541+
.addToggle((toggle) => {
542+
toggle
543+
.setValue(this.plugin.settings.enableTaskStatusSwitcher)
544+
.onChange(async (value) => {
545+
this.plugin.settings.enableTaskStatusSwitcher = value;
546+
this.applySettingsUpdate();
547+
});
548+
});
549+
550+
new Setting(containerEl)
551+
.setName("Task Status Cycle and Marks")
552+
.setDesc(
553+
"Define task states and their corresponding marks. The order from top to bottom defines the cycling sequence."
554+
);
555+
556+
// Create a container for the task states list
557+
const taskStatesContainer = containerEl.createDiv({
558+
cls: "task-states-container",
559+
});
560+
561+
// Function to refresh the task states list
562+
const refreshTaskStatesList = () => {
563+
// Clear the container
564+
taskStatesContainer.empty();
565+
566+
// Get current cycle and marks
567+
const cycle = this.plugin.settings.taskStatusCycle;
568+
const marks = this.plugin.settings.taskStatusMarks;
569+
570+
// Add each status in the cycle
571+
cycle.forEach((state, index) => {
572+
const stateRow = taskStatesContainer.createDiv({
573+
cls: "task-state-row",
574+
});
575+
576+
// Create the setting
577+
const stateSetting = new Setting(stateRow)
578+
.setName(`Status #${index + 1}`)
579+
.addText((text) => {
580+
text.setValue(state)
581+
.setPlaceholder("Status name")
582+
.onChange((value) => {
583+
// Update the state name in both cycle and marks
584+
const oldState = cycle[index];
585+
cycle[index] = value;
586+
587+
// If the old state had a mark, preserve it with the new name
588+
if (oldState in marks) {
589+
marks[value] = marks[oldState];
590+
delete marks[oldState];
591+
}
592+
593+
this.applySettingsUpdate();
594+
});
595+
})
596+
.addText((text) => {
597+
text.setValue(marks[state] || " ")
598+
.setPlaceholder("Mark")
599+
.onChange((value) => {
600+
// Only use the first character
601+
const mark = value.trim().charAt(0) || " ";
602+
marks[state] = mark;
603+
this.applySettingsUpdate();
604+
});
605+
text.inputEl.maxLength = 1;
606+
text.inputEl.style.width = "40px";
607+
});
608+
609+
// Add buttons for moving up/down and removing
610+
stateSetting.addExtraButton((button) => {
611+
button
612+
.setIcon("arrow-up")
613+
.setTooltip("Move up")
614+
.onClick(() => {
615+
if (index > 0) {
616+
// Swap with the previous item
617+
[cycle[index - 1], cycle[index]] = [
618+
cycle[index],
619+
cycle[index - 1],
620+
];
621+
this.applySettingsUpdate();
622+
refreshTaskStatesList();
623+
}
624+
});
625+
button.extraSettingsEl.style.marginRight = "0";
626+
});
627+
628+
stateSetting.addExtraButton((button) => {
629+
button
630+
.setIcon("arrow-down")
631+
.setTooltip("Move down")
632+
.onClick(() => {
633+
if (index < cycle.length - 1) {
634+
// Swap with the next item
635+
[cycle[index], cycle[index + 1]] = [
636+
cycle[index + 1],
637+
cycle[index],
638+
];
639+
this.applySettingsUpdate();
640+
refreshTaskStatesList();
641+
}
642+
});
643+
button.extraSettingsEl.style.marginRight = "0";
644+
});
645+
646+
stateSetting.addExtraButton((button) => {
647+
button
648+
.setIcon("trash")
649+
.setTooltip("Remove")
650+
.onClick(() => {
651+
// Remove from cycle
652+
cycle.splice(index, 1);
653+
// Don't remove from marks to preserve settings
654+
this.applySettingsUpdate();
655+
refreshTaskStatesList();
656+
});
657+
button.extraSettingsEl.style.marginRight = "0";
658+
});
659+
});
660+
661+
// Add button to add new status
662+
const addButtonContainer = taskStatesContainer.createDiv();
663+
new Setting(addButtonContainer).addButton((button) => {
664+
button
665+
.setButtonText("Add Status")
666+
.setCta()
667+
.onClick(() => {
668+
// Add a new status to the cycle with a default mark
669+
const newStatus = `STATUS_${cycle.length + 1}`;
670+
cycle.push(newStatus);
671+
marks[newStatus] = " ";
672+
this.applySettingsUpdate();
673+
refreshTaskStatesList();
674+
});
675+
});
676+
};
677+
678+
// Initial render of the task states list
679+
refreshTaskStatesList();
680+
504681
this.containerEl.createEl("h2", { text: "Say Thank You" });
505682

506683
new Setting(containerEl)

0 commit comments

Comments
 (0)