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