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{}{