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

Commit 1066eb6

Browse files
authored
Merge pull request #519 from trey-wallis/dev
6.14.3
2 parents f4a50e4 + 628f798 commit 1066eb6

21 files changed

+307
-291
lines changed

manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
"authorUrl": "https://github.com/trey-wallis",
88
"isDesktopOnly": false,
99
"fundingUrl": "https://www.buymeacoffee.com/treywallis",
10-
"version": "6.14.2"
10+
"version": "6.14.3"
1111
}

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "obsidian-notion-like-tables",
3-
"version": "6.14.2",
3+
"version": "6.14.3",
44
"description": "Notion-like tables for Obsidian.md",
55
"main": "main.js",
66
"scripts": {

src/data/constants.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const CURRENT_PLUGIN_VERSION = "6.14.2";
1+
export const CURRENT_PLUGIN_VERSION = "6.14.3";
22

33
export const DEFAULT_TABLE_NAME = "Untitled";
44

src/main.ts

+32-35
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Plugin, TFolder } from "obsidian";
1+
import { MarkdownView, Plugin, TFolder } from "obsidian";
22

33
import NLTSettingsTab from "./obsidian/nlt-settings-tab";
44

@@ -16,8 +16,6 @@ import {
1616
EVENT_ROW_DELETE,
1717
} from "./shared/events";
1818
import { nltEmbeddedPlugin } from "./obsidian/nlt-embedded-plugin";
19-
import { getEmbeddedTableLinkEls } from "./obsidian/utils";
20-
import NLTEmbeddedRenderChild from "./obsidian/nlt-embedded-render-child";
2119

2220
export interface NLTSettings {
2321
shouldDebug: boolean;
@@ -53,10 +51,7 @@ export default class NLTPlugin extends Plugin {
5351
async onload() {
5452
await this.loadSettings();
5553

56-
this.registerView(
57-
NOTION_LIKE_TABLES_VIEW,
58-
(leaf) => new NLTView(leaf, this.settings.shouldDebug)
59-
);
54+
this.registerView(NOTION_LIKE_TABLES_VIEW, (leaf) => new NLTView(leaf));
6055
this.registerExtensions([TABLE_EXTENSION], NOTION_LIKE_TABLES_VIEW);
6156

6257
this.addRibbonIcon("table", "Create Notion-Like table", async () => {
@@ -198,10 +193,12 @@ export default class NLTPlugin extends Plugin {
198193
name: "Add column",
199194
hotkeys: [{ modifiers: ["Mod", "Shift"], key: "\\" }],
200195
checkCallback: (checking: boolean) => {
201-
const view = this.app.workspace.getActiveViewOfType(NLTView);
202-
if (view) {
196+
const nltView = this.app.workspace.getActiveViewOfType(NLTView);
197+
const markdownView =
198+
this.app.workspace.getActiveViewOfType(MarkdownView);
199+
if (nltView || markdownView) {
203200
if (!checking) {
204-
this.app.workspace.trigger(EVENT_COLUMN_ADD, view.leaf);
201+
this.app.workspace.trigger(EVENT_COLUMN_ADD);
205202
}
206203
return true;
207204
}
@@ -214,13 +211,12 @@ export default class NLTPlugin extends Plugin {
214211
name: "Delete column",
215212
hotkeys: [{ modifiers: ["Mod", "Shift"], key: "Backspace" }],
216213
checkCallback: (checking: boolean) => {
217-
const view = this.app.workspace.getActiveViewOfType(NLTView);
218-
if (view) {
214+
const nltView = this.app.workspace.getActiveViewOfType(NLTView);
215+
const markdownView =
216+
this.app.workspace.getActiveViewOfType(MarkdownView);
217+
if (nltView || markdownView) {
219218
if (!checking) {
220-
this.app.workspace.trigger(
221-
EVENT_COLUMN_DELETE,
222-
view.leaf
223-
);
219+
this.app.workspace.trigger(EVENT_COLUMN_DELETE);
224220
}
225221
return true;
226222
}
@@ -233,10 +229,11 @@ export default class NLTPlugin extends Plugin {
233229
name: "Add row",
234230
hotkeys: [{ modifiers: ["Mod", "Shift"], key: "Enter" }],
235231
checkCallback: (checking: boolean) => {
236-
const view = this.app.workspace.getActiveViewOfType(NLTView);
237-
if (view) {
238-
if (!checking)
239-
this.app.workspace.trigger(EVENT_ROW_ADD, view.leaf);
232+
const nltView = this.app.workspace.getActiveViewOfType(NLTView);
233+
const markdownView =
234+
this.app.workspace.getActiveViewOfType(MarkdownView);
235+
if (nltView || markdownView) {
236+
if (!checking) this.app.workspace.trigger(EVENT_ROW_ADD);
240237
return true;
241238
}
242239
return false;
@@ -248,10 +245,12 @@ export default class NLTPlugin extends Plugin {
248245
name: "Delete row",
249246
hotkeys: [{ modifiers: ["Alt", "Shift"], key: "Backspace" }],
250247
checkCallback: (checking: boolean) => {
251-
const view = this.app.workspace.getActiveViewOfType(NLTView);
252-
if (view) {
248+
const nltView = this.app.workspace.getActiveViewOfType(NLTView);
249+
const markdownView =
250+
this.app.workspace.getActiveViewOfType(MarkdownView);
251+
if (nltView || markdownView) {
253252
if (!checking) {
254-
this.app.workspace.trigger(EVENT_ROW_DELETE, view.leaf);
253+
this.app.workspace.trigger(EVENT_ROW_DELETE);
255254
}
256255
return true;
257256
}
@@ -263,13 +262,12 @@ export default class NLTPlugin extends Plugin {
263262
id: "nlt-export-markdown",
264263
name: "Export as markdown",
265264
checkCallback: (checking: boolean) => {
266-
const view = this.app.workspace.getActiveViewOfType(NLTView);
267-
if (view) {
265+
const nltView = this.app.workspace.getActiveViewOfType(NLTView);
266+
const markdownView =
267+
this.app.workspace.getActiveViewOfType(MarkdownView);
268+
if (nltView || markdownView) {
268269
if (!checking) {
269-
this.app.workspace.trigger(
270-
EVENT_DOWNLOAD_MARKDOWN,
271-
view.leaf
272-
);
270+
this.app.workspace.trigger(EVENT_DOWNLOAD_MARKDOWN);
273271
}
274272
return true;
275273
}
@@ -281,13 +279,12 @@ export default class NLTPlugin extends Plugin {
281279
id: "nlt-export-csv",
282280
name: "Export as CSV",
283281
checkCallback: (checking: boolean) => {
284-
const view = this.app.workspace.getActiveViewOfType(NLTView);
285-
if (view) {
282+
const nltView = this.app.workspace.getActiveViewOfType(NLTView);
283+
const markdownView =
284+
this.app.workspace.getActiveViewOfType(MarkdownView);
285+
if (nltView || markdownView) {
286286
if (!checking) {
287-
this.app.workspace.trigger(
288-
EVENT_DOWNLOAD_CSV,
289-
view.leaf
290-
);
287+
this.app.workspace.trigger(EVENT_DOWNLOAD_CSV);
291288
}
292289
return true;
293290
}

src/obsidian/nlt-embedded-plugin.tsx

+68-52
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,24 @@ import { EVENT_REFRESH_TABLES } from "src/shared/events";
1111
import { TableState } from "src/shared/types/types";
1212
import _ from "lodash";
1313
import { getEmbeddedTableLinkEls } from "./utils";
14+
import { v4 as uuidv4 } from "uuid";
1415

1516
class NLTEmbeddedPlugin implements PluginValue {
16-
activeTables: {
17+
private tableApps: {
18+
id: string;
19+
parentEl: HTMLElement;
1720
leaf: WorkspaceLeaf;
18-
containerEl: HTMLElement;
1921
root: Root;
2022
file: TFile;
2123
}[];
2224

2325
constructor() {
24-
this.activeTables = [];
26+
this.tableApps = [];
2527
this.setupEventListeners();
2628
}
2729

2830
//This is ran on any editor change
2931
async update() {
30-
console.log("NLTEmbeddedPlugin update");
3132
const activeView = app.workspace.getActiveViewOfType(MarkdownView);
3233
if (!activeView) return;
3334

@@ -37,28 +38,39 @@ class NLTEmbeddedPlugin implements PluginValue {
3738

3839
for (let i = 0; i < embeddedTableLinkEls.length; i++) {
3940
const linkEl = embeddedTableLinkEls[i];
40-
const child = linkEl.children[0];
4141

42-
//If the child is not a title, we have already mounted an app
43-
if (!child.className.includes("file-embed-title")) return;
42+
if (linkEl.children.length === 1) {
43+
const child = linkEl.children[0];
44+
if (child.classList.contains("NLT__embedded-container"))
45+
continue;
46+
}
4447

45-
//Remove the child, we don't need it
46-
linkEl.removeChild(child);
48+
//Remove any children
49+
for (let i = 0; i < linkEl.children.length; i++) {
50+
linkEl.removeChild(linkEl.children[i]);
51+
}
4752

4853
//Get the table file that matches the src
4954
const src = linkEl.getAttribute("src")!;
50-
const tableFile = app.vault
55+
56+
let tableFile = app.vault
5157
.getFiles()
52-
.find((file) => file.name === src);
58+
.find((file) => file.path === src);
59+
if (tableFile === undefined) {
60+
tableFile = app.vault
61+
.getFiles()
62+
.find((file) => file.name === src);
63+
}
5364

54-
if (!tableFile) return;
65+
if (!tableFile) continue;
5566

5667
linkEl.style.height = "340px";
5768
linkEl.style.backgroundColor = "var(--color-primary)";
5869
linkEl.style.cursor = "unset";
5970
linkEl.style.padding = "10px 0px";
6071

6172
const containerEl = linkEl.createDiv();
73+
containerEl.className = "NLT__embedded-container";
6274
containerEl.style.height = "100%";
6375
containerEl.style.width = "100%";
6476

@@ -82,75 +94,79 @@ class NLTEmbeddedPlugin implements PluginValue {
8294
const data = await app.vault.read(tableFile);
8395
const tableState = deserializeTableState(data);
8496

85-
console.log("rendering table");
97+
const appId = uuidv4();
8698
const root = createRoot(containerEl);
87-
this.renderApp(activeView.leaf, tableFile, root, tableState);
99+
this.renderApp(appId, activeView.leaf, tableFile, root, tableState);
88100

89-
this.activeTables.push({
101+
this.tableApps.push({
102+
id: appId,
90103
leaf: activeView.leaf,
91-
containerEl,
104+
parentEl: containerEl,
92105
root,
93106
file: tableFile,
94107
});
95108
}
96109
}
97110

111+
private async handleSave(
112+
tableFile: TFile,
113+
appId: string,
114+
state: TableState
115+
) {
116+
//Save the new state
117+
const serialized = serializeTableState(state);
118+
await app.vault.modify(tableFile, serialized);
119+
120+
//Tell all other views to refresh
121+
app.workspace.trigger(
122+
EVENT_REFRESH_TABLES,
123+
tableFile.path,
124+
appId,
125+
state
126+
);
127+
}
128+
98129
private renderApp(
130+
id: string,
99131
leaf: WorkspaceLeaf,
100132
tableFile: TFile,
101133
root: Root,
102134
tableState: TableState
103135
) {
104-
async function handleSave(value: TableState) {
105-
console.log("NLTEmbeddedPlugin handleSave");
106-
//Save the new state
107-
const serialized = serializeTableState(value);
108-
await app.vault.modify(tableFile, serialized);
109-
110-
//Tell all other views to refresh
111-
app.workspace.trigger(
112-
EVENT_REFRESH_TABLES,
113-
leaf,
114-
tableFile.path,
115-
value
116-
);
117-
}
118-
119136
//Throttle the save function so we don't save too often
120-
//This is the same time as the `debounceFunction`
121-
const throttleHandleSave = _.throttle(handleSave, 2000);
137+
const throttleHandleSave = _.throttle(this.handleSave, 2000);
122138

123139
root.render(
124140
<NotionLikeTable
125-
fileName={tableFile.name}
141+
appId={id}
142+
filePath={tableFile.path}
126143
leaf={leaf}
127144
store={store}
128145
tableState={tableState}
129-
onSaveState={throttleHandleSave}
146+
onSaveState={(appId, state) =>
147+
throttleHandleSave(tableFile, appId, state)
148+
}
130149
/>
131150
);
132151
}
133152

134153
private handleRefreshEvent = (
135-
leaf: WorkspaceLeaf,
136154
filePath: string,
137-
tableState: TableState
155+
sourceAppId: string,
156+
state: TableState
138157
) => {
139-
console.log("NLTEmbeddedPlugin handleRefreshEvent");
140-
141-
const table = this.activeTables.find(
142-
(table) => table.file.path === filePath
158+
const apps = this.tableApps.filter(
159+
(app) => app.id !== sourceAppId && app.file.path === filePath
143160
);
144-
if (!table) return;
145-
const { leaf: tableLeaf } = table;
146-
if (leaf === tableLeaf) return;
147-
148-
const { containerEl, root } = table;
149-
150-
console.log("handling refresh event");
151-
root.unmount();
152-
table.root = createRoot(containerEl);
153-
this.renderApp(tableLeaf, table.file, table.root, tableState);
161+
apps.forEach((app) => {
162+
const { id, parentEl, leaf, file } = app;
163+
164+
setTimeout(() => {
165+
app.root.unmount();
166+
app.root = createRoot(parentEl);
167+
this.renderApp(id, leaf, file, app.root, state);
168+
}, 0);
169+
});
154170
};
155171

156172
private setupEventListeners() {
@@ -159,7 +175,7 @@ class NLTEmbeddedPlugin implements PluginValue {
159175
}
160176

161177
destroy() {
162-
this.activeTables.forEach((table) => table.root.unmount());
178+
this.tableApps.forEach((app) => app.root.unmount());
163179
app.workspace.off(EVENT_REFRESH_TABLES, this.handleRefreshEvent);
164180
}
165181
}

src/obsidian/nlt-embedded-render-child.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ import { NotionLikeTable } from "src/react/table-app";
44
import { store } from "src/redux/global/store";
55
import { NLTView } from "./nlt-view";
66
import { deserializeTableState } from "src/data/serialize-table-state";
7+
import { v4 as uuidv4 } from "uuid";
78

89
export default class NLTEmbeddedRenderChild extends MarkdownRenderChild {
910
private root: Root | null;
1011
private fileName: string;
12+
private appId: string;
1113

1214
constructor(containerEl: HTMLElement, fileName: string) {
1315
super(containerEl);
1416
this.root = null;
1517
this.fileName = fileName;
18+
this.appId = uuidv4();
1619
}
1720

1821
private handleSaveTableState() {}
@@ -34,7 +37,8 @@ export default class NLTEmbeddedRenderChild extends MarkdownRenderChild {
3437

3538
this.root.render(
3639
<NotionLikeTable
37-
fileName={this.fileName}
40+
appId={this.appId}
41+
filePath={file.path}
3842
leaf={activeView.leaf}
3943
store={store}
4044
tableState={state}

0 commit comments

Comments
 (0)