Suas

Suas iOS & Android Unidirectional Flow Architecture

Welcome to the Suas documentation. You'll find comprehensive guides and documentation to help you start working with Suas as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    Guides

Using Suas Monitor

Suas Monitor is a cross-platform (macOS/Windows/Linux) desktop application that helps to visualize the Suas application state and logs the actions received. It connects to the iOS/Android/macOS applications and receives state/action updates from it.

Suas Monitor uses bonjour to provide easy discoverability. Under the hood, it uses Redux DevTools to parse and visualize state and action information.

There are three simple steps to start using Suas Monitor:

Installing the Suas Monitor Desktop app

Using the prebuilt binaries

To install your application head to Suas Monitor GitHub Releases to download the prebuilt binaries.

Using homebrew

If you are on macOS, the preferred way is to install Suas Monitor using Homebrew

brew tap zendesk/suas
brew cask install suas-monitor
`

Building from source

Finally, you can build Suas Monitor from source, head to Suas Monitor GitHub Releases to read about it.

Add Suas Monitor Middleware to your dependencies

Suas iOS

Suas iOS Monitor Middleware can be installed with Carthage or CocoaPods

Installing with Carthage

Open your Cartfile and append the following:

github "zendesk/suas-ios-monitor-middleware" "master"

Then build it with carthage update

Installing with CocoaPods

Add pod 'Suas' to your Podfile.

use_frameworks!

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

pod 'SuasMonitorMiddleware'

Then run pod install

Suas Android

Add Monitor Middleware as a dependency to your build file:

# For Android Plugin 3.x and up
implementation 'com.zendesk.suas:suas-monitor:1.0.0'

# For Android Plugin 2.x and below
compile 'com.zendesk.suas:suas-monitor:1.0.0'

Using the Suas Monitor and the Monitor Middleware

It is very easy to start using Suas Monitor app to visualize your states and actions. All you need to do is pass MonitorMiddleware when creating the store.

// Create a store with a combined reducer and list of middleware
let store = Suas.createStore(
  // Pass two reducers
  reducer: ....,
  // Pass the MonitorMiddleware
  middleware: MonitorMiddleware()
)
val store = Suas.createStore(reducers)
    .withMiddleware(MonitorMiddleware())
    .build()
Store store = Suas.createStore(reducers)
    .withMiddleware(MonitorMiddleware())
    .build();

Next, you need to make sure that your types can be converted to JSON. In Android you don't have to do anything extra here, but in iOS your state and actions have to implement the SuasEncodable protocol.

Encoding State and Actions in Suas iOS

In order for the MonitorMiddleware to send the Actions and State from the app to the Suas Monitor, it needs to convert them to dictionaries. That can be done in two ways; by having your types implement SuasEncodable or by specifying a stateEncoder and actionEncoder when initializing the MonitorMiddleware. Below, we will go through both these approaches.

Implementing SuasEncodable in your types

SuasEncodable is a protocol that contains a single function, toDictionary, which gets called from MonitorMiddleware when it is about to send the data to the Suas Monitor app over the network. Let's see how we can extend one of our states from the weather app Suas example.

struct FoundLocations: SuasEncodable {
  var query: String
  var foundLocation: [Location]
  
  public func toDictionary() -> [String : Any] {
    return [
     "query": query,
     "foundLocation": foundLocation.map({ $0.toDictionary() })
    ]
  }
  
}

If we are using Swift 4 or newer, we don't need to implement toDictionary. The Swift 4 version of the above looks like the following:

struct FoundLocations: SuasEncodable {
  var query: String
  var foundLocation: [Location]
}

Notice that in the Swift 4 version of FoundLocations we don't have to implement the toDictionary. That works since SuasEncodable in Swift 4 is defined as protocol SuasEncodable: Encodable.

Passing a stateEncoder and actionEncoder

When creating the MonitorMiddleware we can pass two blocks that convert our Actions and States to dictionaries. The MonitorMiddleware will use these blocks when sending data to the Monitor desktop app.

let myMonitorMiddleware = MonitorMiddleware(
  stateEncoder: { state in

    if let state = state as? FoundLocations {
      return [
        "query": state.query,
        "foundLocation": state.foundLocation.....
      ]
    }

    return nil
  },
  actionEncoder: { action in
    if let action = action as? SearchForLocations {
      return [
        "query": action.query
      ]
    }

    return nil
  }
)

let store = Suas.createStore(
  reducer: ....,
  middleware: myMonitorMiddleware
)

The stateEncoder receives any particular state, it casts the state and then returns a dictionary or nil. The dictionary returned will be sent to Suas Monitor app.

Similarly, the actionEncoder receives an action and returns a dictionary or a nil.

By setting the stateEncoder and actionEncoder it becomes your responsibility to encode your states and actions to dictionaries.

That's it, now you are ready to use Suas Monitor.

Using Suas Monitor App

Application State Tree

Application State Tree

When you have Suas Monitor open, and an application with SuasMonitorMiddleware is launched, The application will appear in the Suas monitor application list (The left pane in Suas monitor).

To connect to a client application select it from the Applications list. Once selected, all state changes and actions dispatched in that application are sent to Suas Monitor and visualized inside the desktop app.

Suas Monitor has three screens.

  • Application state screen (shown above)
  • Actions dispatched list with details
  • Action dispatched list with state diff

Suas Monitor provides some easy access to features through simple keyboard shortcuts:

  • h or ?: Display the in app help screen
  • m: Cycle between information screen types
  • ctrl + r: Reload the app screen (Just in case of glitches 😬)
Actions dispatched list

Actions dispatched list

Actions dispatched list with state difference

Actions dispatched list with state difference

What's Next