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.RinglyDFUis 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 fromRinglyKitclasses 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 inReleasebuilds for the App Store.HockeySDK: the HockeyApp SDK. This framework is not included inReleasebuilds for the App Store or inDebugbuilds.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.
masteris protected.experimentalshould never be directly committed to (and the Git hooks installed with./tools/bootstrapwill disallow it). Instead,resetit to a commit that you'd wish to deploy via the experimental HockeyApp build, then force-push it.feature/Xbranches 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 theRLYPeripheralStyleenumeration. - This will cause build errors throughout the app for the missing case in
switchstatements. 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 Imagesfolder ofImages.xcassetsas is appropriate.Photographicimages are edited photorealistic renditions of the peripheral, with a transparent background.Ring Stonesimages are drawn versions of each type of stone on a ring.Shadowsimages are unique to each type of peripheral (i.e. ring, bracelet).Stylizedimages are drawn versions. Currently they are only used for bracelets,OnboardingRingView(which uses theRing Stonesimages) 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.pyon the downloaded file. Multiple applications can be processed at once. For each.ipafile, the filename will be printed first, followed by the bundle identifier, then the URL schemes for the app. - Add an entry to the
Apps.plistfile for the new app.
Schemeis the URL scheme - choose the scheme that makes sense (i.e., not a Facebook callback scheme, if possible).Nameis the display name of the app.Identifiersis 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.Analyticsthe 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@2xand60×60@3xversion. 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 theopencommand. 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. Theexpiresparameter 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.0will attempt to load application version1.5.0on 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.ringlyURLs.
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/enabledeveloper-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.