Revision: 29478
          http://sourceforge.net/p/bibdesk/svn/29478
Author:   hofman
Date:     2025-08-27 09:12:22 +0000 (Wed, 27 Aug 2025)
Log Message:
-----------
Add script and script message handlers in webview subclass init. Let message 
handler call new UIDelegate methods. Avoid message handler to send messages to 
the wrong controller (e.g. after createNeWebView...) and has no retain loop 
problem.

Modified Paths:
--------------
    trunk/bibdesk/BDSKTextImportController.m

Modified: trunk/bibdesk/BDSKTextImportController.m
===================================================================
--- trunk/bibdesk/BDSKTextImportController.m    2025-08-26 15:36:06 UTC (rev 
29477)
+++ trunk/bibdesk/BDSKTextImportController.m    2025-08-27 09:12:22 UTC (rev 
29478)
@@ -103,7 +103,9 @@
 
 @protocol BDSKUIDelegate <WKUIDelegate>
 @optional
-- (void)webView:(WKWebView *)webView willPopUpMenu:(NSMenu *)menu;
+- (void)webView:(WKWebView *)webView willOpenMenu:(NSMenu *)menu;
+- (void)webView:(WKWebView *)webView mouseDidMoveOverLink:(NSString *)link;
+- (void)webView:(WKWebView *)webView didChangeSelection:(NSString 
*)selectedText;
 @end
 
 @interface BDSKWKWebView : WKWebView
@@ -112,15 +114,12 @@
 
 #pragma mark -
 
-@interface BDSKScriptMessageForwarder : NSObject <WKScriptMessageHandler> {
-    __weak id<WKScriptMessageHandler> scriptMessageHandler;
-}
-@property (nonatomic, nullable, weak) id<WKScriptMessageHandler> 
scriptMessageHandler;
+@interface BDSKScriptMessageHandler : NSObject <WKScriptMessageHandler>
 @end
 
 #pragma mark -
 
-@interface BDSKTextImportController () <BDSKCitationFormatterDelegate, 
BDSKDownloadDelegate, WKNavigationDelegate, BDSKUIDelegate, 
WKScriptMessageHandler>
+@interface BDSKTextImportController () <BDSKCitationFormatterDelegate, 
BDSKDownloadDelegate, WKNavigationDelegate, BDSKUIDelegate>
 
 - (void)handleFlagsChangedNotification:(NSNotification *)notification;
 - (void)handleBibItemChangedNotification:(NSNotification *)notification;
@@ -624,28 +623,9 @@
 #pragma mark Setup
 
 - (void)setupWebView {
-    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
-    WKUserContentController *userController = [config userContentController];
-    BDSKScriptMessageForwarder *messageHandler = [[BDSKScriptMessageForwarder 
alloc] init];
-    [messageHandler setScriptMessageHandler:self];
-    [userController addScriptMessageHandler:messageHandler 
name:@"changeSelection"];
-    [userController addScriptMessageHandler:messageHandler name:@"hoverLink"];
-    NSString *jsSource = @""
-        "function changeSelection(){ 
window.webkit.messageHandlers.changeSelection.postMessage(document.getSelection().toString());
 };\n"
-        "document.addEventListener('selectionchange', changeSelection);\n"
-        "function hover(){ 
window.webkit.messageHandlers.hoverLink.postMessage(this.href); }\n"
-        "function unhover(){ 
window.webkit.messageHandlers.hoverLink.postMessage(''); }\n"
-        "var links = document.links;\n"
-        "for(var i=0; i<links.length; i++){\n"
-        "  links[i].addEventListener('mouseover', hover);\n"
-        "  links[i].addEventListener('mouseout', unhover);\n"
-        "}";
-    WKUserScript *script = [[WKUserScript alloc] initWithSource:jsSource 
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
-    [userController addUserScript:script];
-    
     [self willChangeValueForKey:@"webView"];
     
-    webView = [[BDSKWKWebView alloc] initWithFrame:[webViewBox bounds] 
configuration:config];
+    webView = [[BDSKWKWebView alloc] initWithFrame:NSRectToCGRect([webViewBox 
bounds]) configuration:[[WKWebViewConfiguration alloc] init]];
     [webView setNavigationDelegate:self];
     [webView setUIDelegate:self];
     
@@ -1070,7 +1050,7 @@
     return nil;
 }
 
-- (void)webView:(WKWebView *)aWebView willPopUpMenu:(NSMenu *)menu {
+- (void)webView:(WKWebView *)aWebView willOpenMenu:(NSMenu *)menu {
     BOOL useURLFields = [[NSUserDefaults standardUserDefaults] 
boolForKey:BDSKUseLocalUrlAndUrlKey];
     NSString *title;
     NSMenuItem *item;
@@ -1151,21 +1131,15 @@
         [menu insertItem:[NSMenuItem separatorItem] atIndex:j];
 }
 
-#pragma mark WKScriptMessageHandler protocol
+- (void)webView:(WKWebView *)aWebView mouseDidMoveOverLink:(NSString *)link {
+    [statusLine setStringValue:link ?: @""];
+}
 
-- (void)userContentController:(WKUserContentController *)userContentController 
didReceiveScriptMessage:(WKScriptMessage *)message {
-    NSString *name = [message name];
-    NSString *body = [message body];
-    if ([body isKindOfClass:[NSString class]] == NO)
-        body = nil;
-    if ([name isEqualToString:@"hoverLink"]) {
-        [statusLine setStringValue:body ?: @""];
-    } else if ([name isEqualToString:@"changeSelection"]) {
-        if ([NSString isEmptyString:body] == NO)
-            webSelection = [body 
stringByCollapsingAndTrimmingCharactersInSet:[NSCharacterSet 
whitespaceAndNewlineCharacterSet]];
-        if ([webView window])
-            [self setTemporaryTypeSelectStatusMessage:[NSString 
isEmptyString:body] == NO];
-    }
+- (void)webView:(WKWebView *)aWebView didChangeSelection:(NSString 
*)selectedText {
+    if ([NSString isEmptyString:selectedText] == NO)
+        webSelection = [selectedText 
stringByCollapsingAndTrimmingCharactersInSet:[NSCharacterSet 
whitespaceAndNewlineCharacterSet]];
+    if ([webView window])
+        [self setTemporaryTypeSelectStatusMessage:[NSString 
isEmptyString:selectedText] == NO];
 }
 
 #pragma mark  BDSKDownloadDelegate methods
@@ -1679,11 +1653,48 @@
 
 @dynamic UIDelegate;
 
+- (void)addScriptObserversIfNeeded {
+    NSString *jsSource = @""
+        "function changeSelection(){ 
window.webkit.messageHandlers.changeSelection.postMessage(document.getSelection().toString());
 };\n"
+        "document.addEventListener('selectionchange', changeSelection);\n"
+        "function hover(){ 
window.webkit.messageHandlers.hoverLink.postMessage(this.href); }\n"
+        "function unhover(){ 
window.webkit.messageHandlers.hoverLink.postMessage(null); }\n"
+        "var links = document.links;\n"
+        "for(var i=0; i<links.length; i++){\n"
+        "  links[i].addEventListener('mouseover', hover);\n"
+        "  links[i].addEventListener('mouseout', unhover);\n"
+        "}";
+    WKUserContentController *userController = [[self configuration] 
userContentController];
+    if ([[userController userScripts] count] == 0 || [[[userController 
userScripts] valueForKey:@"source"] containsObject:jsSource] == NO) {
+        BDSKScriptMessageHandler *messageHandler = [[BDSKScriptMessageHandler 
alloc] init];
+        [userController addScriptMessageHandler:messageHandler 
name:@"changeSelection"];
+        [userController addScriptMessageHandler:messageHandler 
name:@"hoverLink"];
+        WKUserScript *script = [[WKUserScript alloc] initWithSource:jsSource 
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
+        [userController addUserScript:script];
+    }
+}
+
+- (id)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration 
*)configuration {
+    self = [super initWithFrame:frame configuration:configuration];
+    if (self) {
+        [self addScriptObserversIfNeeded];
+    }
+    return self;
+}
+
+- (id)initWithCoder:(NSCoder *)coder {
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self addScriptObserversIfNeeded];
+    }
+    return self;
+}
+
 - (void)willOpenMenu:(NSMenu *)menu withEvent:(NSEvent *)event {
     [super willOpenMenu:menu withEvent:event];
     
-    if ([[self UIDelegate] 
respondsToSelector:@selector(webView:willPopUpMenu:)])
-        [[self UIDelegate] webView:self willPopUpMenu:menu];
+    if ([[self UIDelegate] 
respondsToSelector:@selector(webView:willOpenMenu:)])
+        [[self UIDelegate] webView:self willOpenMenu:menu];
 }
 
 @end
@@ -1690,12 +1701,26 @@
 
 #pragma mark -
 
-@implementation BDSKScriptMessageForwarder
+@implementation BDSKScriptMessageHandler
 
-@synthesize scriptMessageHandler;
-
 - (void)userContentController:(WKUserContentController *)userContentController 
didReceiveScriptMessage:(WKScriptMessage *)message {
-    [scriptMessageHandler userContentController:userContentController 
didReceiveScriptMessage:message];
+    WKWebView *webView = [message webView];
+    if ([webView isKindOfClass:[BDSKWKWebView class]] == NO)
+        return;
+    id<BDSKUIDelegate> delegate = [(BDSKWKWebView *)webView UIDelegate];
+    if (delegate == nil)
+        return;
+    NSString *name = [message name];
+    NSString *body = [message body];
+    if ([body isKindOfClass:[NSString class]] == NO)
+        body = nil;
+    if ([name isEqualToString:@"hoverLink"]) {
+        if ([delegate 
respondsToSelector:@selector(webView:mouseDidMoveOverLink:)])
+            [delegate webView:webView mouseDidMoveOverLink:body];
+    } else if ([name isEqualToString:@"changeSelection"]) {
+        if ([delegate 
respondsToSelector:@selector(webView:didChangeSelection:)])
+            [delegate webView:webView didChangeSelection:body];
+    }
 }
 
 @end

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit

Reply via email to