mirror of
https://github.com/devonthesofa/obsidian-note-status.git
synced 2026-07-22 12:30:24 +00:00
291 lines
7.3 KiB
TypeScript
291 lines
7.3 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
import { Notice } from "obsidian";
|
|
import { PluginSettings } from "@/types/pluginSettings";
|
|
import { TemplateSettings } from "./TemplateSettings";
|
|
import { BehaviourSettings } from "./BehaviourSettings";
|
|
import { CustomStatusSettings } from "./CustomStatusSettings";
|
|
import { QuickCommandsSettings } from "./QuickCommandsSettings";
|
|
import { SynchronizationSettings } from "./SynchronizationSettings";
|
|
import {
|
|
EditorToolbarSettings,
|
|
ExperimentalSettings,
|
|
FileExplorerSettings,
|
|
StatusBarSettings,
|
|
UnknownStatusAppearanceSettings,
|
|
} from "./UISettings";
|
|
|
|
export type Props = {
|
|
settings: PluginSettings;
|
|
onChange: (key: keyof PluginSettings, value: unknown) => void;
|
|
};
|
|
|
|
type SectionId =
|
|
| "templates-statuses"
|
|
| "quick-actions"
|
|
| "status-bar"
|
|
| "editor-toolbar"
|
|
| "file-explorer"
|
|
| "unknown-appearance"
|
|
| "behavior-storage"
|
|
| "synchronization"
|
|
| "experimental-features";
|
|
|
|
type SectionDefinition = {
|
|
id: SectionId;
|
|
label: string;
|
|
description: string;
|
|
content: React.ReactNode;
|
|
};
|
|
|
|
const SettingsUI: React.FC<Props> = ({ settings, onChange }) => {
|
|
const [localSettings, setLocalSettings] = useState(settings);
|
|
const [expandedSections, setExpandedSections] = useState<
|
|
Partial<Record<SectionId, boolean>>
|
|
>({});
|
|
|
|
useEffect(() => {
|
|
setLocalSettings(settings);
|
|
}, [settings]);
|
|
|
|
const handleChange = (key: keyof PluginSettings, value: unknown) => {
|
|
setLocalSettings((prev) => ({ ...prev, [key]: value }));
|
|
onChange(key, value);
|
|
};
|
|
|
|
const handleSupportClick = (url: string, label: string) => {
|
|
window.open(url);
|
|
navigator.clipboard.writeText(url).then(() => {
|
|
new Notice(`Copied ${label} URL to clipboard!`);
|
|
});
|
|
};
|
|
|
|
const sections: SectionDefinition[] = [
|
|
{
|
|
id: "templates-statuses",
|
|
label: "Templates & Statuses",
|
|
description:
|
|
"Enable predefined workflows or define your own statuses.",
|
|
content: (
|
|
<div className="note-status-settings__stack">
|
|
<TemplateSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
<CustomStatusSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
id: "quick-actions",
|
|
label: "Quick Actions",
|
|
description: "Choose statuses with command palette shortcuts.",
|
|
content: (
|
|
<QuickCommandsSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
id: "status-bar",
|
|
label: "Status Bar",
|
|
description:
|
|
"Icon, popup, badge style/content, and no-status behavior.",
|
|
content: (
|
|
<StatusBarSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
id: "editor-toolbar",
|
|
label: "Editor Toolbar",
|
|
description: "Button placement and visibility across panes.",
|
|
content: (
|
|
<EditorToolbarSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
id: "file-explorer",
|
|
label: "File Explorer",
|
|
description:
|
|
"Icon placement, hiding unknown, and visual styling options.",
|
|
content: (
|
|
<FileExplorerSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
id: "unknown-appearance",
|
|
label: "Unknown / No-Status Appearance",
|
|
description: "Fallback icon and color when a note lacks status.",
|
|
content: (
|
|
<UnknownStatusAppearanceSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
id: "behavior-storage",
|
|
label: "Behavior & Storage",
|
|
description:
|
|
"Multi-status mode, tag key, mappings, and vault safeguards.",
|
|
content: (
|
|
<BehaviourSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
id: "synchronization",
|
|
label: "Synchronization",
|
|
description:
|
|
"Keep custom statuses and templates in sync across multiple devices.",
|
|
content: (
|
|
<SynchronizationSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
id: "experimental-features",
|
|
label: "Experimental Features",
|
|
description: "Opt into dashboard and grouped view previews.",
|
|
content: (
|
|
<ExperimentalSettings
|
|
settings={localSettings}
|
|
onChange={handleChange}
|
|
/>
|
|
),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div className="note-status-settings">
|
|
{sections.map((section) => {
|
|
const isOpen = expandedSections[section.id] ?? false;
|
|
return (
|
|
<div
|
|
key={section.id}
|
|
className={`note-status-section ${
|
|
isOpen ? "is-open" : ""
|
|
}`}
|
|
>
|
|
<button
|
|
type="button"
|
|
className="note-status-section__header"
|
|
aria-expanded={isOpen}
|
|
onClick={() =>
|
|
setExpandedSections((prev) => ({
|
|
...prev,
|
|
[section.id]: !prev[section.id],
|
|
}))
|
|
}
|
|
>
|
|
<div className="note-status-section__title-block">
|
|
<div className="setting-item-name">
|
|
{section.label}
|
|
</div>
|
|
<div className="setting-item-description">
|
|
{section.description}
|
|
</div>
|
|
</div>
|
|
<span
|
|
className="note-status-section__chevron"
|
|
aria-hidden="true"
|
|
>
|
|
{isOpen ? "v" : ">"}
|
|
</span>
|
|
</button>
|
|
{isOpen ? (
|
|
<div className="note-status-section__content">
|
|
{section.content}
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
);
|
|
})}
|
|
|
|
<div className="note-status-settings__intro">
|
|
<p className="note-status-settings__description">
|
|
Note Status keeps your vault aligned with clear,
|
|
configurable workflows. Tune the sections below to match how
|
|
you review notes, surface statuses, and keep storage tidy.
|
|
</p>
|
|
<div className="note-status-settings__support">
|
|
<button
|
|
className="note-status-settings__support-link"
|
|
onClick={() =>
|
|
handleSupportClick(
|
|
"https://paypal.me/aleixsoler",
|
|
"PayPal",
|
|
)
|
|
}
|
|
>
|
|
<img
|
|
src="https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white"
|
|
alt="PayPal"
|
|
style={{ height: "20px" }}
|
|
/>
|
|
<span className="note-status-settings__support-link-label">
|
|
Support via PayPal
|
|
</span>
|
|
<span className="note-status-settings__support-link-url">
|
|
paypal.me/aleixsoler
|
|
</span>
|
|
</button>
|
|
<button
|
|
className="note-status-settings__support-link"
|
|
onClick={() =>
|
|
handleSupportClick(
|
|
"https://buymeacoffee.com/aleixsoler",
|
|
"Buy Me a Coffee",
|
|
)
|
|
}
|
|
>
|
|
<img
|
|
src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black"
|
|
alt="Buy me a coffee"
|
|
style={{ height: "20px" }}
|
|
/>
|
|
<span className="note-status-settings__support-link-label">
|
|
Buy me a coffee
|
|
</span>
|
|
<span className="note-status-settings__support-link-url">
|
|
buymeacoffee.com/aleixsoler
|
|
</span>
|
|
</button>
|
|
<button
|
|
className="note-status-settings__support-link"
|
|
onClick={() =>
|
|
handleSupportClick(
|
|
"https://github.com/devonthesofa/obsidian-note-status",
|
|
"GitHub",
|
|
)
|
|
}
|
|
>
|
|
<span className="note-status-settings__support-link-label">
|
|
Star on GitHub
|
|
</span>
|
|
<span className="note-status-settings__support-link-url">
|
|
github.com/devonthesofa/obsidian-note-status
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
export default SettingsUI;
|