From 95b8c2923a5acbdfb6fba7e6291aa1ace855d376 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sun, 6 Sep 2026 15:24:52 +0200 Subject: [PATCH 1/2] Stop the phone drawing its own links over a document A web view built from the storyboard comes with every kind of link detection on, and it cannot be turned off afterwards - so the view is built in code. The reader lays an invisible copy of a pdf's text over the page for selection and search. iOS found an address in that copy and made a link of it, and the link's colour brought the hidden text into view, on top of the page. Phone numbers and addresses in a document are no longer tappable. Links a pdf carries itself still are. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01C2KRXwg8FNE1vYXstnkh8e --- CHANGELOG.md | 9 +++++++- OpenDocumentReader/DocumentWebView.swift | 29 ++++++++++++++++++++++++ OpenDocumentReader/Main.storyboard | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 OpenDocumentReader/DocumentWebView.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e3311b..2f6a416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,13 @@ open: **a second build under the same version goes under the already cut heading, not back under `Unreleased`.** Date the heading and add its compare link once the version tag exists. +## [Unreleased] + +### Fixed + +- An email address or a date in a PDF no longer has a link drawn over it, + which showed the text twice. + ## [1.44] ### Changed @@ -283,7 +290,7 @@ submitted. - An incorrect password is now reported as such instead of a generic failure. - Page handling and decryption fixes when opening protected documents. -[Unreleased]: https://github.com/opendocument-app/OpenDocument.ios/compare/v1.43...HEAD +[Unreleased]: https://github.com/opendocument-app/OpenDocument.ios/compare/v1.44...HEAD [1.43]: https://github.com/opendocument-app/OpenDocument.ios/compare/v1.42...v1.43 [1.42]: https://github.com/opendocument-app/OpenDocument.ios/compare/v1.41...v1.42 [1.41]: https://github.com/opendocument-app/OpenDocument.ios/compare/v1.40...v1.41 diff --git a/OpenDocumentReader/DocumentWebView.swift b/OpenDocumentReader/DocumentWebView.swift new file mode 100644 index 0000000..b43a87e --- /dev/null +++ b/OpenDocumentReader/DocumentWebView.swift @@ -0,0 +1,29 @@ +import WebKit + +/// The reader's web view, built with a configuration the app states rather than +/// the one a storyboard hands it. +/// +/// A `WKWebViewConfiguration` decoded from a nib arrives with every data +/// detector switched on, and `WKWebView.configuration` returns a copy — so a +/// configuration is only ever settable here, before `super.init`. +/// +/// Detectors have to be off. odrcore lays an invisible text layer over a pdf's +/// glyphs for selection and search; iOS finds an address or a date in it, wraps +/// it in a link, and the link's own colour paints that layer over the page the +/// reader is meant to be looking at. +/// +/// Nothing the storyboard states about this view is lost by not decoding it: +/// `DocumentViewController` sizes and positions it in code. Its +/// `wkWebViewConfiguration` element stays there and inert — Interface Builder +/// fails to compile the storyboard without one. +final class DocumentWebView: WKWebView { + + required init?(coder: NSCoder) { + let configuration = WKWebViewConfiguration() + configuration.dataDetectorTypes = [] + // as the storyboard had it: a document's own media plays without a tap + configuration.mediaTypesRequiringUserActionForPlayback = [] + + super.init(frame: .zero, configuration: configuration) + } +} diff --git a/OpenDocumentReader/Main.storyboard b/OpenDocumentReader/Main.storyboard index a49a518..2205f5a 100644 --- a/OpenDocumentReader/Main.storyboard +++ b/OpenDocumentReader/Main.storyboard @@ -69,7 +69,7 @@ - + From 7f7a040f4c92b0ffb3e866b9d4cba3bb2bc9c1fa Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sun, 6 Sep 2026 15:51:45 +0200 Subject: [PATCH 2/2] Say it in three lines Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01C2KRXwg8FNE1vYXstnkh8e --- OpenDocumentReader/DocumentWebView.swift | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/OpenDocumentReader/DocumentWebView.swift b/OpenDocumentReader/DocumentWebView.swift index b43a87e..36ddf19 100644 --- a/OpenDocumentReader/DocumentWebView.swift +++ b/OpenDocumentReader/DocumentWebView.swift @@ -1,27 +1,13 @@ import WebKit -/// The reader's web view, built with a configuration the app states rather than -/// the one a storyboard hands it. -/// -/// A `WKWebViewConfiguration` decoded from a nib arrives with every data -/// detector switched on, and `WKWebView.configuration` returns a copy — so a -/// configuration is only ever settable here, before `super.init`. -/// -/// Detectors have to be off. odrcore lays an invisible text layer over a pdf's -/// glyphs for selection and search; iOS finds an address or a date in it, wraps -/// it in a link, and the link's own colour paints that layer over the page the -/// reader is meant to be looking at. -/// -/// Nothing the storyboard states about this view is lost by not decoding it: -/// `DocumentViewController` sizes and positions it in code. Its -/// `wkWebViewConfiguration` element stays there and inert — Interface Builder -/// fails to compile the storyboard without one. +/// Built here rather than decoded: a nib turns every data detector on, and a +/// configuration cannot be changed once the view has it. Detectors draw links +/// over the invisible text a pdf carries for selection and search. final class DocumentWebView: WKWebView { required init?(coder: NSCoder) { let configuration = WKWebViewConfiguration() configuration.dataDetectorTypes = [] - // as the storyboard had it: a document's own media plays without a tap configuration.mediaTypesRequiringUserActionForPlayback = [] super.init(frame: .zero, configuration: configuration)