Skip to content
This repository was archived by the owner on Jul 28, 2025. It is now read-only.

Commit 8608b6d

Browse files
committed
Merge branch 'checkbox-darkmode-support'
2 parents 3074826 + 534a785 commit 8608b6d

File tree

9 files changed

+216
-10
lines changed

9 files changed

+216
-10
lines changed

docs/docs/changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 1.5.1
2+
*Published on 2022/05/29*
3+
### Shiny new things
4+
- Preview mode now renders a dataview table insead of markdown content! [ISSUE#41](https://github.com/RafaelGB/obsidian-db-folder/issues/41)
5+
### Visual
6+
- Support for darkmode to checkbox column
7+
### No longer broken
8+
- When new row is added and metadata column of created and modified is enabled, the metadata column is automatically filled with the current date and time instead of crashing.
19
## 1.5.0
210
*Published on 2022/05/27*
311
### Shiny new things

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "dbfolder",
33
"name": "DB Folder",
4-
"version": "1.5.0",
4+
"version": "1.5.1",
55
"minAppVersion": "0.14.6",
66
"description": "Folder with the capability to store and retrieve data from a folder like database",
77
"author": "RafaelGB",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "obsidian-dbfolder",
3-
"version": "1.5.0",
3+
"version": "1.5.1",
44
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
55
"main": "main.js",
66
"scripts": {

src/StateManager.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export default class StateManager {
4646
}
4747

4848
async forceRefresh() {
49-
LOGGER.warn("TODO forceRefresh");
49+
this.viewSet.forEach((view) => {
50+
view.reloadDatabase();
51+
});
5052
}
5153
}

src/components/reducers/DatabaseDispatch.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import NoteInfo from "services/NoteInfo";
2323
import { DataviewService } from "services/DataviewService";
2424
import { obtainUniqueOptionValues } from "helpers/SelectHelper";
2525
import { RowSelectOption } from "cdm/RowSelectModel";
26+
import { Literal } from "obsidian-dataview/lib/data-model/value";
27+
import { DateTime } from "luxon";
2628

2729
export function databaseReducer(state: TableDataType, action: ActionType) {
2830
LOGGER.debug(
@@ -81,10 +83,13 @@ export function databaseReducer(state: TableDataType, action: ActionType) {
8183
action.filename,
8284
rowRecord
8385
);
84-
86+
const metadata: Record<string, Literal> = {};
87+
metadata[MetadataColumns.CREATED] = DateTime.now();
88+
metadata[MetadataColumns.MODIFIED] = DateTime.now();
8589
const row: RowDataType = {
8690
...rowRecord.frontmatter,
8791
...rowRecord.inline,
92+
...metadata,
8893
id: state.data.length + 1,
8994
note: new NoteInfo(
9095
{

src/helpers/Constants.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ export const MetadataDatabaseColumns = Object.freeze({
105105
label: MetadataLabels.TASK,
106106
accessor: MetadataColumns.TASKS,
107107
isMetadata: true,
108-
skipPersist: false,
109-
csvCandidate: true,
108+
skipPersist: true,
109+
csvCandidate: false,
110110
config: DEFAULT_COLUMN_CONFIG
111111
},
112112
});

src/main.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import StateManager from 'StateManager';
3333
import { around } from 'monkey-around';
3434
import { LOGGER } from 'services/Logger';
3535
import { DatabaseCore, DatabaseFrontmatterOptions } from 'helpers/Constants';
36+
import { PreviewDatabaseModeService } from 'services/MarkdownPostProcessorService';
3637

3738
export default class DBFolderPlugin extends Plugin {
3839
/** Plugin-wide default settings. */
@@ -41,6 +42,11 @@ export default class DBFolderPlugin extends Plugin {
4142
/** External-facing plugin API */
4243
public api: DbfAPIInterface;
4344

45+
public hover: { linkText: string; sourcePath: string } = {
46+
linkText: null,
47+
sourcePath: null,
48+
};
49+
4450
databaseFileModes: Record<string, string> = {};
4551

4652
viewMap: Map<string, DatabaseView> = new Map();
@@ -58,17 +64,18 @@ export default class DBFolderPlugin extends Plugin {
5864
this.settings = newSettings;
5965
await this.saveSettings();
6066

61-
// Force a complete re-render when settings change
62-
//this.stateManagers.forEach((stateManager) => {
63-
//stateManager.forceRefresh();
64-
//});
67+
//Force a complete re-render when settings change
68+
this.stateManagers.forEach((stateManager) => {
69+
stateManager.forceRefresh();
70+
});
6571
},
6672
})
6773
);
6874

6975
this.registerView(DatabaseCore.FRONTMATTER_KEY, (leaf) => new DatabaseView(leaf, this));
7076
this.registerEvents();
7177
this.registerMonkeyPatches();
78+
this.addMarkdownPostProcessor();
7279
this.api = new DBFolderAPI(this.app, this.settings);
7380
}
7481

@@ -235,6 +242,21 @@ export default class DBFolderPlugin extends Plugin {
235242
);
236243
}
237244

245+
/**
246+
* Displays a transcluded .excalidraw image in markdown preview mode
247+
*/
248+
private addMarkdownPostProcessor() {
249+
const previewMode = PreviewDatabaseModeService.getInstance(this);
250+
this.registerMarkdownPostProcessor(previewMode.markdownPostProcessor);
251+
252+
// internal-link quick preview
253+
this.registerEvent(this.app.workspace.on("quick-preview", previewMode.hoverEvent));
254+
255+
//monitoring for div.popover.hover-popover.file-embed.is-loaded to be added to the DOM tree
256+
// this.observer = observer;
257+
// this.observer.observe(document, { childList: true, subtree: true });
258+
}
259+
238260
/**
239261
* Wrap Obsidian functionalities to add the database support needed
240262
*/
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import { DatabaseCore } from "helpers/Constants";
2+
import DBFolderPlugin from "main";
3+
import { MarkdownPostProcessorContext } from "obsidian";
4+
import DatabaseInfo from "services/DatabaseInfo";
5+
import { VaultManagerDB } from "services/FileManagerService";
6+
import { DataviewService } from "services/DataviewService";
7+
import { obtainColumnsFromFolder, obtainMetadataColumns } from "components/Columns";
8+
import { adapterTFilesToRows } from "helpers/VaultManagement";
9+
import { DatabaseColumn } from "cdm/DatabaseModel";
10+
/**
11+
* Keep info about a note and offer methods to manipulate it
12+
*/
13+
export class PreviewDatabaseModeService {
14+
private static instance: PreviewDatabaseModeService;
15+
private plugin: DBFolderPlugin;
16+
constructor(plugin: DBFolderPlugin) {
17+
this.plugin = plugin;
18+
if (!PreviewDatabaseModeService.instance) {
19+
PreviewDatabaseModeService.instance = this;
20+
}
21+
}
22+
hoverEvent = (e: any) => {
23+
if (!e.linktext) {
24+
this.plugin.hover.linkText = null;
25+
return;
26+
}
27+
this.plugin.hover.linkText = e.linktext;
28+
this.plugin.hover.sourcePath = e.sourcePath;
29+
};
30+
/**
31+
*
32+
* @param el
33+
* @param ctx
34+
*/
35+
markdownPostProcessor = async (
36+
el: HTMLElement,
37+
ctx: MarkdownPostProcessorContext,
38+
) => {
39+
//check to see if we are rendering in editing mode of live preview
40+
//if yes, then there should be no .internal-embed containers
41+
const embeddedItems = el.querySelectorAll(".internal-embed");
42+
if (embeddedItems.length === 0) {
43+
this.tmpObsidianWYSIWYG(el, ctx);
44+
return;
45+
}
46+
47+
//If the file being processed is an excalidraw file,
48+
//then I want to hide all embedded items as these will be
49+
//transcluded text element or some other transcluded content inside the Excalidraw file
50+
//in reading mode these elements should be hidden
51+
if (ctx.frontmatter?.hasOwnProperty(DatabaseCore.FRONTMATTER_KEY)) {
52+
el.style.display = "none";
53+
return;
54+
}
55+
};
56+
57+
tmpObsidianWYSIWYG = async (
58+
el: HTMLElement,
59+
ctx: MarkdownPostProcessorContext,
60+
) => {
61+
if (!ctx.frontmatter) {
62+
return;
63+
}
64+
if (!ctx.frontmatter.hasOwnProperty(DatabaseCore.FRONTMATTER_KEY)) {
65+
return;
66+
}
67+
//@ts-ignore
68+
if (ctx.remainingNestLevel < 4) {
69+
return;
70+
}
71+
if (!el.querySelector(".frontmatter")) {
72+
el.style.display = "none";
73+
return;
74+
}
75+
el.empty();
76+
const previewContainer = await this.renderPreview(el, ctx);
77+
setTimeout(async () => {
78+
let internalEmbedDiv: HTMLElement = el;
79+
while (
80+
!internalEmbedDiv.hasClass("internal-embed") &&
81+
internalEmbedDiv.parentElement
82+
) {
83+
internalEmbedDiv = internalEmbedDiv.parentElement;
84+
}
85+
86+
if (!internalEmbedDiv.hasClass("internal-embed")) {
87+
el.empty();
88+
el.appendChild(previewContainer);
89+
return;
90+
}
91+
92+
internalEmbedDiv.empty();
93+
const previewTimeoutContainer = await this.renderPreview(internalEmbedDiv, ctx);
94+
//timer to avoid the image flickering when the user is typing
95+
let timer: NodeJS.Timeout = null;
96+
const observer = new MutationObserver((m) => {
97+
if (!["alt", "width", "height"].contains(m[0]?.attributeName)) {
98+
return;
99+
}
100+
if (timer) {
101+
clearTimeout(timer);
102+
}
103+
timer = setTimeout(() => {
104+
timer = null;
105+
previewTimeoutContainer.empty();
106+
}, 500);
107+
});
108+
observer.observe(previewTimeoutContainer, {
109+
attributes: true, //configure it to listen to attribute changes
110+
});
111+
}, 300);
112+
};
113+
114+
private renderPreview = async (
115+
el: HTMLElement,
116+
ctx: MarkdownPostProcessorContext,
117+
): Promise<HTMLElement> => {
118+
const dbFile = VaultManagerDB.obtainTfileFromFilePath(ctx.sourcePath);
119+
const databaseDisk = new DatabaseInfo(dbFile);
120+
await databaseDisk.initDatabaseconfigYaml(
121+
this.plugin.settings.local_settings
122+
);
123+
124+
const div = createDiv();
125+
div.textContent = `${databaseDisk
126+
.yaml.description}`;
127+
el.appendChild(div);
128+
let yamlColumns: Record<string, DatabaseColumn> =
129+
databaseDisk.yaml.columns;
130+
// Complete the columns with the metadata columns
131+
yamlColumns = await obtainMetadataColumns(
132+
yamlColumns,
133+
databaseDisk.yaml.config
134+
);
135+
// Obtain base information about columns
136+
const columns = await obtainColumnsFromFolder(yamlColumns);
137+
const rows = await adapterTFilesToRows(
138+
dbFile.parent.path,
139+
columns,
140+
databaseDisk.yaml.filters
141+
);
142+
const dataviewCols: string[] = columns
143+
.filter((col) => !col.skipPersist)
144+
.map((c) => c.key);
145+
const dataviewMatrixRow: any[][] = rows.map((r) =>
146+
dataviewCols.map((c) => r[c])
147+
);
148+
149+
DataviewService.getDataviewAPI().table(
150+
dataviewCols,
151+
dataviewMatrixRow,
152+
div,
153+
null,
154+
ctx.sourcePath
155+
)
156+
return div;
157+
}
158+
159+
public static getInstance(plugin?: DBFolderPlugin): PreviewDatabaseModeService {
160+
if (!this.instance) {
161+
this.instance = new PreviewDatabaseModeService(plugin);
162+
}
163+
return this.instance;
164+
}
165+
}

styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@
143143
background-color: CanvasText;
144144
}
145145

146+
.data-input-checkbox input[type="checkbox"]:checked{
147+
background-color: var(--background-modifier-border);
148+
}
149+
146150
.data-input-checkbox input[type="checkbox"]:checked::before {
147151
transform: scale(1);
148152
}

0 commit comments

Comments
 (0)