Zonble: Use fsStreamHelper to monitor data changes.
This commit is contained in:
parent
115f197b72
commit
541e96ab70
|
@ -128,13 +128,23 @@ struct VersionUpdateApi {
|
|||
}
|
||||
|
||||
@objc(AppDelegate)
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, NonModalAlertWindowControllerDelegate {
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, NonModalAlertWindowControllerDelegate, FSEventStreamHelperDelegate {
|
||||
func helper(_ helper: FSEventStreamHelper, didReceive events: [FSEventStreamHelper.Event]) {
|
||||
DispatchQueue.main.async {
|
||||
if Preferences.shouldAutoReloadUserDataFiles {
|
||||
LanguageModelManager.loadUserPhrases()
|
||||
LanguageModelManager.loadUserPhraseReplacement()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBOutlet weak var window: NSWindow?
|
||||
private var preferencesWindowController: PreferencesWindowController?
|
||||
private var aboutWindowController: frmAboutWindow? // New About Window
|
||||
private var checkTask: URLSessionTask?
|
||||
private var updateNextStepURL: URL?
|
||||
private var fsStreamHelper = FSEventStreamHelper(path: LanguageModelManager.dataFolderPath, queue: DispatchQueue(label: "User Phrases"))
|
||||
|
||||
// 補上 dealloc
|
||||
deinit {
|
||||
|
@ -149,6 +159,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NonModalAlertWindowControlle
|
|||
LanguageModelManager.loadCNSData()
|
||||
LanguageModelManager.loadUserPhrases()
|
||||
LanguageModelManager.loadUserPhraseReplacement()
|
||||
fsStreamHelper.delegate = self
|
||||
_ = fsStreamHelper.start()
|
||||
|
||||
Preferences.setMissingDefaults()
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* FSEventStreamHelper.swift
|
||||
*
|
||||
* Copyright 2021-2022 vChewing Project (3-Clause BSD License).
|
||||
* Derived from 2011-2022 OpenVanilla Project (MIT License).
|
||||
* Some rights reserved. See "LICENSE.TXT" for details.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
public protocol FSEventStreamHelperDelegate: AnyObject {
|
||||
func helper(_ helper: FSEventStreamHelper, didReceive events: [FSEventStreamHelper.Event])
|
||||
}
|
||||
|
||||
public class FSEventStreamHelper : NSObject {
|
||||
|
||||
public struct Event {
|
||||
var path: String
|
||||
var flags: FSEventStreamEventFlags
|
||||
var id: FSEventStreamEventId
|
||||
}
|
||||
|
||||
public let path: String
|
||||
public let dispatchQueue: DispatchQueue
|
||||
public weak var delegate: FSEventStreamHelperDelegate?
|
||||
|
||||
@objc public init(path: String, queue: DispatchQueue) {
|
||||
self.path = path
|
||||
self.dispatchQueue = queue
|
||||
}
|
||||
|
||||
private var stream: FSEventStreamRef? = nil
|
||||
|
||||
public func start() -> Bool {
|
||||
if stream != nil {
|
||||
return false
|
||||
}
|
||||
var context = FSEventStreamContext()
|
||||
context.info = Unmanaged.passUnretained(self).toOpaque()
|
||||
guard let stream = FSEventStreamCreate(nil, {
|
||||
(stream, clientCallBackInfo, eventCount, eventPaths, eventFlags, eventIds) in
|
||||
let helper = Unmanaged<FSEventStreamHelper>.fromOpaque(clientCallBackInfo!).takeUnretainedValue()
|
||||
let pathsBase = eventPaths.assumingMemoryBound(to: UnsafePointer<CChar>.self)
|
||||
let pathsPtr = UnsafeBufferPointer(start: pathsBase, count: eventCount)
|
||||
let flagsPtr = UnsafeBufferPointer(start: eventFlags, count: eventCount)
|
||||
let eventIDsPtr = UnsafeBufferPointer(start: eventIds, count: eventCount)
|
||||
let events = (0..<eventCount).map {
|
||||
FSEventStreamHelper.Event(path: String(cString: pathsPtr[$0]),
|
||||
flags: flagsPtr[$0],
|
||||
id: eventIDsPtr[$0] )
|
||||
}
|
||||
helper.delegate?.helper(helper, didReceive: events)
|
||||
},
|
||||
&context,
|
||||
[path] as CFArray,
|
||||
UInt64(kFSEventStreamEventIdSinceNow),
|
||||
1.0,
|
||||
FSEventStreamCreateFlags(kFSEventStreamCreateFlagNone)
|
||||
) else {
|
||||
return false
|
||||
}
|
||||
|
||||
FSEventStreamSetDispatchQueue(stream, dispatchQueue)
|
||||
if !FSEventStreamStart(stream) {
|
||||
FSEventStreamInvalidate(stream)
|
||||
return false
|
||||
}
|
||||
self.stream = stream
|
||||
return true
|
||||
}
|
||||
|
||||
func stop() {
|
||||
guard let stream = stream else {
|
||||
return
|
||||
}
|
||||
FSEventStreamStop(stream)
|
||||
FSEventStreamInvalidate(stream)
|
||||
self.stream = nil
|
||||
}
|
||||
}
|
|
@ -192,11 +192,6 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
|||
NSString *basisKeyboardLayoutID = Preferences.basisKeyboardLayout;
|
||||
[client overrideKeyboardWithKeyboardNamed:basisKeyboardLayoutID];
|
||||
|
||||
// Load UserPhrases // 這裡今後需要改造成「驗證檔案指紋、根據驗證結果判定是否需要重新讀入」的形式。
|
||||
if (Preferences.shouldAutoReloadUserDataFiles) {
|
||||
[self reloadUserPhrases:(id)nil];
|
||||
}
|
||||
|
||||
// reset the state
|
||||
_currentDeferredClient = nil;
|
||||
_currentCandidateClient = nil;
|
||||
|
|
|
@ -181,7 +181,7 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
|||
[writeFile writeData:data];
|
||||
[writeFile closeFile];
|
||||
|
||||
[self loadUserPhrases];
|
||||
// [self loadUserPhrases]; // Not Needed since AppDelegate is handling this.
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,4 +17,5 @@
|
|||
+ (void)loadCNSData;
|
||||
+ (void)loadUserPhrases;
|
||||
+ (void)loadUserPhraseReplacement;
|
||||
@property (class, readonly, nonatomic) NSString *dataFolderPath;
|
||||
@end
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
5B5F4F972792A4EA00922DC2 /* UserPhrasesLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B5F4F962792A4EA00922DC2 /* UserPhrasesLM.mm */; };
|
||||
5B6797B52794822C004AC7CE /* PhraseReplacementMap.h in Sources */ = {isa = PBXBuildFile; fileRef = 5B6797B32794822C004AC7CE /* PhraseReplacementMap.h */; };
|
||||
5B810D9F27A3A5E50032C1A9 /* LMConsolidator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B810D9D27A3A5E50032C1A9 /* LMConsolidator.mm */; };
|
||||
5B9DD0A927A7950D00ED335A /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9DD0A827A7950D00ED335A /* FSEventStreamHelper.swift */; };
|
||||
5BC2D2882793B434002C0BEC /* KeyValueBlobReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */; };
|
||||
5BC2D28B2793B8FB002C0BEC /* EmacsKeyHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D28A2793B8FB002C0BEC /* EmacsKeyHelper.swift */; };
|
||||
5BC2D28D2793B98F002C0BEC /* PreferencesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */; };
|
||||
|
@ -124,6 +125,7 @@
|
|||
5B9781D52763850700897999 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
5B9781D72763850700897999 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "Source/zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
5B9781D82763850700897999 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "Source/zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
5B9DD0A827A7950D00ED335A /* FSEventStreamHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FSEventStreamHelper.swift; sourceTree = "<group>"; };
|
||||
5BA923AC2791B7C20001323A /* vChewingInstaller-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "vChewingInstaller-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
5BC2D2842793B434002C0BEC /* KeyValueBlobReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyValueBlobReader.h; sourceTree = "<group>"; };
|
||||
5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyValueBlobReader.cpp; sourceTree = "<group>"; };
|
||||
|
@ -264,6 +266,7 @@
|
|||
5B6797B32794822C004AC7CE /* PhraseReplacementMap.h */,
|
||||
5B810D9D27A3A5E50032C1A9 /* LMConsolidator.mm */,
|
||||
5B810D9E27A3A5E50032C1A9 /* LMConsolidator.h */,
|
||||
5B9DD0A827A7950D00ED335A /* FSEventStreamHelper.swift */,
|
||||
);
|
||||
path = LanguageModel;
|
||||
sourceTree = "<group>";
|
||||
|
@ -714,6 +717,7 @@
|
|||
5BD0D19A27943D390008F48E /* clsSFX.swift in Sources */,
|
||||
5BDD25F9279D6D1200AA18F8 /* ioapi.m in Sources */,
|
||||
5BE798A72793280C00337FF9 /* NotifierController.swift in Sources */,
|
||||
5B9DD0A927A7950D00ED335A /* FSEventStreamHelper.swift in Sources */,
|
||||
5B5F4F93279294A300922DC2 /* LanguageModelManager.mm in Sources */,
|
||||
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,
|
||||
6A0D4ED315FC0D6400ABF4B3 /* main.swift in Sources */,
|
||||
|
|
Loading…
Reference in New Issue