🧑‍💻 Add onDataChanged method to handle data changes in the plugin (#16244)

This commit is contained in:
Jeffrey Chen 2025-11-25 16:49:22 +08:00 committed by GitHub
parent 319cdbb98a
commit 9bfe00cf10
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 94 additions and 35 deletions

View file

@ -743,7 +743,8 @@ export const bazaar = {
app.plugins.find((item: Plugin) => { app.plugins.find((item: Plugin) => {
if (item.name === dataObj.name) { if (item.name === dataObj.name) {
reloadPlugin(app, { reloadPlugin(app, {
upsertPlugins: [dataObj.name], upsertCodePlugins: [dataObj.name],
upsertDataPlugins: [],
removePlugins: [] removePlugins: []
}); });
return true; return true;

View file

@ -113,6 +113,10 @@ export class Plugin {
// 卸载 // 卸载
} }
public onDataChanged() {
// 存储数据变更
}
public async updateCards(options: ICardData) { public async updateCards(options: ICardData) {
return options; return options;
} }

View file

@ -210,20 +210,48 @@ export const afterLoadPlugin = (plugin: Plugin) => {
/// #endif /// #endif
}; };
export const reloadPlugin = async (app: App, data: { upsertPlugins: string[], removePlugins: string[] }) => { export const reloadPlugin = async (app: App, data: { upsertCodePlugins?: string[], upsertDataPlugins?: string[], removePlugins?: string[] } = {}) => {
data.removePlugins.forEach((item) => { const { upsertCodePlugins = [], upsertDataPlugins = [], removePlugins = [] } = data;
const reloadPlugins: string[] = [];
removePlugins.forEach((item) => {
uninstall(app, item, true); uninstall(app, item, true);
}); });
data.upsertPlugins.forEach((item) => {
upsertCodePlugins.forEach((pluginName) => {
reloadPlugins.push(pluginName);
});
upsertDataPlugins.forEach((pluginName) => {
const plugin = app.plugins.find(p => p.name === pluginName);
// 检查插件是否重写了 onDataChanged 方法(不是基类的默认实现)
const hasOverriddenOnDataChanged = plugin &&
typeof plugin.onDataChanged === "function" &&
plugin.onDataChanged !== Plugin.prototype.onDataChanged;
if (hasOverriddenOnDataChanged) {
try {
plugin.onDataChanged();
return;
} catch (e) {
console.error(`plugin ${pluginName} onDataChanged error:`, e);
}
}
reloadPlugins.push(pluginName);
});
reloadPlugins.forEach((item) => {
uninstall(app, item, false); uninstall(app, item, false);
}); });
loadPlugins(app, data.upsertPlugins).then(() => { if (reloadPlugins.length > 0) {
app.plugins.forEach(item => { loadPlugins(app, reloadPlugins).then(() => {
if (data.upsertPlugins.includes(item.name)) { app.plugins.forEach(item => {
afterLoadPlugin(item); if (reloadPlugins.includes(item.name)) {
} afterLoadPlugin(item);
}
});
}); });
}); }
/// #if !MOBILE /// #if !MOBILE
saveLayout(); saveLayout();
/// #endif /// #endif

View file

@ -67,10 +67,10 @@ func setPetalEnabled(c *gin.Context) {
app = arg["app"].(string) app = arg["app"].(string)
} }
if enabled { if enabled {
upsertPluginSet := hashset.New(packageName) upsertPluginCodeSet := hashset.New(packageName)
model.PushReloadPlugin(upsertPluginSet, nil, app) model.PushReloadPlugin(upsertPluginCodeSet, nil, nil, app)
} else { } else {
removePluginSet := hashset.New(packageName) removePluginSet := hashset.New(packageName)
model.PushReloadPlugin(nil, removePluginSet, app) model.PushReloadPlugin(nil, nil, removePluginSet, app)
} }
} }

View file

@ -257,7 +257,7 @@ func UninstallBazaarPlugin(pluginName, frontend string) error {
savePetals(petals) savePetals(petals)
removePluginSet := hashset.New(pluginName) removePluginSet := hashset.New(pluginName)
pushReloadPlugin(nil, removePluginSet, "") PushReloadPlugin(nil, nil, removePluginSet, "")
return nil return nil
} }

View file

@ -38,15 +38,38 @@ import (
"github.com/siyuan-note/siyuan/kernel/util" "github.com/siyuan-note/siyuan/kernel/util"
) )
func PushReloadPlugin(upsertPluginSet, removePluginNameSet *hashset.Set, excludeApp string) { func PushReloadPlugin(upsertCodePluginSet, upsertDataPluginSet, removePluginNameSet *hashset.Set, excludeApp string) {
pushReloadPlugin(upsertPluginSet, removePluginNameSet, excludeApp) if nil != removePluginNameSet {
} for _, n := range removePluginNameSet.Values() {
pluginName := n.(string)
// 如果插件在 removePluginSet 中,从其他集合中移除
if nil != upsertCodePluginSet {
upsertCodePluginSet.Remove(pluginName)
}
if nil != upsertDataPluginSet {
upsertDataPluginSet.Remove(pluginName)
}
}
}
if nil != upsertCodePluginSet {
for _, n := range upsertCodePluginSet.Values() {
pluginName := n.(string)
// 如果插件在 upsertCodePluginSet 中,从 upsertDataPluginSet 中移除
if nil != upsertDataPluginSet {
upsertDataPluginSet.Remove(pluginName)
}
}
}
func pushReloadPlugin(upsertPluginSet, removePluginNameSet *hashset.Set, excludeApp string) { upsertCodePlugins, upsertDataPlugins, removePlugins := []string{}, []string{}, []string{}
upsertPlugins, removePlugins := []string{}, []string{} if nil != upsertCodePluginSet {
if nil != upsertPluginSet { for _, n := range upsertCodePluginSet.Values() {
for _, n := range upsertPluginSet.Values() { upsertCodePlugins = append(upsertCodePlugins, n.(string))
upsertPlugins = append(upsertPlugins, n.(string)) }
}
if nil != upsertDataPluginSet {
for _, n := range upsertDataPluginSet.Values() {
upsertDataPlugins = append(upsertDataPlugins, n.(string))
} }
} }
if nil != removePluginNameSet { if nil != removePluginNameSet {
@ -55,22 +78,24 @@ func pushReloadPlugin(upsertPluginSet, removePluginNameSet *hashset.Set, exclude
} }
} }
pushReloadPlugin0(upsertPlugins, removePlugins, excludeApp) pushReloadPlugin0(upsertCodePlugins, upsertDataPlugins, removePlugins, excludeApp)
} }
func pushReloadPlugin0(upsertPlugins, removePlugins []string, excludeApp string) { func pushReloadPlugin0(upsertCodePlugins, upsertDataPlugins, removePlugins []string, excludeApp string) {
logging.LogInfof("reload plugins [upserts=%v, removes=%v]", upsertPlugins, removePlugins) logging.LogInfof("reload plugins [codeChanges=%v, dataChanges=%v, removes=%v]", upsertCodePlugins, upsertDataPlugins, removePlugins)
if "" == excludeApp { if "" == excludeApp {
util.BroadcastByType("main", "reloadPlugin", 0, "", map[string]interface{}{ util.BroadcastByType("main", "reloadPlugin", 0, "", map[string]interface{}{
"upsertPlugins": upsertPlugins, "upsertCodePlugins": upsertCodePlugins,
"removePlugins": removePlugins, "upsertDataPlugins": upsertDataPlugins,
"removePlugins": removePlugins,
}) })
return return
} }
util.BroadcastByTypeAndExcludeApp(excludeApp, "main", "reloadPlugin", 0, "", map[string]interface{}{ util.BroadcastByTypeAndExcludeApp(excludeApp, "main", "reloadPlugin", 0, "", map[string]interface{}{
"upsertPlugins": upsertPlugins, "upsertCodePlugins": upsertCodePlugins,
"removePlugins": removePlugins, "upsertDataPlugins": upsertDataPlugins,
"removePlugins": removePlugins,
}) })
} }

View file

@ -1594,7 +1594,8 @@ func processSyncMergeResult(exit, byHand bool, mergeResult *dejavu.MergeResult,
var upsertTrees int var upsertTrees int
// 可能需要重新加载部分功能 // 可能需要重新加载部分功能
var needReloadFlashcard, needReloadOcrTexts, needReloadPlugin bool var needReloadFlashcard, needReloadOcrTexts, needReloadPlugin bool
upsertPluginSet := hashset.New() upsertCodePluginSet := hashset.New() // 插件代码变更 data/plugins/
upsertDataPluginSet := hashset.New() // 插件存储数据变更 data/storage/petal/
needUnindexBoxes, needIndexBoxes := map[string]bool{}, map[string]bool{} needUnindexBoxes, needIndexBoxes := map[string]bool{}, map[string]bool{}
for _, file := range mergeResult.Upserts { for _, file := range mergeResult.Upserts {
upserts = append(upserts, file.Path) upserts = append(upserts, file.Path)
@ -1617,7 +1618,7 @@ func processSyncMergeResult(exit, byHand bool, mergeResult *dejavu.MergeResult,
needReloadPlugin = true needReloadPlugin = true
if parts := strings.Split(file.Path, "/"); 3 < len(parts) { if parts := strings.Split(file.Path, "/"); 3 < len(parts) {
if pluginName := parts[3]; "petals.json" != pluginName { if pluginName := parts[3]; "petals.json" != pluginName {
upsertPluginSet.Add(pluginName) upsertDataPluginSet.Add(pluginName)
} }
} }
} }
@ -1625,7 +1626,7 @@ func processSyncMergeResult(exit, byHand bool, mergeResult *dejavu.MergeResult,
if strings.HasPrefix(file.Path, "/plugins/") { if strings.HasPrefix(file.Path, "/plugins/") {
if parts := strings.Split(file.Path, "/"); 2 < len(parts) { if parts := strings.Split(file.Path, "/"); 2 < len(parts) {
needReloadPlugin = true needReloadPlugin = true
upsertPluginSet.Add(parts[2]) upsertCodePluginSet.Add(parts[2])
} }
} }
@ -1655,7 +1656,7 @@ func processSyncMergeResult(exit, byHand bool, mergeResult *dejavu.MergeResult,
needReloadPlugin = true needReloadPlugin = true
if parts := strings.Split(file.Path, "/"); 3 < len(parts) { if parts := strings.Split(file.Path, "/"); 3 < len(parts) {
if pluginName := parts[3]; "petals.json" != pluginName { if pluginName := parts[3]; "petals.json" != pluginName {
removePluginSet.Add(pluginName) upsertDataPluginSet.Add(pluginName)
} }
} }
} }
@ -1676,7 +1677,7 @@ func processSyncMergeResult(exit, byHand bool, mergeResult *dejavu.MergeResult,
for _, upsertPetal := range mergeResult.UpsertPetals { for _, upsertPetal := range mergeResult.UpsertPetals {
needReloadPlugin = true needReloadPlugin = true
upsertPluginSet.Add(upsertPetal) upsertCodePluginSet.Add(upsertPetal)
} }
for _, removePetal := range mergeResult.RemovePetals { for _, removePetal := range mergeResult.RemovePetals {
needReloadPlugin = true needReloadPlugin = true
@ -1692,7 +1693,7 @@ func processSyncMergeResult(exit, byHand bool, mergeResult *dejavu.MergeResult,
} }
if needReloadPlugin { if needReloadPlugin {
pushReloadPlugin(upsertPluginSet, removePluginSet, "") PushReloadPlugin(upsertCodePluginSet, upsertDataPluginSet, removePluginSet, "")
} }
for _, widgetDir := range removeWidgetDirSet.Values() { for _, widgetDir := range removeWidgetDirSet.Values() {