Skip to content

Commit d1a20b0

Browse files
committed
fix #249
1 parent f9f99e8 commit d1a20b0

File tree

20 files changed

+375
-183
lines changed

20 files changed

+375
-183
lines changed

exampleVault/Button Example.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
---
2-
count: 0
2+
count: -1
33
someList:
44
- 1708945050652
5+
- 1709918700548
6+
count2: 0
57
---
68
Meta Bind is getting Buttons
79

exampleVault/Examples.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
slider1: 5
2+
slider1: 6
33
suggest: test
44
toggle1: false
55
Domestic_tasks:
@@ -13,7 +13,7 @@ inlineSelect: 0
1313
nested:
1414
object: test
1515
number1: 2
16-
number2: 10
16+
number2: 12
1717
time:
1818
---
1919

packages/core/src/api/API.ts

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ import {
3737
type SimpleInlineButtonDeclaration,
3838
} from 'packages/core/src/parsers/ButtonParser';
3939
import { JsViewFieldParser } from 'packages/core/src/parsers/viewFieldParser/JsViewFieldParser';
40+
import { Signal } from 'packages/core/src/utils/Signal';
41+
import { parsePropPath } from 'packages/core/src/utils/prop/PropParser';
42+
import { type BindTargetDeclaration } from 'packages/core/src/parsers/bindTargetParser/BindTargetDeclaration';
43+
import { type MetadataSubscription } from 'packages/core/src/metadata/MetadataSubscription';
4044

4145
export enum FieldType {
4246
INPUT_FIELD = 'INPUT_FIELD',
@@ -410,4 +414,167 @@ export abstract class API<Plugin extends IPlugin> {
410414

411415
return undefined;
412416
}
417+
418+
public createSignal<T>(value: T): Signal<T> {
419+
return new Signal<T>(value);
420+
}
421+
422+
/**
423+
* Sets a property in meta binds metadata cache.
424+
*
425+
* @param storageType
426+
* @param storagePath
427+
* @param property the property path a.b.c = ['a', 'b', 'c']
428+
* @param value
429+
*/
430+
public setMetadata(storageType: string, storagePath: string, property: string[], value: unknown): void {
431+
this.plugin.metadataManager.write(value, {
432+
storageType: storageType,
433+
storagePath: storagePath,
434+
storageProp: parsePropPath(property),
435+
listenToChildren: false,
436+
});
437+
}
438+
439+
/**
440+
* Sets a property in meta binds metadata cache.
441+
*
442+
* @param bindTarget
443+
* @param value
444+
*/
445+
public setMetadataWithBindTarget(bindTarget: BindTargetDeclaration, value: unknown): void {
446+
this.plugin.metadataManager.write(value, bindTarget);
447+
}
448+
449+
/**
450+
* Reads a property from meta binds metadata cache.
451+
* If the value is not present in the cache, it will check the underlying source. E.g. Obsidians metadata cache.
452+
*
453+
* @param storageType
454+
* @param storagePath
455+
* @param property the property path a.b.c = ['a', 'b', 'c']
456+
*/
457+
public getMetadata(storageType: string, storagePath: string, property: string[]): unknown {
458+
return this.plugin.metadataManager.read({
459+
storageType: storageType,
460+
storagePath: storagePath,
461+
storageProp: parsePropPath(property),
462+
listenToChildren: false,
463+
});
464+
}
465+
466+
/**
467+
* Reads a property from meta binds metadata cache.
468+
* If the value is not present in the cache, it will check the underlying source. E.g. Obsidians metadata cache.
469+
*
470+
* @param bindTarget
471+
*/
472+
public getMetadataWithBindTarget(bindTarget: BindTargetDeclaration): unknown {
473+
return this.plugin.metadataManager.read(bindTarget);
474+
}
475+
476+
/**
477+
* Updates a property in meta binds metadata cache.
478+
*
479+
* @param storageType
480+
* @param storagePath
481+
* @param property the property path a.b.c = ['a', 'b', 'c']
482+
* @param updateFn a function that takes the current value and returns the new value
483+
*/
484+
public updateMetadata(
485+
storageType: string,
486+
storagePath: string,
487+
property: string[],
488+
updateFn: (value: unknown) => unknown,
489+
): void {
490+
const bindTarget: BindTargetDeclaration = {
491+
storageType: storageType,
492+
storagePath: storagePath,
493+
storageProp: parsePropPath(property),
494+
listenToChildren: false,
495+
};
496+
497+
const value = this.plugin.metadataManager.read(bindTarget);
498+
const newValue = updateFn(value);
499+
this.plugin.metadataManager.write(newValue, bindTarget);
500+
}
501+
502+
/**
503+
* Updates a property in meta binds metadata cache.
504+
*
505+
* @param bindTarget
506+
* @param updateFn a function that takes the current value and returns the new value
507+
*/
508+
public updateMetadataWithBindTarget(
509+
bindTarget: BindTargetDeclaration,
510+
updateFn: (value: unknown) => unknown,
511+
): void {
512+
const value = this.plugin.metadataManager.read(bindTarget);
513+
const newValue = updateFn(value);
514+
this.plugin.metadataManager.write(newValue, bindTarget);
515+
}
516+
517+
/**
518+
* Subscribes to a property in meta binds metadata cache.
519+
* This returns a subscription that can be used to unsubscribe as well as update the cache.
520+
* IF YOU DON'T CALL `unsubscribe` THE SUBSCRIPTION WILL LEAK MEMORY.
521+
*
522+
* @param storageType
523+
* @param storagePath
524+
* @param property the property path a.b.c = ['a', 'b', 'c']
525+
* @param listenToChildren
526+
* @param callback
527+
*/
528+
public subscribeToMetadata(
529+
storageType: string,
530+
storagePath: string,
531+
property: string[],
532+
listenToChildren: boolean,
533+
callback: (value: unknown) => void,
534+
): MetadataSubscription {
535+
const uuid = getUUID();
536+
const signal = new Signal<unknown>(undefined);
537+
538+
signal.registerListener({
539+
callback: callback,
540+
});
541+
542+
return this.plugin.metadataManager.subscribe(
543+
uuid,
544+
signal,
545+
{
546+
storageType: storageType,
547+
storagePath: storagePath,
548+
storageProp: parsePropPath(property),
549+
listenToChildren: listenToChildren,
550+
},
551+
(): void => {
552+
signal.unregisterAllListeners();
553+
},
554+
);
555+
}
556+
557+
/**
558+
* Subscribes to a property in meta binds metadata cache.
559+
* This returns a subscription that can be used to unsubscribe as well as update the cache.
560+
* IF YOU DON'T CALL `unsubscribe` THE SUBSCRIPTION WILL LEAK MEMORY.
561+
*
562+
* @param bindTarget
563+
* @param callback
564+
*/
565+
public subscribeToMetadataWithBindTarget(
566+
bindTarget: BindTargetDeclaration,
567+
callback: (value: unknown) => void,
568+
): MetadataSubscription {
569+
const uuid = getUUID();
570+
const signal = new Signal<unknown>(undefined);
571+
572+
signal.registerListener({
573+
callback: callback,
574+
});
575+
576+
return this.plugin.metadataManager.subscribe(uuid, signal, bindTarget, (): void => {
577+
signal.unregisterAllListeners();
578+
});
579+
}
413580
}

packages/core/src/fields/button/ButtonActionRunner.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import {
1414
type UpdateMetadataButtonAction,
1515
} from 'packages/core/src/config/ButtonConfig';
1616
import { MDLinkParser } from 'packages/core/src/parsers/MarkdownLinkParser';
17-
import { Signal } from 'packages/core/src/utils/Signal';
18-
import { expectType, getUUID, openURL } from 'packages/core/src/utils/Utils';
17+
import { expectType, openURL } from 'packages/core/src/utils/Utils';
18+
import { parseLiteral } from 'packages/core/src/utils/Literal';
1919

2020
export class ButtonActionRunner {
2121
plugin: IPlugin;
@@ -187,14 +187,15 @@ export class ButtonActionRunner {
187187

188188
async runUpdateMetadataAction(action: UpdateMetadataButtonAction, filePath: string): Promise<void> {
189189
const bindTarget = this.plugin.api.bindTargetParser.fromStringAndValidate(action.bindTarget, filePath);
190-
const uuid = getUUID();
191-
const signal = new Signal<unknown>(undefined);
192-
const subscription = this.plugin.metadataManager.subscribe(uuid, signal, bindTarget, () => {});
193-
subscription.applyUpdate({
194-
value: action.value,
195-
evaluate: action.evaluate,
196-
});
197-
subscription.unsubscribe();
190+
191+
if (action.evaluate) {
192+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
193+
const func = new Function('x', `return ${action.value};`) as (value: unknown) => unknown;
194+
195+
this.plugin.api.updateMetadataWithBindTarget(bindTarget, func);
196+
} else {
197+
this.plugin.api.setMetadataWithBindTarget(bindTarget, parseLiteral(action.value));
198+
}
198199
}
199200

200201
async runCreateNoteAction(action: CreateNoteButtonAction): Promise<void> {

packages/core/src/fields/button/ButtonManager.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,6 @@ export class ButtonManager {
147147

148148
const fileButtons = this.buttons.get(filePath)!;
149149

150-
if (fileButtons.has(button.id)) {
151-
if (JSON.stringify(fileButtons.get(button.id)?.getValue()) === JSON.stringify(button)) {
152-
fileButtons.get(button.id)?.increment();
153-
return;
154-
} else {
155-
throw new Error(`ButtonManager | button with id "${button.id}" already exists`);
156-
}
157-
}
158-
159150
fileButtons.set(button.id, new RefCounter(button));
160151
this.notifyButtonLoadListeners(filePath, button.id);
161152
}

packages/core/src/fields/inputFields/fields/InlineListSuggester/InlineListSuggesterComponent.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import Icon from '../../../../utils/components/Icon.svelte';
3-
import { MBLiteral, stringifyLiteral } from '../../../../utils/Literal';
3+
import { MBLiteral } from '../../../../utils/Literal';
44
import LiteralRenderComponent from '../../../../utils/components/LiteralRenderComponent.svelte';
55
import { IPlugin } from '../../../../IPlugin';
66
import { ContextMenuItemDefinition } from 'packages/core/src/utils/IContextMenu';

packages/core/src/fields/inputFields/fields/ListSuggester/ListSuggesterComponent.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import Icon from '../../../../utils/components/Icon.svelte';
3-
import { MBLiteral, stringifyLiteral } from '../../../../utils/Literal';
3+
import { MBLiteral } from '../../../../utils/Literal';
44
import LiteralRenderComponent from '../../../../utils/components/LiteralRenderComponent.svelte';
55
import Button from '../../../../utils/components/Button.svelte';
66
import { IPlugin } from '../../../../IPlugin';

packages/core/src/metadata/ComputedMetadataSubscription.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ export class ComputedMetadataSubscription implements IMetadataSubscription {
7676
const values = this.dependencySubscriptions.map(x => x.callbackSignal.get());
7777
const value = await this.computeFunction(values);
7878
this.callbackSignal.set(value);
79-
this.metadataManager.update(value, this);
79+
if (this.bindTarget !== undefined) {
80+
this.metadataManager.write(value, this.bindTarget, this.uuid);
81+
}
8082
}
8183

8284
/**

packages/core/src/metadata/InternalMetadataSources.ts

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import { type PropPath } from 'packages/core/src/utils/prop/PropPath';
1616
import { PropUtils } from 'packages/core/src/utils/prop/PropUtils';
1717

1818
export class InternalMetadataSource extends FilePathMetadataSource<FilePathMetadataCacheItem> {
19+
public readExternal(_storagePath: string): Metadata {
20+
return {};
21+
}
22+
1923
public getDefaultCacheItem(storagePath: string): FilePathMetadataCacheItem {
2024
return {
2125
data: {},
@@ -44,6 +48,14 @@ export class GlobalMetadataSource implements IMetadataSource<GlobalMetadataCache
4448
};
4549
}
4650

51+
public createCacheItem(_storagePath: string): GlobalMetadataCacheItem {
52+
return this.cache;
53+
}
54+
55+
public getOrCreateCacheItem(_storagePath: string): GlobalMetadataCacheItem {
56+
return this.cache;
57+
}
58+
4759
public validateStoragePath(
4860
storagePath: ParsingResultNode,
4961
hadStoragePath: boolean,
@@ -70,7 +82,7 @@ export class GlobalMetadataSource implements IMetadataSource<GlobalMetadataCache
7082
return bindTargetDeclaration;
7183
}
7284

73-
public delete(_cacheItem: GlobalMetadataCacheItem): void {
85+
public deleteCache(_cacheItem: GlobalMetadataCacheItem): void {
7486
// noop
7587
}
7688

@@ -113,16 +125,8 @@ export class GlobalMetadataSource implements IMetadataSource<GlobalMetadataCache
113125
return this.cache;
114126
}
115127

116-
public update(value: unknown, subscription: IMetadataSubscription): GlobalMetadataCacheItem {
117-
if (subscription.bindTarget === undefined) {
118-
throw new MetaBindInternalError({
119-
errorLevel: ErrorLevel.CRITICAL,
120-
effect: 'can not update metadata',
121-
cause: 'subscription bind target undefined',
122-
});
123-
}
124-
125-
PropUtils.setAndCreate(this.cache.data, subscription.bindTarget.storageProp, value);
128+
public updateCache(value: unknown, bindTarget: BindTargetDeclaration): GlobalMetadataCacheItem {
129+
PropUtils.setAndCreate(this.cache.data, bindTarget.storageProp, value);
126130

127131
return this.cache;
128132
}
@@ -145,6 +149,22 @@ export class ScopeMetadataSource implements IMetadataSource<IMetadataCacheItem>
145149
this.manager = manager;
146150
}
147151

152+
public createCacheItem(_storagePath: string): IMetadataCacheItem {
153+
throw new MetaBindInternalError({
154+
errorLevel: ErrorLevel.CRITICAL,
155+
effect: 'action not permitted',
156+
cause: `source 'scope' should have no cache items or subscriptions`,
157+
});
158+
}
159+
160+
public getOrCreateCacheItem(_storagePath: string): IMetadataCacheItem {
161+
throw new MetaBindInternalError({
162+
errorLevel: ErrorLevel.CRITICAL,
163+
effect: 'action not permitted',
164+
cause: `source 'scope' should have no cache items or subscriptions`,
165+
});
166+
}
167+
148168
public validateStoragePath(
149169
storagePath: ParsingResultNode,
150170
hadStoragePath: boolean,
@@ -171,7 +191,7 @@ export class ScopeMetadataSource implements IMetadataSource<IMetadataCacheItem>
171191
return parser.resolveScope(bindTargetDeclaration, scope);
172192
}
173193

174-
public delete(_cacheItem: IMetadataCacheItem): void {
194+
public deleteCache(_cacheItem: IMetadataCacheItem): void {
175195
// noop
176196
}
177197

@@ -219,7 +239,7 @@ export class ScopeMetadataSource implements IMetadataSource<IMetadataCacheItem>
219239
});
220240
}
221241

222-
public update(_value: unknown, _subscription: IMetadataSubscription): IMetadataCacheItem {
242+
public updateCache(_value: unknown, _bindTarget: BindTargetDeclaration): IMetadataCacheItem {
223243
throw new MetaBindInternalError({
224244
errorLevel: ErrorLevel.CRITICAL,
225245
effect: 'action not permitted',

packages/core/src/metadata/MetadataCacheUpdate.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)