shinyMobile Tools

Mobile preview

Since V0.2.0, {shinyMobile} has a function to preview your app in a large range of mobile devices: iphone X, iphone 8+, iphone8, iphone 5s, iphone 4s, ipad, Samsung galaxy S5, Samsung galaxy Note 8, … either locally on online:

library(shiny)
library(shinyMobile)
preview_mobile(appPath = system.file("examples/gallery/app.R", package = "shinyMobile"), device = "iphoneX")
preview_mobile(url = "https://dgranjon.shinyapps.io/miniUI2DemoMd", device = "ipadMini")

The local preview is a 4 steps process:

  • run preview_mobile with appPath
  • Copy the returned code R -e "shiny::runApp('appPath', port = 3838)" in a terminal to launch the app
  • Press enter to run the wrapper app
  • Have fun!

preview_mobile has other options such as color and landscape (to preview in landscape mode).

Pull to Refresh

{shinyMobile} introduces the pull to refresh feature. It may be used to refresh the page content by pulling from top to bottom. This feature is disabled by default but passing pullToRefresh = TRUE in f7Page options will activate it. On the server side, an input, namely input$ptr is TRUE when ptr is refreshed and becomes NULL at the end of the animation. This allows to trigger updates/computations on the server side, for instance:

shinyApp(
  ui = f7Page(
    title = "My app",
    options = list(pullToRefresh = TRUE),
    f7SingleLayout(
      navbar = f7Navbar(
        title = "Single Layout",
        hairline = FALSE,
        shadow = TRUE
      ),
      toolbar = f7Toolbar(
        position = "bottom",
        f7Link(label = "Link 1", href = "https://www.google.com"),
        f7Link(label = "Link 2", href = "https://www.google.com")
      ),
      # main content
      f7List(
        lapply(1:3, function(j) {
          f7ListItem(
            letters[j],
            media = f7Icon("alarm_fill"),
            right = "Right Text",
            header = "Header",
            footer = "Footer"
          )
        })
      )
    )
  ),
  server = function(input, output, session) {
    observe(print(input$ptr))

    observeEvent(input$ptr, {
      ptrStatus <- if (input$ptr) "on"
      f7Dialog(
        text = paste('ptr is', ptrStatus),
        type = "alert"
      )
    })
  }
)

Predefined input values

{shinyMobile} contains a set of useful functions to help you setting the layout as best as possible.

Informations about your current device

Description

{shinyMobile} has a predefined input, namely input$deviceInfo:

shiny::shinyApp(
  ui = f7Page(
    title = "My app",
    f7SingleLayout(
      navbar = f7Navbar(
        title = "Access device info",
        hairline = FALSE,
        shadow = TRUE
      ),
      # main content
      verbatimTextOutput("info")
    )
  ),
  server = function(input, output) {
    output$info <- renderPrint({
      input$deviceInfo
    })
  }
)

The following fields are returned:

  • input$deviceInfo$os, returns a string containing your OS
  • input$deviceInfo$desktop, TRUE or FALSE (if you are running the app on your laptop or desktop)
  • input$deviceInfo$standalone, TRUE or FALSE (standalone, namely whether you access the app like a native app)
  • input$deviceInfo$webview, TRUE or FALSE (webview)
  • input$deviceInfo$electron, TRUE or FALSE (electron)

There are other fields, with less inportance:

  • input$deviceInfo$ios, TRUE or FALSE (if you are running under iOS)
  • input$deviceInfo$android, TRUE or FALSE (if you are running under android)
  • input$deviceInfo$androidChrome, TRUE or FALSE (if you are running under android with Chrome)
  • input$deviceInfo$iphone, TRUE or FALSE (if you have an iphone)
  • input$deviceInfo$ipod, TRUE or FALSE (if you have an ipod)
  • input$deviceInfo$ipad, TRUE or FALSE (if you have an ipad)
  • input$deviceInfo$edge, TRUE or FALSE (if you are using edge)
  • input$deviceInfo$ie, TRUE or FALSE (if you are using Internet Explorer)
  • input$deviceInfo$firefox, TRUE or FALSE (if you are using Firefox)
  • input$deviceInfo$macos, TRUE or FALSE (if you have macOS)
  • input$deviceInfo$windows, TRUE or FALSE (if you have Windows)
  • input$deviceInfo$cordova, TRUE or FALSE (cordova)
  • input$deviceInfo$phonegap, TRUE or FALSE (phonegap)

Usecase

Below the example displays a card only when the app is on desktop.

shinyApp(
  ui = f7Page(
    title = "My app",
    f7SingleLayout(
      navbar = f7Navbar(
        title = "Access device info",
        hairline = FALSE,
        shadow = TRUE
      ),
      # main content
      uiOutput("card"),
      textOutput("userAgent"),
    )
  ),
  server = function(input, output) {
    
    output$userAgent <- renderText(input$deviceInfo$desktop)
    
    # generate a card only for desktop
    output$card <- renderUI({
      if (input$deviceInfo$desktop) {
        f7Card(
          "This is a simple card with plain text,
          but cards can also contain their own header,
          footer, list view, image, or any other element."
        )
      }
    })
  }
)

Informations about Shiny inputs

{shinyMobile} has input$lastInputChanged which returns the name, value and type of the last changed input, see below:

shinyApp(
  ui = f7Page(
    title = "My app",
    f7SingleLayout(
      navbar = f7Navbar(
        title = "Single Layout",
        hairline = FALSE,
        shadow = TRUE
      ),
      toolbar = f7Toolbar(
        position = "bottom",
        f7Link(label = "Link 1", href = "https://www.google.com"),
        f7Link(label = "Link 2", href = "https://www.google.com")
      ),
      # main content
      f7Card(verbatimTextOutput("infos")),
      f7Card(
        f7Text(inputId = "text", label = "Text"),
        f7Slider(inputId = "range1", label = "Range", min = 0, max = 2, value = 1, step = 0.1),
        f7Stepper(inputId = "stepper1", label = "Stepper", min = 0, max = 10, value = 5),
        verbatimTextOutput("lastChanged")
      )
    )
  ),
  server = function(input, output) {
    output$infos <- renderPrint(input$shinyInfo)
    output$lastChanged <- renderPrint(input$lastInputChanged)
  }
)

This is convenient since usually, there is no shortcut to get the last changed value and this needs to be done server side in shiny.

Soon there will be a way to compare initial input values (frozen) to current input values and get a diff.

Other information

input$shinyInfo gives the current workerId (for shinyapps.io, shiny server pro, rstudio connect), the unique sessionId (equal to session$token on the server side).