Skip to content

Commit 179fa99

Browse files
authored
Add documentation for custom user interfaces (#235)
1 parent 5270966 commit 179fa99

File tree

5 files changed

+67
-3
lines changed

5 files changed

+67
-3
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
layout: documentation
3+
id: documentation
4+
title: Custom User Interfaces
5+
---
6+
7+
## Custom User Interfaces
8+
9+
Sparkle's standard user interface handles many standard behaviors for you. However, some applications may want their own tailored user interface. Before switching to a custom UI for your updater, you should consider if your application will provide the updating functionality users want. For example, users appreciate viewing release notes when being shown a new update is available. Some users may also prefer to reduce update notifications/badges/alerts/custom UI indicators altogether by automatically downloading and installing updates in the future. You may also want to check [gentle update reminders](/documentation/gentle-reminders) for changing how Sparkle's standard update alert can be presented.
10+
11+
### SPUUserDriver
12+
13+
[SPUUserDriver](/documentation/api-reference/Protocols/SPUUserDriver.html) is a protocol that drives the user interface of [SPUUpdater](/documentation/api-reference/Classes/SPUUpdater.html).
14+
15+
To create your own user interface, you can create your own class which conforms to [SPUUserDriver](/documentation/api-reference/Protocols/SPUUserDriver.html). Please read the API documentation for all the methods you implement. Then you can [instantiate a SPUUpdater](/documentation/api-reference/Classes/SPUUpdater.html#/c:objc(cs)SPUUpdater(im)initWithHostBundle:applicationBundle:userDriver:delegate:) with your user driver instead of creating the typical [SPUStandardUpdaterController](/documentation/api-reference/Classes/SPUStandardUpdaterController.html).
16+
17+
Reference classes in Sparkle's repository that implement `SPUUserDriver` are:
18+
19+
* [SPUStandardUserDriver](https://github.com/sparkle-project/Sparkle/blob/2.x/Sparkle/SPUStandardUserDriver.m): Sparkle's standard user interface
20+
* [SUPopUpTitlebarUserDriver](https://github.com/sparkle-project/Sparkle/blob/2.x/TestApplication/SUPopUpTitlebarUserDriver.m): Alternative user interface to the Sparkle Test App
21+
* [SUCommandLineUserDriver](https://github.com/sparkle-project/Sparkle/blob/2.x/sparkle-cli/SPUCommandLineUserDriver.m): User interface to the [sparkle-cli](/documentation/sparkle-cli) tool
22+
23+
Futher sections below highlight scenarios you will need to consider when implementing a custom UI.
24+
25+
### Update Check Permission
26+
27+
By default, Sparkle asks users for their permission to check for new updates automatically on your application's second launch (along with options like if updates should also be downloaded and installed automatically). To add support for this permission request, a user driver needs to implement [-[SPUUserDriver showUpdatePermissionRequest:reply:]](/documentation/api-reference/Protocols/SPUUserDriver.html#/c:objc(pl)SPUUserDriver(im)showUpdatePermissionRequest:reply:).
28+
29+
To test this permision request, you can reset the response by running:
30+
31+
```sh
32+
# Automatic checks for updates
33+
defaults delete my-app-bundle-id SUEnableAutomaticChecks
34+
# Automatic downloading/installing of updates
35+
defaults delete my-app-bundle-id SUAutomaticallyUpdate
36+
# Sending anonymous system profile information
37+
defaults delete my-app-bundle-id SUSendProfileInfo
38+
```
39+
40+
Applications that don't want to ask the user permission for update checking may opt-out by specifying [SUEnableAutomaticChecks in Info.plist](/documentation/customization/). In this case, this user driver method will not be called.
41+
42+
### Authorization
43+
44+
Custom user interfaces need to handle updates that require user authorization to install them. Before installing an update, users on some systems may be requested for an administrator username/password to authorize the installation. While user authorization is always required for [package updates](/documentation/package-updates), authorization can also be required for regular updates on certain systems (e.g. updating a bundle in `/Applications` on standard user accounts or managed systems). To test authorized installs, you can change the ownership of a bundle to `root` before checking for updates:
45+
46+
```sh
47+
sudo chown root path-to-app-bundle
48+
```
49+
50+
This implies your user interface needs to let the user be in control of installing an update once [an update is found](/documentation/api-reference/Protocols/SPUUserDriver.html#/c:objc(pl)SPUUserDriver(im)showUpdateFoundWithAppcastItem:state:reply:) so they do not receive an unexpected authorization prompt. If you want as much as the downloading and installing of an update to be done in the background before a user's input or presenting an update is needed, you can opt into automatic updates via [SUAutomaticallyUpdate](/documentation/customization/).
51+
52+
### Update States
53+
54+
When a new update is found the updater can be in one of several different stages. The most regular stage is when an update has not been downloaded yet. The second most typical stage is when the update has already begun installing in the background (due to automatic updates via [SUAutomaticallyUpdate](/documentation/customization/)); in this case, the application may be immediately relaunched if the user chooses to install the update, or just installed on quit without any additional input. Another stage is when the update has been automatically downloaded but not begun installing yet, which is typically for automatic updates when the updater needs to request for user authorization.
55+
56+
Lastly, custom user interfaces should be able to handle [informational only updates](/documentation/publishing/#downloading-from-a-web-site) as a safety net in case updates cannot be served normally.
57+
58+
Please read the documentation for [-[SPUUserDriver showUpdateFoundWithAppcastItem:state:reply:]](/documentation/api-reference/Protocols/SPUUserDriver.html#/c:objc(pl)SPUUserDriver(im)showUpdateFoundWithAppcastItem:state:reply:) for detailed information on different update states.
59+
60+
### Update Back in Focus
61+
62+
After an update has been shown, a user can check for updates again to bring the update UI back in frontmost focus. To support this you need to implement [-[SPUUserDriver showUpdateInFocus]](/documentation/api-reference/Protocols/SPUUserDriver.html#/c:objc(pl)SPUUserDriver(im)showUpdateInFocus). This method used to be required but is now optional since Sparkle 2.8. Don't implement this method if bringing an update back in focus does not make sense for your user interface (e.g. update UI is always in frontmost focus).
63+

documentation/gentle-reminders/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,4 @@ let UPDATE_NOTIFICATION_IDENTIFIER = "UpdateCheck"
242242

243243
## Custom User Interfaces
244244

245-
The APIs for gentle reminders discussed here are a part of Sparkle's standard user interface and are great if you want to leverage Sparkle's standard UI. If you need even greater customization, you can implement your own custom user interface by writing your your own [SPUUserDriver](/documentation/api-reference/Protocols/SPUUserDriver.html) and passing it when you instantiate a [`SPUUpdater`](/documentation/api-reference/Classes/SPUUpdater.html).
245+
The APIs for gentle reminders discussed here are a part of Sparkle's standard user interface and are great if you want to leverage Sparkle's standard UI. If you need even greater customization, you can implement your own [custom user interface](/documentation/custom-user-interfaces).

documentation/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,5 +201,6 @@ That's it! You're done! You don't have to do any more. But you might want to:
201201
* [Add update settings](/documentation/preferences-ui/) to your settings panel.
202202
* [Add binary delta updates](/documentation/delta-updates/) to your application.
203203
* [Add gentle update reminders](/documentation/gentle-reminders) for your application.
204+
* [Add a custom user interface](/documentation/custom-user-interfaces) for your application's updater.
204205
* [Learn about gathering anonymous statistics about your users' systems](/documentation/system-profiling/).
205206
* [Review Sparkle 2's API Reference](/documentation/api-reference)

documentation/programmatic-setup/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ import Sparkle
125125

126126
```
127127

128-
Note Sparkle's standard user interface cannot display HTML release notes because macOS WebKit views cannot be used inside a Catalyst application. As of Sparkle 2.4 or later, you can use plain text release notes instead. For older versions of Sparkle, you can disable showing release notes by setting [SUShowReleaseNotes](/documentation/customization) to `NO`. A more advanced approach for using HTML release notes using Sparkle 2 is instantiating [SPUUpdater](/documentation/api-reference/Classes/SPUUpdater.html) with your own [SPUUserDriver](/documentation/api-reference/Protocols/SPUUserDriver.html) and custom user interface, which may use an iOS WebKit view from the Catalyst side.
128+
Note Sparkle's standard user interface cannot display HTML release notes because macOS WebKit views cannot be used inside a Catalyst application. As of Sparkle 2.4 or later, you can use plain text release notes instead. For older versions of Sparkle, you can disable showing release notes by setting [SUShowReleaseNotes](/documentation/customization) to `NO`. A more advanced approach for using HTML release notes using Sparkle 2 is creating your own [custom user interface](/documentation/custom-user-interfaces), which may use an iOS WebKit view from the Catalyst side.
129129

130130
If you run into issues with loading the Sparkle framework from your plug-in at runtime, please refer to [Add the Sparkle framework to your project](/documentation/#1-add-the-sparkle-framework-to-your-project) where the setup guide talks about having the <samp>Runpath Search Paths</samp> set to `@loader_path/../Frameworks` and using an `Apple Development` certificate for development to satisfy Library Validation. This applies to the setup for the plug-in target as well.
131131

documentation/upgrading/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ Plug-ins that share the same process as their host should prefer to use an out-o
7575

7676
`SPUUpdater` when used directly can:
7777
* Update other Sparkle-based bundles
78-
* Use a custom user interface (`SPUUserDriver`)
78+
* Use a [custom user interface](/documentation/custom-user-interfaces) (`SPUUserDriver`)
7979

8080
[sparkle-cli](/documentation/sparkle-cli) makes use of both these features as an example.
8181

0 commit comments

Comments
 (0)