Compare commits

...

8 Commits

Author SHA1 Message Date
Winston Chang
914baf594b Merge pull request #2241 from rstudio/joe/bugfix/icon-examples
Remove icon examples
2018-11-01 20:41:58 -05:00
Joe Cheng
02b0802886 Add note about FontAwesome path change 2018-11-01 15:08:59 -07:00
Joe Cheng
0725239397 Remove icon examples
These cause browser windows to pop up during R CMD check, which is
against CRAN policy. @wch will merge a PR that has other examples
once we release v1.2.
2018-11-01 14:56:15 -07:00
Joe Cheng
d72e8a06a7 Fix error in global reactiveTimer
When reactiveTimer is created without a default reactive domain
(i.e. outside of a session, i.e. global) there's no session to
call cycleStartAction on. Instead, invalidation should proceed
right away.

Fixes #2228
2018-10-29 11:43:03 -05:00
Joe Cheng
cf79fec720 Merge pull request #2226 from rstudio/joe/bugfix/cycle-queue-stall-2
Fix input event queue stall
2018-10-25 15:19:23 -07:00
Joe Cheng
31dda45d1c Update NEWS 2018-10-25 12:13:37 -07:00
Joe Cheng
9836b72661 Fix #2225: Input event queue can stall in apps that use async 2018-10-25 12:12:21 -07:00
Winston Chang
5ec38581ca Add support for Font-Awesome 5 brands (#2221)
* Add support for Font-Awesome 5 brands

* Fix glyphicon support
2018-10-24 16:13:36 -05:00
7 changed files with 133 additions and 12 deletions

View File

@@ -106,6 +106,7 @@ Collate:
'cache-utils.R'
'diagnose.R'
'fileupload.R'
'font-awesome.R'
'graph.R'
'reactives.R'
'reactive-domains.R'

View File

@@ -5,6 +5,10 @@ This release features plot caching, an important new tool for improving performa
## Full changelog
### Breaking changes
* The URL paths for FontAwesome CSS/JS/font assets have changed, due to our upgrade from FontAwesome 4 to 5. This shouldn't affect you unless you're using `www/index.html` to provide your UI and have hardcoded the old FontAwesome paths into your HTML. If that's you, consider switching to [HTML templates](https://shiny.rstudio.com/articles/templates.html), which give you the syntax of raw HTML while still taking advantage of Shiny's automatic management of web dependencies.
### New features
* Added `renderCachedPlot()`, which stores plots in a cache so that they can be served up almost instantly. ([#1997](https://github.com/rstudio/shiny/pull/1997))
@@ -49,6 +53,10 @@ This release features plot caching, an important new tool for improving performa
* Fixed [#2204](https://github.com/rstudio/shiny/issues/2204): `updateDateInput` could set the wrong date on days where DST begins. (Thanks @GaGaMan1101!) [#2212](https://github.com/rstudio/shiny/pull/2212)
* Fixed [#2225](https://github.com/rstudio/shiny/issues/2225): Input event queue can stall in apps that use async. [#2226](https://github.com/rstudio/shiny/pull/2226)
* Fixed [#2228](https://github.com/rstudio/shiny/issues/2228): `reactiveTimer` fails when not owned by a session. Thanks, @P-Bettega! [#2229](https://github.com/rstudio/shiny/pull/2229)
### Documentation Updates
* Addressed [#1864](https://github.com/rstudio/shiny/issues/1864) by changing `optgroup` documentation to use `list` instead of `c`. ([#2084](https://github.com/rstudio/shiny/pull/2084))

View File

@@ -1508,10 +1508,6 @@ downloadLink <- function(outputId, label="Download", class=NULL, ...) {
#'
#'
#' @examples
#' icon("calendar") # standard icon
#' icon("calendar", "fa-3x") # 3x normal size
#' icon("cog", lib = "glyphicon") # From glyphicon library
#'
#' # add an icon to a submit button
#' submitButton("Update View", icon = icon("refresh"))
#'
@@ -1537,8 +1533,13 @@ icon <- function(name, class = NULL, lib = "font-awesome") {
# build the icon class (allow name to be null so that other functions
# e.g. buildTabset can pass an explicit class value)
iconClass <- ""
if (!is.null(name))
iconClass <- paste0(prefix, " ", prefix, "-", name)
if (!is.null(name)) {
prefix_class <- prefix
if (prefix_class == "fa" && name %in% font_awesome_brands) {
prefix_class <- "fab"
}
iconClass <- paste0(prefix_class, " ", prefix, "-", name)
}
if (!is.null(class))
iconClass <- paste(iconClass, class)

75
R/font-awesome.R Normal file
View File

@@ -0,0 +1,75 @@
font_awesome_brands <- c(
"500px", "accessible-icon", "accusoft", "adn", "adversal",
"affiliatetheme", "algolia", "alipay", "amazon", "amazon-pay",
"amilia", "android", "angellist", "angrycreative", "angular",
"app-store", "app-store-ios", "apper", "apple", "apple-pay",
"asymmetrik", "audible", "autoprefixer", "avianex", "aviato",
"aws", "bandcamp", "behance", "behance-square", "bimobject",
"bitbucket", "bitcoin", "bity", "black-tie", "blackberry", "blogger",
"blogger-b", "bluetooth", "bluetooth-b", "btc", "buromobelexperte",
"buysellads", "cc-amazon-pay", "cc-amex", "cc-apple-pay", "cc-diners-club",
"cc-discover", "cc-jcb", "cc-mastercard", "cc-paypal", "cc-stripe",
"cc-visa", "centercode", "chrome", "cloudscale", "cloudsmith",
"cloudversify", "codepen", "codiepie", "connectdevelop", "contao",
"cpanel", "creative-commons", "creative-commons-by", "creative-commons-nc",
"creative-commons-nc-eu", "creative-commons-nc-jp", "creative-commons-nd",
"creative-commons-pd", "creative-commons-pd-alt", "creative-commons-remix",
"creative-commons-sa", "creative-commons-sampling", "creative-commons-sampling-plus",
"creative-commons-share", "css3", "css3-alt", "cuttlefish", "d-and-d",
"dashcube", "delicious", "deploydog", "deskpro", "deviantart",
"digg", "digital-ocean", "discord", "discourse", "dochub", "docker",
"draft2digital", "dribbble", "dribbble-square", "dropbox", "drupal",
"dyalog", "earlybirds", "ebay", "edge", "elementor", "ello",
"ember", "empire", "envira", "erlang", "ethereum", "etsy", "expeditedssl",
"facebook", "facebook-f", "facebook-messenger", "facebook-square",
"firefox", "first-order", "first-order-alt", "firstdraft", "flickr",
"flipboard", "fly", "font-awesome", "font-awesome-alt", "font-awesome-flag",
"font-awesome-logo-full", "fonticons", "fonticons-fi", "fort-awesome",
"fort-awesome-alt", "forumbee", "foursquare", "free-code-camp",
"freebsd", "fulcrum", "galactic-republic", "galactic-senate",
"get-pocket", "gg", "gg-circle", "git", "git-square", "github",
"github-alt", "github-square", "gitkraken", "gitlab", "gitter",
"glide", "glide-g", "gofore", "goodreads", "goodreads-g", "google",
"google-drive", "google-play", "google-plus", "google-plus-g",
"google-plus-square", "google-wallet", "gratipay", "grav", "gripfire",
"grunt", "gulp", "hacker-news", "hacker-news-square", "hackerrank",
"hips", "hire-a-helper", "hooli", "hornbill", "hotjar", "houzz",
"html5", "hubspot", "imdb", "instagram", "internet-explorer",
"ioxhost", "itunes", "itunes-note", "java", "jedi-order", "jenkins",
"joget", "joomla", "js", "js-square", "jsfiddle", "kaggle", "keybase",
"keycdn", "kickstarter", "kickstarter-k", "korvue", "laravel",
"lastfm", "lastfm-square", "leanpub", "less", "line", "linkedin",
"linkedin-in", "linode", "linux", "lyft", "magento", "mailchimp",
"mandalorian", "markdown", "mastodon", "maxcdn", "medapps", "medium",
"medium-m", "medrt", "meetup", "megaport", "microsoft", "mix",
"mixcloud", "mizuni", "modx", "monero", "napster", "neos", "nimblr",
"nintendo-switch", "node", "node-js", "npm", "ns8", "nutritionix",
"odnoklassniki", "odnoklassniki-square", "old-republic", "opencart",
"openid", "opera", "optin-monster", "osi", "page4", "pagelines",
"palfed", "patreon", "paypal", "periscope", "phabricator", "phoenix-framework",
"phoenix-squadron", "php", "pied-piper", "pied-piper-alt", "pied-piper-hat",
"pied-piper-pp", "pinterest", "pinterest-p", "pinterest-square",
"playstation", "product-hunt", "pushed", "python", "qq", "quinscape",
"quora", "r-project", "ravelry", "react", "readme", "rebel",
"red-river", "reddit", "reddit-alien", "reddit-square", "rendact",
"renren", "replyd", "researchgate", "resolving", "rev", "rocketchat",
"rockrms", "safari", "sass", "schlix", "scribd", "searchengin",
"sellcast", "sellsy", "servicestack", "shirtsinbulk", "shopware",
"simplybuilt", "sistrix", "sith", "skyatlas", "skype", "slack",
"slack-hash", "slideshare", "snapchat", "snapchat-ghost", "snapchat-square",
"soundcloud", "speakap", "spotify", "squarespace", "stack-exchange",
"stack-overflow", "staylinked", "steam", "steam-square", "steam-symbol",
"sticker-mule", "strava", "stripe", "stripe-s", "studiovinari",
"stumbleupon", "stumbleupon-circle", "superpowers", "supple",
"teamspeak", "telegram", "telegram-plane", "tencent-weibo", "the-red-yeti",
"themeco", "themeisle", "trade-federation", "trello", "tripadvisor",
"tumblr", "tumblr-square", "twitch", "twitter", "twitter-square",
"typo3", "uber", "uikit", "uniregistry", "untappd", "usb", "ussunnah",
"vaadin", "viacoin", "viadeo", "viadeo-square", "viber", "vimeo",
"vimeo-square", "vimeo-v", "vine", "vk", "vnv", "vuejs", "weebly",
"weibo", "weixin", "whatsapp", "whatsapp-square", "whmcs", "wikipedia-w",
"windows", "wix", "wolf-pack-battalion", "wordpress", "wordpress-simple",
"wpbeginner", "wpexplorer", "wpforms", "xbox", "xing", "xing-square",
"y-combinator", "yahoo", "yandex", "yandex-international", "yelp",
"yoast", "youtube", "youtube-square", "zhihu"
)

View File

@@ -1402,14 +1402,23 @@ reactiveTimer <- function(intervalMs=1000, session = getDefaultReactiveDomain())
timerHandle <<- scheduleTask(intervalMs, sys.function())
session$cycleStartAction(function() {
doInvalidate <- function() {
lapply(
dependents$values(),
function(dep.ctx) {
dep.ctx$invalidate()
NULL
})
})
}
if (!is.null(session)) {
# If this timer belongs to a session, we must wait until the next cycle is
# ready to invalidate.
session$cycleStartAction(doInvalidate)
} else {
# If this timer doesn't belong to a session, we invalidate right away.
doInvalidate()
}
})
if (!is.null(session)) {

View File

@@ -683,11 +683,42 @@ ShinySession <- R6Class(
# See cycleStartAction
startCycle = function() {
# TODO: This should check for busyCount == 0L, and remove the checks from
# the call sites
if (length(private$cycleStartActionQueue) > 0) {
head <- private$cycleStartActionQueue[[1L]]
private$cycleStartActionQueue <- private$cycleStartActionQueue[-1L]
# After we execute the current cycleStartAction (head), there may be
# more items left on the queue. If the current busyCount > 0, then that
# means an async task is running; whenever that task finishes, it will
# decrement the busyCount back to 0 and a startCycle will then be
# scheduled. But if the current busyCount is 0, it means that either
# busyCount was incremented and then decremented; OR that running head()
# never touched busyCount (one example of the latter is that an input
# changed that didn't actually cause any observers to be invalidated,
# i.e. an input that's used in the body of an observeEvent). Because of
# the possibility of the latter case, we need to conditionally schedule
# a startCycle ourselves to ensure that the remaining queue items get
# processed.
#
# Since we can't actually tell whether head() increment and decremented
# busyCount, it's possible we're calling startCycle spuriously; that's
# OK, it's essentially a no-op in that case.
on.exit({
if (private$busyCount == 0L && length(private$cycleStartActionQueue) > 0L) {
later::later(function() {
if (private$busyCount == 0L) {
private$startCycle()
}
})
}
}, add = TRUE)
head()
}
invisible()
}
),
public = list(

View File

@@ -30,10 +30,6 @@ of a button, or as an icon for a \code{\link{tabPanel}} within a
\code{\link{navbarPage}}.
}
\examples{
icon("calendar") # standard icon
icon("calendar", "fa-3x") # 3x normal size
icon("cog", lib = "glyphicon") # From glyphicon library
# add an icon to a submit button
submitButton("Update View", icon = icon("refresh"))