-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Register a custom view #27
Comments
Thanks for creating the issue! For anyone who's interested, there's some context in #13 as well! I really want this to be as effortless as possible for other plugin developers, rather than have to maintain a separate "plugin". Ideally, it should just have to be a translation layer from one data structure to another. I've been passively experimenting with this, but now that the plugin seems to be relatively stable, I'll focus on this more. |
Let me know if I need to share some info or implement internally something inside dbfolder to help you with this =) |
I have a working proof-of-concept right now. The Projects plugin scans all enabled plugins and looks for a import { Plugin } from "obsidian";
export default class MyPlugin extends Plugin {
onRegisterProjectView(data: DataFrame, contentEl: HTMLElement) {
contentEl.createEl("h1", { text: "Debug" });
const ul = contentEl.createEl("ul");
for (let field of data.fields) {
ul.createEl("li", {
text: field.name,
});
}
}
} Most likely we'll need to change the signature to provide a builder-type pattern like for menus so we can extend it with more configuration options in the future. onRegisterProjectView(ctx: ViewContext) {
ctx.setTitle("Sample view").setNoPadding().setOnLoad((data, contentEl) => { ... });
} WDYT? |
I'd love to ship it pretty soon so that you can start testing it out and we can start iterating on the API. |
I will test it as soon as is released for sure |
maybe I have to expose a selector modal with all the current db notes the user have inside that registerproyect |
Ok. I think I finally have something you can start testing. Here's an example of a plugin that does nothing but registers itself as a Projects view. import { Plugin } from "obsidian";
import { ProjectView } from "obsidian-projects-types";
export default class MyPlugin extends Plugin {
onRegisterProjectView(view: ProjectView) {
view.setTitle("Sample view")
.setIcon("apple")
.setOnOpen((data, contentEl) => {
contentEl.createEl("h1", { text: "Debug" });
const ul = contentEl.createEl("ul");
for (let field of data.fields) {
ul.createEl("li", {
text: field.name,
});
}
});
}
} Install the types by running: yarn add --dev obsidian-projects-types@0.2.0 The API is only intended to give you something to experiment for now. Please don't add this to any releases :) I'm super excited to see if anyone actually gets it to work 😅 |
with v0.14.7 I try it with dbfolder plugin and an empty one and I am receiving an undefined on The function its called when I try to create a new view but breaks the modal |
Support was introduced in 0.14.8, so make sure upgrade and try again 🙏 |
Please, update your manifest.json. BRAT (and also official plugins) reads your main branch > manifest.json to download the version https://github.com/marcusolsson/obsidian-projects/blob/main/manifest.json |
What should I update? 0.14.8 is the latest version and that's what's in the manifest? I don't know BRAT that well tbh :) |
now BRAT upload it, thanks! I am afraid I need a lot of work for integrate the table.
I will try to mock it |
The context of the plugin is lost inside the api function. https://stackoverflow.com/questions/4011793/this-is-undefined-in-javascript-class-methods. We need to bind it on call |
Good find! I'll fix it with the next release! |
@RafaelGB Should hopefully be fixed in 0.14.10. Let me know if not. |
Looks like now the context is available, thanks! I will let you know if I found another issue |
I could mock the table inside! but there is a little problem... Your API is rendering on loop the view, I don't know if it happens after an exception or that loops provokes de exception Screen.Recording.2022-09-22.at.16.10.08.mov |
Wow!! 🤩 I'm not sure I understand what you mean by "rendering on loop the view"? The onOpen function gets called any time there's new data, for example if you add a file to the workspace. |
In the case of dbfolder, the refresh of the information is managed internally with Zustand and I think that this refresh trigger jumps in cases where it shouldn't. Would there be the possibility of disabling refresh as an API option (just like addIcon but toggleRefresh)? If the plugins already have their own way of managing it, you may incur a conflict. I think that is the case here |
Also, I just need a path to the ddbb file, but with the view the user will need to select it every time, maybe some kind of config map per view inside the API? |
Would you rather have a separate callbacks for receiving new data and when the user opens the view? For example: .setOnData((data: DataFrame) => {
/...
})
.setOnOpen((contentEl: HTMLElement) => {
// ...
}) Each view has a config object stored in the data.json. Haven't figured out a good way to expose it yet, but it's coming. |
Since the plugin rewrite all the config every time it Marshall/unmarshall the yaml info I think it provokes the eternal loop of the callback. I like the idea of separating them 👌 |
I've published 0.14.11 of the Projects plugin, and 0.3.3 of obsidian-projects-types package, which exposes a reworked version of the API. Instead of the builder pattern, in V2, you implement an abstract class: import { Plugin } from "obsidian";
import { DataFrame, ProjectViewV2 } from "obsidian-projects-types";
class MySampleView extends ProjectViewV2 {
dataEl?: HTMLElement;
getViewType(): string {
return "my-sample-view";
}
getDisplayName(): string {
return "Sample view";
}
getIcon(): string {
return "apple";
}
async onData(frame: DataFrame) {
if (this.dataEl) {
this.dataEl.empty();
this.dataEl.createDiv({ text: JSON.stringify(frame.fields) });
this.dataEl.createDiv({ text: JSON.stringify(frame.records) });
}
}
async onOpen() {
console.log("Opening ", this.getDisplayName());
const contentEl = this.containerEl;
contentEl.createEl("h1", { text: "My Sample View" });
this.dataEl = contentEl.createEl("div");
}
async onClose() {
console.log("Closing ", this.getDisplayName());
}
}
export default class MyPlugin extends Plugin {
onRegisterProjectViewV2 = () => new MySampleView();
}
Compared to V1, you can now set up more expensive computations in |
Really nice job. I will test it this weekend to give you feedback :) |
class MySampleView extends ProjectViewV2 {
private plugin: DBFolderPlugin;
constructor(plugin: DBFolderPlugin) {
super();
this.plugin = plugin;
}
dataEl?: HTMLElement;
getViewType(): string {
return "my-sample-view";
}
getDisplayName(): string {
return "Sample view";
}
getIcon(): string {
return DB_ICONS.NAME;
}
async onData(frame: DataFrame) {
// Do nothing here
}
async onOpen() {
const [firstKey] = this.plugin.viewMap.keys();
const db = this.plugin.viewMap.get(firstKey)
db.initDatabase().then(() => {
this.containerEl.createDiv().appendChild(db.containerEl)
})
}
async onClose() {
console.log("Closing ", this.getDisplayName());
}
}
// ***
onRegisterProjectViewV2 = () => new MySampleView(this); Screen.Recording.2022-09-25.at.17.00.15.movWith the correct configuration the mock is working =) |
0.21.0 contains an updated API for custom views. This release has several breaking changes, but updating should be relatively straight-forward. Notably, with this release, all the built-in views are now using the custom view API. Hopefully, that means that I'll be able to catch issues early. Feel free to have a look the table view, for example. For documentation, refer to Custom View API. It's a bit bare, but I'll keep improving it as we go. With this release, I'll consider this issue closed. Feel free to open new issues for any issues you find. I'll label any issues for custom views with Exciting times ahead! |
I can't wait to play with it 😄😄 |
Saw your idea in discord, so I decide to file a issue to record this.
And can't wait to see this happen. I wanted to build a view and use data from projects.
The text was updated successfully, but these errors were encountered: