Skip to content

Commit 4c4d3d2

Browse files
committed
Merge branch 'main' into eng-1283-allow-node-sharing-with-groups
2 parents 79a6790 + 7195930 commit 4c4d3d2

28 files changed

Lines changed: 319 additions & 259 deletions

apps/obsidian/src/components/BulkIdentifyDiscourseNodesModal.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { BulkImportCandidate, BulkImportPattern } from "~/types";
66
import { QueryEngine } from "~/services/QueryEngine";
77
import { TFile } from "obsidian";
88
import { getNodeTypeById } from "~/utils/typeUtils";
9+
import { FrontmatterRecord } from "./canvas/shapes/discourseNodeShapeUtils";
910

1011
type BulkImportModalProps = {
1112
plugin: DiscourseGraphPlugin;
@@ -63,7 +64,7 @@ const BulkImportContent = ({ plugin, onClose }: BulkImportModalProps) => {
6364
);
6465
};
6566

66-
const handleScanVault = useCallback(async () => {
67+
const handleScanVault = useCallback(() => {
6768
const enabledPatterns = patterns.filter(
6869
(p) => p.enabled && p.alternativePattern.trim(),
6970
);
@@ -77,7 +78,7 @@ const BulkImportContent = ({ plugin, onClose }: BulkImportModalProps) => {
7778
try {
7879
const validNodeTypes = plugin.settings.nodeTypes;
7980
const foundCandidates =
80-
await queryEngineRef.current.scanForBulkImportCandidates(
81+
queryEngineRef.current.scanForBulkImportCandidates(
8182
enabledPatterns,
8283
validNodeTypes,
8384
);
@@ -127,7 +128,7 @@ const BulkImportContent = ({ plugin, onClose }: BulkImportModalProps) => {
127128
try {
128129
await plugin.app.fileManager.processFrontMatter(
129130
candidate.file,
130-
(fm) => {
131+
(fm: FrontmatterRecord) => {
131132
fm.nodeTypeId = candidate.matchedNodeType.id;
132133
},
133134
);
@@ -376,7 +377,7 @@ const BulkImportContent = ({ plugin, onClose }: BulkImportModalProps) => {
376377
<div className="mt-6 flex justify-between">
377378
<button onClick={() => setStep("patterns")}>Back</button>
378379
<button
379-
onClick={handleBulkIdentify}
380+
onClick={() => void handleBulkIdentify()}
380381
className="!bg-accent !text-on-accent rounded px-4 py-2"
381382
disabled={candidates.filter((c) => c.selected).length === 0}
382383
>

apps/obsidian/src/components/DiscourseContextView.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ export class DiscourseContextView extends ItemView {
248248
return "telescope";
249249
}
250250

251+
// eslint-disable-next-line @typescript-eslint/require-await -- required by obsidian
251252
async onOpen(): Promise<void> {
252253
const container = this.containerEl.children[1];
253254
if (container) {
@@ -279,6 +280,7 @@ export class DiscourseContextView extends ItemView {
279280
}
280281
}
281282

283+
// eslint-disable-next-line @typescript-eslint/require-await -- required by obsidian
282284
async onClose(): Promise<void> {
283285
if (this.root) {
284286
this.root.unmount();

apps/obsidian/src/components/GeneralSettings.tsx

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,27 @@
1-
import { useState, useCallback, useRef, useEffect } from "react";
1+
import { useState, useCallback } from "react";
22
import { usePlugin } from "./PluginContext";
33
import { setIcon } from "obsidian";
44
import SuggestInput from "./SuggestInput";
5-
import { SLACK_LOGO, WHITE_LOGO_SVG } from "~/icons";
5+
import { DiscourseGraphLogoIcon, SlackLogoIcon } from "./Icons";
66

77
const DOCS_URL = "https://discoursegraphs.com/docs/obsidian";
88
const COMMUNITY_URL =
99
"https://join.slack.com/t/discoursegraphs/shared_invite/zt-37xklatti-cpEjgPQC0YyKYQWPNgAkEg";
1010

1111
const InfoSection = () => {
1212
const plugin = usePlugin();
13-
const logoRef = useRef<HTMLDivElement>(null);
14-
const communityIconRef = useRef<HTMLDivElement>(null);
15-
16-
useEffect(() => {
17-
if (logoRef.current) {
18-
logoRef.current.innerHTML = WHITE_LOGO_SVG;
19-
}
20-
if (communityIconRef.current) {
21-
communityIconRef.current.innerHTML = SLACK_LOGO;
22-
}
23-
}, []);
24-
2513
return (
2614
<div className="flex justify-center">
2715
<div
2816
className="flex w-48 flex-col items-center rounded-lg p-3"
2917
style={{ background: "var(--tag-background)" }}
3018
>
3119
<div
32-
ref={logoRef}
3320
className="flex h-12 w-12 items-center justify-center"
3421
style={{ color: "var(--interactive-accent)" }}
35-
/>
22+
>
23+
<DiscourseGraphLogoIcon />
24+
</div>
3625
<div
3726
className="font-semibold"
3827
style={{ color: "var(--interactive-accent)" }}
@@ -48,7 +37,9 @@ const InfoSection = () => {
4837
rel="noopener noreferrer"
4938
aria-label="Community"
5039
>
51-
<div ref={communityIconRef} className="icon" />
40+
<span className="icon flex items-center">
41+
<SlackLogoIcon />
42+
</span>
5243
<span>Community</span>
5344
<span
5445
className="icon"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from "react";
2+
3+
export const DiscourseGraphLogoIcon = (): React.ReactElement => (
4+
<svg
5+
width="32"
6+
height="32"
7+
viewBox="0 0 256 264"
8+
fill="none"
9+
xmlns="http://www.w3.org/2000/svg"
10+
aria-hidden
11+
>
12+
<path
13+
fillRule="evenodd"
14+
clipRule="evenodd"
15+
d="M156.705 252.012C140.72 267.995 114.803 267.995 98.8183 252.012L11.9887 165.182C-3.99622 149.197 -3.99622 123.28 11.9886 107.296L55.4035 63.8807C63.3959 55.8881 76.3541 55.8881 84.3467 63.8807C92.3391 71.8731 92.3391 84.8313 84.3467 92.8239L69.8751 107.296C53.8901 123.28 53.8901 149.197 69.8751 165.182L113.29 208.596C121.282 216.589 134.241 216.589 142.233 208.596C150.225 200.604 150.225 187.646 142.233 179.653L127.761 165.182C111.777 149.197 111.777 123.28 127.761 107.296C143.746 91.3105 143.746 65.3939 127.761 49.4091L113.29 34.9375C105.297 26.9452 105.297 13.9868 113.29 5.99432C121.282 -1.99811 134.241 -1.99811 142.233 5.99434L243.533 107.296C259.519 123.28 259.519 149.197 243.533 165.182L156.705 252.012ZM200.119 121.767C192.127 113.775 179.168 113.775 171.176 121.767C163.184 129.76 163.184 142.718 171.176 150.71C179.168 158.703 192.127 158.703 200.119 150.71C208.112 142.718 208.112 129.76 200.119 121.767Z"
16+
fill="currentColor"
17+
/>
18+
</svg>
19+
);
20+
21+
export const SlackLogoIcon = (): React.ReactElement => (
22+
<svg
23+
width="16"
24+
height="16"
25+
viewBox="0 0 127 127"
26+
xmlns="http://www.w3.org/2000/svg"
27+
aria-hidden
28+
>
29+
<path
30+
d="M27.2 80c0 7.3-5.9 13.2-13.2 13.2C6.7 93.2.8 87.3.8 80c0-7.3 5.9-13.2 13.2-13.2h13.2V80zm6.6 0c0-7.3 5.9-13.2 13.2-13.2 7.3 0 13.2 5.9 13.2 13.2v33c0 7.3-5.9 13.2-13.2 13.2-7.3 0-13.2-5.9-13.2-13.2V80z"
31+
fill="currentColor"
32+
/>
33+
<path
34+
d="M47 27c-7.3 0-13.2-5.9-13.2-13.2C33.8 6.5 39.7.6 47 .6c7.3 0 13.2 5.9 13.2 13.2V27H47zm0 6.7c7.3 0 13.2 5.9 13.2 13.2 0 7.3-5.9 13.2-13.2 13.2H13.9C6.6 60.1.7 54.2.7 46.9c0-7.3 5.9-13.2 13.2-13.2H47z"
35+
fill="currentColor"
36+
/>
37+
<path
38+
d="M99.9 46.9c0-7.3 5.9-13.2 13.2-13.2 7.3 0 13.2 5.9 13.2 13.2 0 7.3-5.9 13.2-13.2 13.2H99.9V46.9zm-6.6 0c0 7.3-5.9 13.2-13.2 13.2-7.3 0-13.2-5.9-13.2-13.2V13.8C66.9 6.5 72.8.6 80.1.6c7.3 0 13.2 5.9 13.2 13.2v33.1z"
39+
fill="currentColor"
40+
/>
41+
<path
42+
d="M80.1 99.8c7.3 0 13.2 5.9 13.2 13.2 0 7.3-5.9 13.2-13.2 13.2-7.3 0-13.2-5.9-13.2-13.2V99.8h13.2zm0-6.6c-7.3 0-13.2-5.9-13.2-13.2 0-7.3 5.9-13.2 13.2-13.2h33.1c7.3 0 13.2 5.9 13.2 13.2 0 7.3-5.9 13.2-13.2 13.2H80.1z"
43+
fill="currentColor"
44+
/>
45+
</svg>
46+
);

apps/obsidian/src/components/InlineNodeTypePicker.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class InlineNodeTypePicker {
3636
const rect = range.getBoundingClientRect();
3737

3838
if (rect.width === 0 && rect.height === 0) {
39-
const span = document.createElement("span");
39+
const span = createSpan();
4040
span.textContent = "\u200B";
4141
range.insertNode(span);
4242
const spanRect = span.getBoundingClientRect();
@@ -54,10 +54,10 @@ export class InlineNodeTypePicker {
5454
}
5555

5656
private createPopover(): HTMLElement {
57-
const popover = document.createElement("div");
57+
const popover = createDiv();
5858
popover.className =
5959
"inline-node-type-picker fixed z-[10000] bg-primary border border-modifier-border rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.15)] max-h-[300px] overflow-y-auto min-w-[200px] max-w-[400px]";
60-
const itemsContainer = document.createElement("div");
60+
const itemsContainer = createDiv();
6161
itemsContainer.className = "inline-node-type-items-container";
6262
popover.appendChild(itemsContainer);
6363

@@ -70,28 +70,28 @@ export class InlineNodeTypePicker {
7070
container.innerHTML = "";
7171

7272
if (this.items.length === 0) {
73-
const noResults = document.createElement("div");
73+
const noResults = createDiv();
7474
noResults.className = "p-3 text-center text-muted text-sm";
7575
noResults.textContent = "No node types available";
7676
container.appendChild(noResults);
7777
return;
7878
}
7979

8080
this.items.forEach((item, index) => {
81-
const itemEl = document.createElement("div");
81+
const itemEl = createDiv();
8282
itemEl.className = `inline-node-type-item px-3 py-2 cursor-pointer flex items-center gap-2 border-b border-[var(--background-modifier-border-hover)]${
8383
index === this.selectedIndex ? " bg-modifier-hover" : ""
8484
}`;
8585
itemEl.dataset.index = index.toString();
8686

8787
if (item.color) {
88-
const colorDot = document.createElement("div");
88+
const colorDot = createDiv();
8989
colorDot.className = "w-3 h-3 rounded-full shrink-0";
9090
colorDot.style.backgroundColor = item.color;
9191
itemEl.appendChild(colorDot);
9292
}
9393

94-
const nameText = document.createElement("div");
94+
const nameText = createDiv();
9595
nameText.textContent = item.name;
9696
nameText.className = "font-medium text-normal text-sm";
9797
itemEl.appendChild(nameText);
@@ -201,17 +201,25 @@ export class InlineNodeTypePicker {
201201
}
202202
};
203203

204-
document.addEventListener("keydown", this.keydownHandler, true);
205-
document.addEventListener("mousedown", this.clickOutsideHandler, true);
204+
activeDocument.addEventListener("keydown", this.keydownHandler, true);
205+
activeDocument.addEventListener(
206+
"mousedown",
207+
this.clickOutsideHandler,
208+
true,
209+
);
206210
}
207211

208212
private removeEventHandlers() {
209213
if (this.keydownHandler) {
210-
document.removeEventListener("keydown", this.keydownHandler, true);
214+
activeDocument.removeEventListener("keydown", this.keydownHandler, true);
211215
this.keydownHandler = null;
212216
}
213217
if (this.clickOutsideHandler) {
214-
document.removeEventListener("mousedown", this.clickOutsideHandler, true);
218+
activeDocument.removeEventListener(
219+
"mousedown",
220+
this.clickOutsideHandler,
221+
true,
222+
);
215223
this.clickOutsideHandler = null;
216224
}
217225
}
@@ -225,7 +233,7 @@ export class InlineNodeTypePicker {
225233
if (!position) return;
226234

227235
this.popover = this.createPopover();
228-
document.body.appendChild(this.popover);
236+
activeDocument.body.appendChild(this.popover);
229237

230238
const popoverRect = this.popover.getBoundingClientRect();
231239
const viewportWidth = window.innerWidth;

apps/obsidian/src/components/ModifyNodeModal.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,21 +114,19 @@ export const ModifyNodeForm = ({
114114
}
115115

116116
if (debounceTimeoutRef.current) {
117-
clearTimeout(debounceTimeoutRef.current);
117+
window.clearTimeout(debounceTimeoutRef.current);
118118
}
119119

120120
setIsSearching(true);
121121
debounceTimeoutRef.current = window.setTimeout(() => {
122-
void (async () => {
122+
void (() => {
123123
try {
124124
const results = selectedNodeType
125-
? await queryEngine.current.searchDiscourseNodesByTitle(
125+
? queryEngine.current.searchDiscourseNodesByTitle(
126126
searchQuery,
127127
selectedNodeType.id,
128128
)
129-
: await queryEngine.current.searchDiscourseNodesByTitle(
130-
searchQuery,
131-
);
129+
: queryEngine.current.searchDiscourseNodesByTitle(searchQuery);
132130
setSearchResults(results);
133131
} catch (error) {
134132
console.error("Error searching nodes:", error);
@@ -140,7 +138,7 @@ export const ModifyNodeForm = ({
140138
}, 250);
141139
return () => {
142140
if (debounceTimeoutRef.current) {
143-
clearTimeout(debounceTimeoutRef.current);
141+
window.clearTimeout(debounceTimeoutRef.current);
144142
}
145143
};
146144
}, [query, selectedNodeType, isEditMode, disableExistingNodeSearch]);

apps/obsidian/src/components/NodeTagSuggestModal.tsx

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class NodeTagSuggestPopover {
4545

4646
// If the rect has no dimensions (collapsed cursor), try using a temporary span to get cursor position
4747
if (rect.width === 0 && rect.height === 0) {
48-
const span = document.createElement("span");
48+
const span = activeDocument.createElement("span");
4949
span.textContent = "\u200B";
5050
range.insertNode(span);
5151
const spanRect = span.getBoundingClientRect();
@@ -73,11 +73,11 @@ export class NodeTagSuggestPopover {
7373
}
7474

7575
private createPopover(): HTMLElement {
76-
const popover = document.createElement("div");
76+
const popover = activeDocument.createElement("div");
7777
popover.className =
7878
"node-tag-suggest-popover fixed z-[10000] bg-primary border border-modifier-border rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.15)] max-h-[300px] overflow-y-auto min-w-[200px] max-w-[400px]";
7979

80-
const itemsContainer = document.createElement("div");
80+
const itemsContainer = activeDocument.createElement("div");
8181
itemsContainer.className = "node-tag-items-container";
8282
popover.appendChild(itemsContainer);
8383

@@ -90,35 +90,35 @@ export class NodeTagSuggestPopover {
9090
container.innerHTML = "";
9191

9292
if (this.items.length === 0) {
93-
const noResults = document.createElement("div");
93+
const noResults = activeDocument.createElement("div");
9494
noResults.className = "p-3 text-center text-muted text-sm";
9595
noResults.textContent = "No node tags available";
9696
container.appendChild(noResults);
9797
return;
9898
}
9999

100100
this.items.forEach((item, index) => {
101-
const itemEl = document.createElement("div");
101+
const itemEl = activeDocument.createElement("div");
102102
itemEl.className = `node-tag-item px-3 py-2 cursor-pointer flex items-center gap-2 border-b border-[var(--background-modifier-border-hover)]${
103103
index === this.selectedIndex ? " bg-modifier-hover" : ""
104104
}`;
105105
itemEl.dataset.index = index.toString();
106106

107107
if (item.nodeType.color) {
108-
const colorDot = document.createElement("div");
108+
const colorDot = activeDocument.createElement("div");
109109
colorDot.className = `w-3 h-3 rounded-full shrink-0`;
110110
colorDot.style.backgroundColor = item.nodeType.color;
111111
itemEl.appendChild(colorDot);
112112
}
113113

114-
const textContainer = document.createElement("div");
114+
const textContainer = activeDocument.createElement("div");
115115
textContainer.className = "flex flex-col gap-0.5 flex-1";
116116

117-
const tagText = document.createElement("div");
117+
const tagText = activeDocument.createElement("div");
118118
tagText.textContent = `#${item.tag}`;
119119
tagText.className = "font-medium text-normal text-sm";
120120

121-
const nodeTypeText = document.createElement("div");
121+
const nodeTypeText = activeDocument.createElement("div");
122122
nodeTypeText.textContent = item.nodeType.name;
123123
nodeTypeText.className = "text-xs text-muted";
124124

@@ -224,17 +224,25 @@ export class NodeTagSuggestPopover {
224224
}
225225
};
226226

227-
document.addEventListener("keydown", this.keydownHandler, true);
228-
document.addEventListener("mousedown", this.clickOutsideHandler, true);
227+
activeDocument.addEventListener("keydown", this.keydownHandler, true);
228+
activeDocument.addEventListener(
229+
"mousedown",
230+
this.clickOutsideHandler,
231+
true,
232+
);
229233
}
230234

231235
private removeEventHandlers() {
232236
if (this.keydownHandler) {
233-
document.removeEventListener("keydown", this.keydownHandler, true);
237+
activeDocument.removeEventListener("keydown", this.keydownHandler, true);
234238
this.keydownHandler = null;
235239
}
236240
if (this.clickOutsideHandler) {
237-
document.removeEventListener("mousedown", this.clickOutsideHandler, true);
241+
activeDocument.removeEventListener(
242+
"mousedown",
243+
this.clickOutsideHandler,
244+
true,
245+
);
238246
this.clickOutsideHandler = null;
239247
}
240248
}
@@ -251,7 +259,7 @@ export class NodeTagSuggestPopover {
251259
}
252260

253261
this.popover = this.createPopover();
254-
document.body.appendChild(this.popover);
262+
activeDocument.body.appendChild(this.popover);
255263

256264
const popoverRect = this.popover.getBoundingClientRect();
257265
const viewportWidth = window.innerWidth;

0 commit comments

Comments
 (0)