Skip to content

Commit

Permalink
chore: Restore legacy autoreload watcher if {watcher} not installed
Browse files Browse the repository at this point in the history
  • Loading branch information
gadenbuie committed Feb 28, 2025
1 parent f52efec commit b3f2948
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 25 deletions.
6 changes: 3 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ Imports:
glue (>= 1.3.2),
bslib (>= 0.6.0),
cachem (>= 1.1.0),
lifecycle (>= 0.2.0),
watcher
lifecycle (>= 0.2.0)
Suggests:
coro (>= 1.1.0),
datasets,
Expand All @@ -112,7 +111,8 @@ Suggests:
dygraphs,
ragg,
showtext,
sass
sass,
watcher
URL: https://shiny.posit.co/,
https://github.com/rstudio/shiny
BugReports: https://github.com/rstudio/shiny/issues
Expand Down
84 changes: 62 additions & 22 deletions R/shinyapp.R
Original file line number Diff line number Diff line change
Expand Up @@ -313,32 +313,72 @@ initAutoReloadMonitor <- function(dir) {
".*\\.(r|html?|js|css|png|jpe?g|gif)$"
)

lastValue <- NULL
check_for_update <- function(paths) {
paths <- grep(
filePattern,
paths,
ignore.case = TRUE,
value = TRUE
)

if (length(paths) == 0) {
return()

if (is_installed("watcher")) {
check_for_update <- function(paths) {
paths <- grep(
filePattern,
paths,
ignore.case = TRUE,
value = TRUE
)

if (length(paths) == 0) {
return()
}

cachedAutoReloadLastChanged$set()
autoReloadCallbacks$invoke()
}

# [garrick, 2025-02-20] Shiny <= v1.10.0 used `invalidateLater()` with an
# autoreload.interval in ms. {watcher} instead uses a latency parameter in
# seconds, which serves a similar purpose and that I'm keeping for backcompat.
latency <- getOption("shiny.autoreload.interval", 250) / 1000
watcher <- watcher::watcher(dir, check_for_update, latency = latency)
watcher$start()
onStop(watcher$stop)
} else {
# Fall back to legacy observer behavior
if (!isFALSE(getOption("shiny.autoreload.legacy_warning", TRUE))) {
cli::cli_warn(
c(
"Using legacy autoreload file watching. Please install {.pkg watcher} for a more performant autoreload file watcher.",
"i" = "Set {.run options(shiny.autoreload.legacy_warning = FALSE)} to suppress this warning."
),
.frequency = "regularly",
.frequency_id = "shiny.autoreload.legacy_warning"
)
}

cachedAutoReloadLastChanged$set()
autoReloadCallbacks$invoke()
lastValue <- NULL
observeLabel <- paste0("File Auto-Reload - '", basename(dir), "'")
watcher <- observe(label = observeLabel, {
files <- sort_c(
list.files(dir, pattern = filePattern, recursive = TRUE, ignore.case = TRUE)
)
times <- file.info(files)$mtime
names(times) <- files

if (is.null(lastValue)) {
# First run
lastValue <<- times
} else if (!identical(lastValue, times)) {
# We've changed!
lastValue <<- times
cachedAutoReloadLastChanged$set()
autoReloadCallbacks$invoke()
}

invalidateLater(getOption("shiny.autoreload.interval", 500))
})

onStop(watcher$destroy)

watcher$destroy
}

# [garrick, 2025-02-20] Shiny <= v1.10.0 used `invalidateLater()` with an
# autoreload.interval in ms. {watcher} instead uses a latency parameter in
# seconds, which serves a similar purpose and that I'm keeping for backcompat.
latency <- getOption("shiny.autoreload.interval", 250) / 1000
watcher <- watcher::watcher(dir, check_for_update, latency = latency)
watcher$start()
onStop(watcher$stop)

watcher
invisible(watcher)
}

#' Load an app's supporting R files
Expand Down

0 comments on commit b3f2948

Please sign in to comment.