Skip to content

Commit 710ea3c

Browse files
committed
Signals \o/
1 parent 793ece3 commit 710ea3c

28 files changed

+300
-209
lines changed
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
---
1+
---
22
toggle: false
3-
---
4-
5-
```meta-bind
6-
INPUT[toggle(showcase):toggle]
3+
---
4+
5+
```meta-bind
6+
INPUT[toggle(showcase):toggle]
77
```

exampleVault/Meta Bind JS.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
select: d
2+
select: c
33
---
44

55
test
@@ -9,12 +9,15 @@ const declaration = mb.createDeclaration(
99
[
1010
{type: 'option', value: 'a'},
1111
{type: 'option', value: 'c'},
12-
],
13-
'select'
12+
]
1413
);
1514
15+
mb.bindDeclaration(declaration, 'select');
16+
1617
const inputField = mb.createInputField(declaration, undefined, 'block');
1718
19+
inputField.readSignal.registerListener({callback: (value) => console.log(`test ${value}`)})
20+
1821
ctx.addChild(inputField);
1922
```
2023

@@ -24,10 +27,11 @@ const declaration = mb.createDeclaration(
2427
[
2528
{type: 'option', value: 'd'},
2629
{type: 'option', value: 'e'},
27-
],
28-
'select'
30+
]
2931
);
3032
33+
mb.bindDeclaration(declaration, 'select');
34+
3135
const inputField = mb.createInputField(declaration, undefined, 'block');
3236
3337
ctx.addChild(inputField);

exampleVault/examples.md

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -72,43 +72,10 @@ Lorem ipsum dolor sit amet, `INPUT[date():other note#date]` consectetur adipisci
7272
- `INPUT[slider(nonExistantArgument)]`
7373
- `INPUT[select(option(option a),option(option b),option(option c),option(option d)):select]`
7474

75+
76+
Lorem ipsum dolor sit amet, `INPUT[text():meta bind/nonExistantFile#title]` consectetur adipiscing elit. Pellentesque sit amet porttitor arcu. Quisque scelerisque dolor augue, et posuere nulla bibendum nec. `INPUT[slider(nonExistantArgument)]` Curabitur sed rhoncus nisl. Maecenas nisi justo, viverra vel tempus vel, hendrerit at metus. `INPUT[select(option(option a),option(option b),option(option c),option(option d)):select]` asdasd asdasdasd
77+
7578
Code block error
7679
```meta-bind
7780
INPUT[slider(nonExistantArgument)]
78-
```
79-
80-
81-
82-
83-
84-
>[!info]+ Trackers
85-
>`````col
86-
>flexgrow=2
87-
>===
88-
>````col-md
89-
>##### ○ Slept
90-
>```meta-bind
91-
>INPUT[time(class(meta-bind-full-width)):Slept]
92-
>```
93-
>````
94-
>
95-
>````col-md
96-
>##### ○ Woke Up
97-
>```meta-bind
98-
>INPUT[time(class(meta-bind-full-width)):WokeUp]
99-
>```
100-
>````
101-
>````col-md
102-
>##### ○ Stretch (minutes)
103-
>```meta-bind
104-
>INPUT[number(class(meta-bind-full-width)):Stretch]
105-
>```
106-
>````
107-
>
108-
>````col-md
109-
>##### ○ Meditate (minutes)
110-
>```meta-bind
111-
>INPUT[number(class(meta-bind-full-width)):Meditate]
112-
>```
113-
>````
114-
>`````
81+
```

exampleVault/other note.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
---
2+
"1": A
3+
"2": C
4+
"6": false
25
tags: test
36
title: test
47
select: option b
@@ -37,4 +40,5 @@ option(option b),
3740
option(option c),
3841
option(option d)
3942
):select]
40-
```
43+
```
44+

src/API.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,7 @@ export class API {
4141
return new InputFieldMarkdownRenderChild(container, renderType, declaration, this.plugin, filePath, crypto.randomUUID());
4242
}
4343

44-
public createDeclaration(
45-
inputFieldType: InputFieldType,
46-
inputFieldArguments?: { type: InputFieldArgumentType; value: string }[],
47-
bindTargetField?: string,
48-
bindTargetFile?: string
49-
): InputFieldDeclaration {
50-
if (bindTargetFile && !bindTargetField) {
51-
throw new MetaBindBindTargetError('if a bind target file is specified, a bind target field must also be specified');
52-
}
53-
44+
public createDeclaration(inputFieldType: InputFieldType, inputFieldArguments?: { type: InputFieldArgumentType; value: string }[]): InputFieldDeclaration {
5445
if (this.parser.getInputFieldType(inputFieldType) === InputFieldType.INVALID) {
5546
throw new MetaBindParsingError(`input field type '${inputFieldType}' is invalid`);
5647
}
@@ -60,13 +51,24 @@ export class API {
6051
fullDeclaration: undefined,
6152
inputFieldType: inputFieldType,
6253
argumentContainer: this.parser.parseArguments(inputFieldType, inputFieldArguments),
63-
isBound: isTruthy(bindTargetField),
64-
bindTarget: bindTargetFile ? bindTargetFile + '#' + bindTargetField : bindTargetField,
54+
isBound: false,
55+
bindTarget: '',
6556
error: undefined,
6657
} as InputFieldDeclaration;
6758
}
6859

6960
public createDeclarationFromString(fullDeclaration: string): InputFieldDeclaration {
7061
return this.parser.parseString(fullDeclaration);
7162
}
63+
64+
public bindDeclaration(declaration: InputFieldDeclaration, bindTargetField: string, bindTargetFile?: string): InputFieldDeclaration {
65+
if (bindTargetFile && !bindTargetField) {
66+
throw new MetaBindBindTargetError('if a bind target file is specified, a bind target field must also be specified');
67+
}
68+
69+
declaration.isBound = isTruthy(bindTargetField);
70+
declaration.bindTarget = bindTargetFile ? bindTargetFile + '#' + bindTargetField : bindTargetField;
71+
72+
return declaration;
73+
}
7274
}

src/InlineAPI.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { API } from './API';
22
import { InputFieldArgumentType, InputFieldDeclaration, InputFieldType } from './parsers/InputFieldDeclarationParser';
33
import { InputFieldMarkdownRenderChild, RenderChildType } from './InputFieldMarkdownRenderChild';
4+
import { MetaBindBindTargetError } from './utils/MetaBindErrors';
5+
import { isTruthy } from './utils/Utils';
46

57
export class InlineAPI {
68
public api: API;
@@ -42,16 +44,15 @@ export class InlineAPI {
4244
return this.api.createInputFieldFromString(fullDeclaration, renderType, filePath, container);
4345
}
4446

45-
public createDeclaration(
46-
inputFieldType: InputFieldType,
47-
inputFieldArguments?: { type: InputFieldArgumentType; value: string }[],
48-
bindTargetField?: string,
49-
bindTargetFile?: string
50-
): InputFieldDeclaration {
51-
return this.api.createDeclaration(inputFieldType, inputFieldArguments, bindTargetField, bindTargetFile);
47+
public createDeclaration(inputFieldType: InputFieldType, inputFieldArguments?: { type: InputFieldArgumentType; value: string }[]): InputFieldDeclaration {
48+
return this.api.createDeclaration(inputFieldType, inputFieldArguments);
5249
}
5350

5451
public createDeclarationFromString(fullDeclaration: string): InputFieldDeclaration {
5552
return this.api.createDeclarationFromString(fullDeclaration);
5653
}
54+
55+
public bindDeclaration(declaration: InputFieldDeclaration, bindTargetField: string, bindTargetFile?: string): InputFieldDeclaration {
56+
return this.api.bindDeclaration(declaration, bindTargetField, bindTargetFile);
57+
}
5758
}

src/InputFieldMarkdownRenderChild.ts

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { parsePath, traverseObjectByPath } from '@opd-libs/opd-utils-lib/lib/Obj
1111
import { ShowcaseInputFieldArgument } from './inputFieldArguments/ShowcaseInputFieldArgument';
1212
import { TitleInputFieldArgument } from './inputFieldArguments/TitleInputFieldArgument';
1313
import { isTruthy } from './utils/Utils';
14+
import { Listener, Signal } from './utils/Signal';
1415

1516
export enum RenderChildType {
1617
INLINE = 'inline',
@@ -30,12 +31,19 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
3031
inputFieldDeclaration: InputFieldDeclaration;
3132
bindTargetFile: TFile | undefined;
3233
bindTargetMetadataPath: string[] | undefined;
33-
34-
intervalCounter: number;
35-
metadataValueUpdateQueue: any[];
36-
inputFieldValueUpdateQueue: any[];
37-
38-
constructor(containerEl: HTMLElement, type: RenderChildType, declaration: InputFieldDeclaration, plugin: MetaBindPlugin, filePath: string, uuid: string) {
34+
private metadataManagerReadSignalListener: Listener<any> | undefined;
35+
36+
// maybe 2: in/out
37+
/**
38+
* Signal to write to the input field
39+
*/
40+
public writeSignal: Signal<any>;
41+
/**
42+
* Signal to read from the input field
43+
*/
44+
public readSignal: Signal<any>;
45+
46+
constructor(containerEl: HTMLElement, renderChildType: RenderChildType, declaration: InputFieldDeclaration, plugin: MetaBindPlugin, filePath: string, uuid: string) {
3947
super(containerEl);
4048

4149
if (!declaration.error) {
@@ -47,24 +55,22 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
4755
this.filePath = filePath;
4856
this.uuid = uuid;
4957
this.plugin = plugin;
50-
this.renderChildType = type;
58+
this.renderChildType = renderChildType;
5159
this.fullDeclaration = declaration.fullDeclaration;
52-
53-
this.metadataValueUpdateQueue = [];
54-
this.inputFieldValueUpdateQueue = [];
55-
this.intervalCounter = 0;
5660
this.inputFieldDeclaration = declaration;
5761

62+
this.writeSignal = new Signal<any>(undefined);
63+
this.readSignal = new Signal<any>(undefined);
64+
5865
if (!this.error) {
5966
try {
6067
if (this.inputFieldDeclaration.isBound) {
6168
this.parseBindTarget();
6269
}
6370

6471
this.inputField = InputFieldFactory.createInputField(this.inputFieldDeclaration.inputFieldType, {
65-
type: type,
72+
renderChildType: renderChildType,
6673
inputFieldMarkdownRenderChild: this,
67-
onValueChanged: this.updateMetadataManager.bind(this),
6874
});
6975
} catch (e: any) {
7076
this.error = e.message;
@@ -113,35 +119,31 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
113119
}
114120

115121
registerSelfToMetadataManager(): MetadataFileCache | undefined {
122+
// if bind target is invalid, return
116123
if (!this.inputFieldDeclaration?.isBound || !this.bindTargetFile || !this.bindTargetMetadataPath || this.bindTargetMetadataPath?.length === 0) {
117124
return;
118125
}
119126

120-
return this.plugin.metadataManager.register(
121-
this.bindTargetFile,
122-
value => {
123-
if (!this.inputField) {
124-
throw new MetaBindInternalError('inputField is undefined, can not update inputField');
125-
}
127+
this.metadataManagerReadSignalListener = this.readSignal.registerListener({ callback: this.updateMetadataManager.bind(this) });
126128

127-
if (!this.inputField.isEqualValue(value)) {
128-
this.inputField.setValue(value);
129-
}
130-
},
131-
this.bindTargetMetadataPath,
132-
this.uuid
133-
);
129+
return this.plugin.metadataManager.register(this.bindTargetFile, this.writeSignal, this.bindTargetMetadataPath, this.uuid);
134130
}
135131

136132
unregisterSelfFromMetadataManager(): void {
133+
// if bind target is invalid, return
137134
if (!this.inputFieldDeclaration?.isBound || !this.bindTargetFile || !this.bindTargetMetadataPath || this.bindTargetMetadataPath?.length === 0) {
138135
return;
139136
}
140137

138+
if (this.metadataManagerReadSignalListener) {
139+
this.readSignal.unregisterListener(this.metadataManagerReadSignalListener);
140+
}
141+
141142
this.plugin.metadataManager.unregister(this.bindTargetFile, this.uuid);
142143
}
143144

144145
updateMetadataManager(value: any): void {
146+
// if bind target is invalid, return
145147
if (!this.inputFieldDeclaration?.isBound || !this.bindTargetFile || !this.bindTargetMetadataPath || this.bindTargetMetadataPath?.length === 0) {
146148
return;
147149
}
@@ -179,32 +181,31 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
179181
);
180182
}
181183

184+
hasValidBindTarget(): boolean {
185+
return isTruthy(this.inputFieldDeclaration?.isBound) && isTruthy(this.bindTargetFile) && isTruthy(this.bindTargetMetadataPath) && this.bindTargetMetadataPath?.length !== 0;
186+
}
187+
182188
async onload(): Promise<void> {
183189
console.log('meta-bind | InputFieldMarkdownRenderChild >> load', this);
184190

191+
this.containerEl.addClass('meta-bind-plugin-input');
192+
185193
const container: HTMLDivElement = createDiv();
186194
container.addClass('meta-bind-plugin-input-wrapper');
187-
this.containerEl.addClass('meta-bind-plugin-input');
188195

189196
if (this.error) {
190-
this.containerEl.empty();
191-
this.containerEl.createEl('span', { text: this.fullDeclaration, cls: 'meta-bind-code' });
192-
container.innerText = ` -> ERROR: ${this.error}`;
193-
container.addClass('meta-bind-plugin-error');
194-
this.containerEl.appendChild(container);
197+
this.renderError(this.error);
195198
return;
196199
}
197200

198201
if (!this.inputField) {
199-
this.containerEl.empty();
200-
this.containerEl.createEl('span', { text: this.fullDeclaration, cls: 'meta-bind-code' });
201-
container.innerText = ` -> ERROR: ${new MetaBindInternalError('input field is undefined and error is empty').message}`;
202-
container.addClass('meta-bind-plugin-error');
203-
this.containerEl.appendChild(container);
202+
this.renderError(new MetaBindInternalError('input field is undefined and error is empty').message);
204203
return;
205204
}
206205

207-
this.metadataCache = this.registerSelfToMetadataManager();
206+
if (this.hasValidBindTarget()) {
207+
this.metadataCache = this.registerSelfToMetadataManager();
208+
}
208209
this.plugin.registerInputFieldMarkdownRenderChild(this);
209210

210211
this.inputField.render(container);
@@ -236,6 +237,20 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
236237
}
237238
}
238239

240+
renderError(message: string): void {
241+
this.containerEl.empty();
242+
243+
if (this.renderChildType === RenderChildType.BLOCK) {
244+
const cardContainer: HTMLDivElement = this.containerEl.createDiv({ cls: 'meta-bind-plugin-card' });
245+
246+
cardContainer.createEl('code', { text: ` ${this.fullDeclaration} ` });
247+
cardContainer.createEl('span', { text: message, cls: 'meta-bind-plugin-error' });
248+
} else {
249+
this.containerEl.createEl('code', { text: ` ${this.fullDeclaration}` });
250+
this.containerEl.createEl('code', { text: `-> ${message}`, cls: 'meta-bind-plugin-error' });
251+
}
252+
}
253+
239254
onunload(): void {
240255
console.log('meta-bind | InputFieldMarkdownRenderChild >> unload', this);
241256

@@ -244,7 +259,7 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
244259
this.unregisterSelfFromMetadataManager();
245260

246261
this.containerEl.empty();
247-
this.containerEl.remove();
262+
this.containerEl.createEl('span', { text: 'unloaded meta bind input field', cls: 'meta-bind-plugin-error' });
248263

249264
super.onunload();
250265
}

0 commit comments

Comments
 (0)