From 7135c5181e57dcb2bbcbf1de56f6aec5f9668667 Mon Sep 17 00:00:00 2001 From: Al0cam Date: Sun, 2 Nov 2025 18:39:34 +0100 Subject: [PATCH] feat: work on moving logic --- Settings/ProjectSection.ts | 3 - Utils/ProjectMatcherUtil.ts | 45 ++++++++++++ Utils/PropertyUtil.ts | 42 ++++++----- styles.css | 134 ++++++++++++++++++------------------ 4 files changed, 138 insertions(+), 86 deletions(-) create mode 100644 Utils/ProjectMatcherUtil.ts diff --git a/Settings/ProjectSection.ts b/Settings/ProjectSection.ts index 602c451..ef588fb 100644 --- a/Settings/ProjectSection.ts +++ b/Settings/ProjectSection.ts @@ -50,7 +50,6 @@ export function projectSection(containerEl: HTMLElement, plugin: AutoMoverPlugin */ for (const project of plugin.settings.projectRules as ProjectRule[]) { const child = projectList.createDiv({ cls: "project" }); - const projectDetails = child.createDiv({ cls: "rule" }); // Class used from obdsidian's css for consistency const movingRulesDetails = child.createEl("details", {}); @@ -149,7 +148,5 @@ export function projectSection(containerEl: HTMLElement, plugin: AutoMoverPlugin display(); }); } - - projectDetails.createEl("br"); } } diff --git a/Utils/ProjectMatcherUtil.ts b/Utils/ProjectMatcherUtil.ts new file mode 100644 index 0000000..d01b616 --- /dev/null +++ b/Utils/ProjectMatcherUtil.ts @@ -0,0 +1,45 @@ +import { ProjectRule } from "Models/ProjectRule"; +import type { TFile } from "obsidian"; +import propertyUtil from "./PropertyUtil"; + +class ProjectMatcherUtil { + private static instance: ProjectMatcherUtil; + + private constructor() {} + + public static getInstance(): ProjectMatcherUtil { + if (!ProjectMatcherUtil.instance) { + ProjectMatcherUtil.instance = new ProjectMatcherUtil(); + } + return ProjectMatcherUtil.instance; + } + + /** + * Returns the first project rule that matches the file + * If no rule matches, returns null + * @param file + * @param projectRules + * @returns ProjectRule | null + */ + public getMatchingProjectRule(file: TFile, projectRules: ProjectRule[]): ProjectRule | null { + propertyUtil.getPropertiesFromFile(file); + for (const rule of projectRules) { + if (rule.projectName == null || rule.projectName === "") { + console.error("Project Rule does not have a project name: ", rule); + continue; + } + if (rule.folder == null || rule.folder === "") { + console.error("Project Rule does not have a destination folder: ", rule); + continue; + } + // Check if the file path contains the project name as a wiki link or plain text + const wikiLink = `[[${rule.projectName}]]`; + if (file.path.includes(wikiLink) || file.path.includes(rule.projectName)) { + return rule; + } + } + return null; + } +} +const exclusionMatcherUtil = ProjectMatcherUtil.getInstance(); +export default exclusionMatcherUtil; diff --git a/Utils/PropertyUtil.ts b/Utils/PropertyUtil.ts index b6b2bcf..efda3a1 100644 --- a/Utils/PropertyUtil.ts +++ b/Utils/PropertyUtil.ts @@ -1,3 +1,5 @@ +import { TFile } from "obsidian"; + class PropertyUtil { private static instance: PropertyUtil; @@ -10,23 +12,31 @@ class PropertyUtil { return PropertyUtil.instance; } + /** + * TODO: Add property support + * + * overview.md + * Page Properties: + * Project: [[Project A]] + * File Type: asset + * + * It would take those Project Property and File Type Properties, moving it to Project A/assets. + * + * + * + * Theoretically, projects should then take precedence over tags and names, as they are more specific. + * + * + * The way i see the implementation is adding a new model that will contain the project destination + * and then specify in subdirectories where each matching file goes. + * And it has to check if the file contains the property from the project such as it was mentioned in the overview.md example. + * + */ -/** - * TODO: Add property support - * - * overview.md - * Page Properties: - * Project: [[Project A]] - * File Type: asset - * - * It would take those Project Property and File Type Properties, moving it to Project A/assets. - * - * - * - * Theoretically, projects should then take precedence over tags and names, as they are more specific. - * - */ - + public getPropertiesFromFile(file: TFile): Record { + console.log("Extracted properties: ", properties); + return properties; + } } const propertyUtil = PropertyUtil.getInstance(); diff --git a/styles.css b/styles.css index 77cdb03..a92fbc4 100644 --- a/styles.css +++ b/styles.css @@ -8,118 +8,118 @@ If your plugin does not need CSS, delete this file. */ .moving_rules_container { - padding: 0.75em 0; - border-top: 1px solid var(--background-modifier-border); - display: flex; - flex-direction: column; + padding: 0.75em 0; + border-top: 1px solid var(--background-modifier-border); + display: flex; + flex-direction: column; } .rule { - display: flex; - flex-direction: row; - align-items: center; - margin-bottom: 0.5em; - justify-content: space-evenly; - gap: 0.5em; + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 0.5em; + justify-content: space-evenly; + gap: 0.5em; } .rule_header { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - width: 100%; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + width: 100%; } .rule_title { - padding: 0.5em; - width: 100%; - font-weight: bold; + padding: 0.5em; + width: 100%; + font-weight: bold; } .rule_input { - width: 100%; - padding: 0.5em; - border: 1px solid var(--background-modifier-border); - border-radius: 0.25em; + width: 100%; + padding: 0.5em; + border: 1px solid var(--background-modifier-border); + border-radius: 0.25em; } .rule_button { - cursor: pointer; + cursor: pointer; } .rule_button:hover { - background-color: var(--color-green); + background-color: var(--color-green); } .rule_button:active { - background-color: var(--background-modifier-active); + background-color: var(--background-modifier-active); } .rule_button_remove:hover { - background-color: var(--color-red) !important; + background-color: var(--color-red) !important; } .rule_button_duplicate:hover { - background-color: var(--color-blue) !important; + background-color: var(--color-blue) !important; } /* Style for timer-setting input field */ .setting-item.timer-setting input[type="text"] { - width: auto; - min-width: 8ch; - /* Minimum for hh:mm:ss */ - max-width: 16ch; - /* Allows up to ~9999:59:59 */ - /* padding: 2px 6px; */ - font-family: monospace; - text-align: center; - /* box-sizing: content-box; */ + width: auto; + min-width: 8ch; + /* Minimum for hh:mm:ss */ + max-width: 16ch; + /* Allows up to ~9999:59:59 */ + /* padding: 2px 6px; */ + font-family: monospace; + text-align: center; + /* box-sizing: content-box; */ } .project { - display: flex; - flex-direction: column; - gap: 0.5em; - border-bottom: 1px solid var(--background-modifier-border); - padding-bottom: 0.75em; - padding-top: 0.75em; + display: flex; + flex-direction: column; + gap: 0.5em; + border-bottom: 1px solid var(--background-modifier-border); + padding-bottom: 0.75em; + padding-top: 0.75em; } .project_rule { - display: flex; - flex-direction: row; - align-items: center; - margin-bottom: 0.5em; - margin-left: 1em; - justify-content: space-evenly; - gap: 0.5em; + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 0.5em; + margin-left: 3em; + justify-content: space-evenly; + gap: 0.5em; } summary { - /* Hides the marker in most browsers */ - list-style: none; - /* Hides the marker in Safari/WebKit */ - /* This is crucial for cross-browser consistency */ - -webkit-appearance: none; + /* Hides the marker in most browsers */ + list-style: none; + /* Hides the marker in Safari/WebKit */ + /* This is crucial for cross-browser consistency */ + -webkit-appearance: none; } /* Add a custom icon using ::before */ summary::before { - content: "▶"; - /* Closed state icon */ - margin-right: 10px; - /* Position the arrow before the content */ - display: inline-block; - transition: transform 0.2s; - /* Customize the look/color of the arrow */ - color: #fff; - min-width: 12px; - /* Ensure it doesn't shift */ + content: "▶"; + /* Closed state icon */ + margin-right: 10px; + /* Position the arrow before the content */ + display: inline-block; + transition: transform 0.2s; + /* Customize the look/color of the arrow */ + color: #fff; + min-width: 12px; + /* Ensure it doesn't shift */ } /* Rotate the icon when the details is open */ -details[open]>summary::before { - transform: rotate(90deg); - /* Rotates the '▶' into a '▼' */ +details[open] > summary::before { + transform: rotate(90deg); + /* Rotates the '▶' into a '▼' */ }