From aa7a745eb22b5d395bc82e8dd64ac8e6dfcfba9a Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 18 Jun 2024 19:25:22 +0800 Subject: [PATCH] :art: Custom Emoji folders no longer require manual refresh when they change https://github.com/siyuan-note/siyuan/issues/11749 --- kernel/main.go | 1 + kernel/model/emojis_watcher.go | 111 ++++++++++++++++++++++++++ kernel/model/emojis_watcher_darwin.go | 91 +++++++++++++++++++++ kernel/model/repository.go | 2 + kernel/util/websocket.go | 4 + 5 files changed, 209 insertions(+) create mode 100644 kernel/model/emojis_watcher.go create mode 100644 kernel/model/emojis_watcher_darwin.go diff --git a/kernel/main.go b/kernel/main.go index b162d8882da..1addbca3f36 100644 --- a/kernel/main.go +++ b/kernel/main.go @@ -53,5 +53,6 @@ func main() { go util.CheckFileSysStatus() model.WatchAssets() + model.WatchEmojis() model.HandleSignal() } diff --git a/kernel/model/emojis_watcher.go b/kernel/model/emojis_watcher.go new file mode 100644 index 00000000000..855d972f4be --- /dev/null +++ b/kernel/model/emojis_watcher.go @@ -0,0 +1,111 @@ +// SiYuan - Refactor your thinking +// Copyright (c) 2020-present, b3log.org +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//go:build !darwin + +package model + +import ( + "os" + "path/filepath" + "time" + + "github.com/88250/gulu" + "github.com/fsnotify/fsnotify" + "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/util" +) + +var emojisWatcher *fsnotify.Watcher + +func WatchEmojis() { + if util.ContainerAndroid == util.Container || util.ContainerIOS == util.Container { + return + } + + go func() { + watchEmojis() + }() +} + +func watchEmojis() { + emojisDir := filepath.Join(util.DataDir, "emojis") + if nil != emojisWatcher { + emojisWatcher.Close() + } + + var err error + if emojisWatcher, err = fsnotify.NewWatcher(); nil != err { + logging.LogErrorf("add emojis watcher for folder [%s] failed: %s", emojisDir, err) + return + } + + go func() { + defer logging.Recover() + + var ( + timer *time.Timer + lastEvent fsnotify.Event + ) + timer = time.NewTimer(100 * time.Millisecond) + <-timer.C // timer should be expired at first + + for { + select { + case event, ok := <-emojisWatcher.Events: + if !ok { + return + } + + lastEvent = event + timer.Reset(time.Millisecond * 100) + + if lastEvent.Op&fsnotify.Rename == fsnotify.Rename || lastEvent.Op&fsnotify.Write == fsnotify.Write { + util.PushReloadEmojiConf() + } else if lastEvent.Op&fsnotify.Remove == fsnotify.Remove { + util.PushReloadEmojiConf() + } + case err, ok := <-emojisWatcher.Errors: + if !ok { + return + } + logging.LogErrorf("watch emojis failed: %s", err) + case <-timer.C: + //logging.LogInfof("emojis changed: %s", lastEvent) + if lastEvent.Op&fsnotify.Remove == fsnotify.Remove { + util.PushReloadEmojiConf() + } else { + util.PushReloadEmojiConf() + } + } + } + }() + + if !gulu.File.IsDir(emojisDir) { + os.MkdirAll(emojisDir, 0755) + } + + if err = emojisWatcher.Add(emojisDir); err != nil { + logging.LogErrorf("add emojis watcher for folder [%s] failed: %s", emojisDir, err) + } + //logging.LogInfof("added file watcher [%s]", emojisDir) +} + +func CloseWatchEmojis() { + if nil != emojisWatcher { + emojisWatcher.Close() + } +} diff --git a/kernel/model/emojis_watcher_darwin.go b/kernel/model/emojis_watcher_darwin.go new file mode 100644 index 00000000000..5c12590bde5 --- /dev/null +++ b/kernel/model/emojis_watcher_darwin.go @@ -0,0 +1,91 @@ +// SiYuan - Refactor your thinking +// Copyright (c) 2020-present, b3log.org +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//go:build darwin + +package model + +import ( + "path/filepath" + "time" + + "github.com/radovskyb/watcher" + "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/util" +) + +var emojisWatcher *watcher.Watcher + +func WatchEmojis() { + go func() { + watchEmojis() + }() +} + +func watchEmojis() { + if nil != emojisWatcher { + emojisWatcher.Close() + } + emojisWatcher = watcher.New() + + emojisDir := filepath.Join(util.DataDir, "emojis") + + go func() { + for { + select { + case event, ok := <-emojisWatcher.Event: + if !ok { + return + } + + //logging.LogInfof("emojis changed: %s", event) + if watcher.Write == event.Op { + IncSync() + } + + if watcher.Remove == event.Op { + util.PushReloadEmojiConf() + } else { + util.PushReloadEmojiConf() + } + case err, ok := <-emojisWatcher.Error: + if !ok { + return + } + logging.LogErrorf("watch emojis failed: %s", err) + case <-emojisWatcher.Closed: + return + } + } + }() + + if err := emojisWatcher.Add(emojisDir); nil != err { + logging.LogErrorf("add emojis watcher for folder [%s] failed: %s", emojisDir, err) + return + } + + //logging.LogInfof("added file watcher [%s]", emojisDir) + if err := emojisWatcher.Start(10 * time.Second); nil != err { + logging.LogErrorf("start emojis watcher for folder [%s] failed: %s", emojisDir, err) + return + } +} + +func CloseWatchEmojis() { + if nil != emojisWatcher { + emojisWatcher.Close() + } +} diff --git a/kernel/model/repository.go b/kernel/model/repository.go index a35a5edddd6..a5afac2ca54 100644 --- a/kernel/model/repository.go +++ b/kernel/model/repository.go @@ -634,6 +634,8 @@ func checkoutRepo(id string) { WaitForWritingFiles() CloseWatchAssets() defer WatchAssets() + CloseWatchEmojis() + defer WatchEmojis() // 恢复快照时自动暂停同步,避免刚刚恢复后的数据又被同步覆盖 syncEnabled := Conf.Sync.Enabled diff --git a/kernel/util/websocket.go b/kernel/util/websocket.go index d4eede994bb..13923902980 100644 --- a/kernel/util/websocket.go +++ b/kernel/util/websocket.go @@ -266,6 +266,10 @@ func PushProtyleLoading(rootID, msg string) { BroadcastByType("protyle", "addLoading", 0, msg, rootID) } +func PushReloadEmojiConf() { + BroadcastByType("main", "reloadEmojiConf", 0, "", nil) +} + func PushDownloadProgress(id string, percent float32) { evt := NewCmdResult("downloadProgress", 0, PushModeBroadcast) evt.Data = map[string]interface{}{