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:
preview_mobile
with appPathR -e "shiny::runApp('appPath', port = 3838)"
in a terminal to launch the apppreview_mobile
has other options such as color and landscape (to preview in landscape mode).
{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"
)
})
}
)
{shinyMobile}
contains a set of useful functions to help you setting the layout as best as possible.
{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 OSinput$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)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."
)
}
})
}
)
{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.
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).