Ringly uses Carthage for dependency management. To work on the Ringly app after it has been cloned, the Carthage frameworks must first be built. Generally, this will only need to be done once - it will only need to be repeated if a framework version is updated.
First, if necessary, install Carthage:
brew install carthage
Then, in the root directory for your clone of this repository, run the bootstrapping script:
./Tools/bootstrap
The app should then be ready to build in Xcode (make sure that the right scheme is selected in the top left of the your Xcode window - it should be "Ringly" with a pink icon).
The Ringly workspace (Ringly.xcworkspace
) contains several separate projects:
Ringly
: the Ringly app itself.RinglyAPI
: a client for the Ringly API.RinglyActivityTracking
: manages the database of activity tracking data, and integrates with the Apple Health app.RinglyDFU
: implements firmware updates for Ringly peripherals.DFULibrary
: a fork of the Nordic DFU library.RinglyDFU
is implemented on top of this library.
RinglyExtensions
: extensions and utilities for use in other projects.RinglyKit
: implements the Bluetooth layer, connecting and managing Ringly peripherals. This framework is written in Objective-C.ReactiveRinglyKit
: A bridge fromRinglyKit
classes toReactiveSwift
.
Additionally, the Ringly app and frameworks are built atop some dependencies, which are declared in Cartfile
:
DOHexKeyboard
: a keyboard for entering hex strings. This framework is only used inDeveloperWriteViewController
, and is not included inRelease
builds for the App Store.HockeySDK
: the HockeyApp SDK. This framework is not included inRelease
builds for the App Store or inDebug
builds.Mixpanel
: analytics.Nimble
: a betterXCAssert...
. This framework is only used in tests, and is not included in any app builds.PureLayout
: a better API for Auto Layout. We maintained a fork for better Swift function names in Swift 2, but this might be worth revisiting to see if Swift 3's new Objective-C import rules have improved the naming. There are additionally somePureLayout
-inspired extensions inRinglyExtensions
.ReactiveSwift
: functional-reactive programming. Used extensively for reacting to peripheral events.Realm
: a database used for activity tracking data.Result
: a dependency ofReactiveSwift
.
master
is protected.experimental
should never be directly committed to (and the Git hooks installed with./tools/bootstrap
will disallow it). Instead,reset
it to a commit that you'd wish to deploy via the experimental HockeyApp build, then force-push it.feature/X
branches can be rebased and force pushed.
The app uses the RLog
functions (SLog
in Swift code) to log data to the console. To make the logs more usable for development, the logs are filtered based on categories. While ad-hoc (HockeyApp) builds will have all categories enabled, builds made in Xcode will not. The enabled categories are set at the top of AppDelegate
's application:didFinishLaunchingWithOptions:
callback.
If you are not running the app in Xcode, you can still view log information with idevicesyslog
. This program is part of libimobiledevice
:
brew install libimobiledevice
Then, with your iOS device connected, run idevicesyslog
. It may be necessary to pipe the output to grep "Ringly"
to cut down on unrelated output. However, if the logs are unfiltered, additional ANCS logging from iOS itself can also be viewed.
We use swiftgen
to create type-safe enumerations for resources (currently, images and localizable strings). It's available from Homebrew:
brew install swiftgen
Whenever an image is added to Images.xcassets
or a string is added to Localizable.strings
, run the script ./Tools/generate-resources
to update Resources.swift
with new case
values. The generated code in that file can be used as follows:
- For images, use the
UIImage(asset: ...)
initializer. - For localizable strings, use the
tr(...)
function. ThetrUpper(...)
function is also provided forSCREAMING CAPS
(if these aren't set directly inLocalizable.strings
).
- In
RLYPeripheralEnumerations.h
, add a new case to theRLYPeripheralStyle
enumeration. - This will cause build errors throughout the app for the missing case in
switch
statements. Fix those. - Be sure to update
RLYPeripheralStyleFromShortName
- this is not a switch statement and will not raise an error. - Add new images to the
Peripheral Images
folder ofImages.xcassets
as is appropriate.Photographic
images are edited photorealistic renditions of the peripheral, with a transparent background.Ring Stones
images are drawn versions of each type of stone on a ring.Shadows
images are unique to each type of peripheral (i.e. ring, bracelet).Stylized
images are drawn versions. Currently they are only used for bracelets,OnboardingRingView
(which uses theRing Stones
images) is used for rings.
- Test the app with the new peripheral!
The applications that Ringly supports are listed in the file Ringly/Ringly/Apps.plist
. To add a new app, follow these steps:
- Download the app from the iTunes, then reveal it in Finder by right-clicking on it in the "My iPhone Apps" screen.
- Run the script
./Tools/ringly-ipa.py
on the downloaded file. Multiple applications can be processed at once. For each.ipa
file, the filename will be printed first, followed by the bundle identifier, then the URL schemes for the app. - Add an entry to the
Apps.plist
file for the new app.
Scheme
is the URL scheme - choose the scheme that makes sense (i.e., not a Facebook callback scheme, if possible).Name
is the display name of the app.Identifiers
is a comma-separated list of bundle identifiers - for most apps, there should only be one identifier. Multiple identifiers are only used to combine two apps into one, i.e.com.apple.mobilephone,com.apple.facetime
.Analytics
the the identifier that will be sent to the Ringly analytics endpoints for this app.
- Run
./Tools/LSApplicationQueriesSchemes.py
. This will updateRingly/Ringly/Ringly-Info.plist
, so that the app has permission to read the URL scheme for the new app. - Add an icon set for the app to
Apps.xcassets
. The name of the image should be the app's URL scheme. Include a40×40
@2x
and60×60
@3x
version. To help with this, there is a Photoshop script,./Tools/Save Ringly app images.jsx
. This can either be installed into Photoshop, or can be run from a shell with theopen
command. The script will make the image square, then resize and save all required scales - the image should already have been converted to a white/transparent icon before running the script, we can't automate that.
The com.ringly.ringly://
URL scheme can be used to control app features via URLs. Note that in non-release builds, the bundle identifier suffix is also applied to this URL scheme, i.e. com.ringly.ringly.future://
ab/enable/[test]?expires=[timestamp]
- Enables the A/B test[test]
, which will expire at the Unix timestamp specified. Theexpires
parameter may be omitted, for a test that will never expire.ab/disable/[test]
- Disables the A/B test[test]
.
dfu?hardware=[version]&application=[version]
For example,com.ringly.ringly://dfu?hardware=V00&application=1.5.0
will attempt to load application version1.5.0
on hardware versionV00
.
multi?[anything]=[url]
- evaluates an arbitrary number of URLs, in the order in which they are included in the query string. The names of the query parameters are ignored, as are URLs that are not validcom.ringly.ringly
URLs.
reset-password/[token]
- presents the user with the password reset interface, using the reset token provided in the URL. If the user is already authenticated, this URL will have no effect.
collect-diagnostic-data[?reference=]
- builds a CSV representation of the logs, and uploads it to the Ringly API.
developer-mode/enable
developer-mode/disable
Note that developer mode is automatically enabled when the app starts in a Debug
build.
review
- immediately enables the review prompt in the peripherals view.
These endpoints enable and disable developer mode, which allows access to diagnostic information. Developer mode is not included in apps submitted to the App Store.