>>> DEMO <<<
A MercuryApi based iOS reader written in Swift.
Most modern webbrowers (mobile or desktop) implement a "reader mode" allowing to sanitise/epurate the design of a webpage and offer a better reading experience. However, WKWebView doesn't. Which means that an iOS app can't, natively, load a webpage and switch to the reader mode without passing it to safari. This project aims to add this functionality to a WKWebView subclass.
You can easily switch between 3 font sizes and change between serif/sans
The project basically contains 3 parts, each one adding something to the previous:
- MercuryApi: a MercuryApi client, composed of two classes:
MercuryApi
andMercurtResponse
. They're used to communicate with the API and handle the data it sends back. - ReaderWebView: a
WKWebView
subclass that loads the data received by the API in an HTML template. It supports Dark/Light themes and different font sizes. - ArticleReaderController: It's a
UIViewConroller
subclass that implements the basic functionalities of a web browser with the ability to switch to "reader mode" on any page that is supported by MercuryApi.
First of all, you have to set you set your Mercury Api key. If you don't have one, you can get it for free here.
- create a
keys.plist
file at the root of the project (along with theinfo.plist
file) - add a property called
mercuryApiKey
- put your api key as value to this property
Then, you just use parseUrl
with the url of the webpage you want to make more readable as parameter. You will get a MercuryResponse that encapsulate all the attributes generated by the API.
MercuryApi.shared.parseUrl(url: url.absoluteString, completion: {(resp) -> Void in
if resp != nil {
print(resp!.title)
}
})
See the documentation of the api for more info about them.
You have to add the ReaderWebView
instance in a view (as you would with a WKWebView). Then , you load a webpage with
load(url: URL)
If the webpage is supported by the API (meaning it's able to parse it and extract the content out of it), the ReaderWebView will load the content in the html template and render the whole thing.
It's also possible to directly load a MercuryResponse
:
load(MercuryResponse resp: MercuryResponse)
Use the delegate's methods contentDidLoad
and contentFailedToLoad
to determine whether the content successfully loaded or not (see the following section about the delegate).
You can play with the apparence of the reader with:
/// Available content sizes
enum ReaderContentSize {
case small
case medium
case large
}
/// Available themes
enum ReaderContentTheme {
case light
case dark
}
/// Currently displayed theme
var readerTheme: ReaderContentTheme
/// Current size of the content
var readerContentSize: ReaderContentSize
/// Indicates whether to use a serif font or not
var fontSerif: Bool
You can implement the following methods to keep track of what's happening inside the reader:
/// Called when the user taps on a link inside the reader.
func navigationRequested(request: URLRequest, navigationType: WKNavigationType)
/// Called when a MercuryResponse was successfully loaded in the reader
func contentDidLoad(reader: ReaderWebView, content: MercuryResponse)
/// Called when the reader failed to load a URL
func contentFailedToLoad(reader: ReaderWebView, url: URL?, content: MercuryResponse?)
/// Called when the template has been loaded in the reader webview
func readerInitialized(reader: ReaderWebView)
Note: Since the ReaderWebView inherits from WKWebView, you can, in theory, assign a WKNavigationDelegate to it. In practice though, since the webview is only used to load the reader's template, the methods of the delegate aren't really useful.
Check the ReaderWebViewDemo.swift
file for a quick example.
This part of the project is an example of implementation of the previous part. You can use it as is if it fits your needs or modify it as you want.
In short, it's a controller handling a WKWebView
that has a ReaderWebView
associated (meaning they will always show the same content). It implements a navigation bar and a toolbar presenting the basic webview controls (back, forward and refresh).
For a basic usage, all you have to do is instantiate the ArticleReaderController
and give it a URL. Al the rest is controlled by the user.
You may find usefull to manually show/hide the reader, you can do that using the isReaderEnabled
property.
Check the ArticlesReaderDemo.swift
file for an example.
- customisable background color for the reader (add swift properties for the color of the dark & light themes instead of hardcoding them in the html template)
- better error handling in MercuryApi