🤷‍♂️ RStudio Addin to Search and Copy Emoji
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

185 lines
4.9KB

  1. #' Emoji Picker
  2. #'
  3. #' An emoji picker gadget that lets you search and find emoji and insert either
  4. #' the unicode, HTML, or `emo::ji()` versions of the emoji. Built using the
  5. #' [Emoji Button](https://emoji-button.js.org/) JavaScript library.
  6. #'
  7. #' @return A list with the `emoji`, the emoji `name` and the `html` entity.
  8. #'
  9. #' @param gadget If `TRUE` the app is run as a gadget, otherwise it's run as a
  10. #' standalone app.
  11. #'
  12. #' @export
  13. emoji_picker <- function(gadget = TRUE) {
  14. shiny::addResourcePath("eb", system.file("picker", package = "ermoji"))
  15. if (gadget) {
  16. shiny::runGadget(
  17. emoji_picker_ui(),
  18. emoji_picker_server(quick_add = TRUE),
  19. viewer = shiny::dialogViewer("ermoji", width = 375, height = 463)
  20. )
  21. } else {
  22. shiny::shinyApp(emoji_picker_ui(), emoji_picker_server(quick_add = FALSE))
  23. }
  24. }
  25. emoji_picker_ui <- function() {
  26. shiny::fluidPage(
  27. id = "picker-gadget",
  28. class = paste(
  29. if (is_rstudio_dark()) "dark-theme",
  30. get_picker_type()
  31. ),
  32. shiny::div(id = "emoji-picker", style = "width: 100%; min-height: 425; position: relative;"),
  33. shiny::HTML('<div id="alert_bad_emo_ji" class="alert alert-danger" role="alert"><strong style="font-family: monospace">emo</strong> doesn\'t know the emoji <strong id="bad_emo_ji_name"></strong></div>'),
  34. rstudio_style(),
  35. shiny::tags$script(src = "eb/emoji-picker.js", type = "module"),
  36. shiny::tags$head(
  37. shiny::tags$script(src = 'eb/he.js'),
  38. shiny::tags$style('
  39. .emoji-picker__plugin-container { justify-content: space-between; }
  40. .emoji-picker { border-radius: 0 !important; }
  41. #alert_bad_emo_ji {
  42. position: fixed;
  43. top: 0;
  44. left: 0;
  45. right: 0;
  46. z-index: 9999;
  47. border-radius: 0;
  48. transform: translateY(-100px);
  49. transition: transform 0.5s ease-in;
  50. text-align: center;
  51. }
  52. #alert_bad_emo_ji.show-bad-emo-ji {
  53. transform: translateY(0);
  54. }
  55. #bad_emo_ji_name {
  56. white-space: nowrap;
  57. }
  58. '
  59. )
  60. )
  61. )
  62. }
  63. is_rstudio_dark <- function() {
  64. if (rstudioapi::hasFun("getThemeInfo")) {
  65. rstudioapi::getThemeInfo()$dark
  66. } else {
  67. FALSE
  68. }
  69. }
  70. rstudio_style <- function() {
  71. if (!rstudioapi::hasFun("getThemeInfo")) {
  72. return(NULL)
  73. }
  74. theme <- rstudioapi::getThemeInfo()
  75. shiny::tags$style(shiny::HTML(paste0(
  76. ".emoji-picker {\n",
  77. if (theme$dark) " --dark-background-color: " else " --background-color: ", theme$background, ";\n",
  78. if (theme$dark) " --dark-text-color: " else " --text-color: ", theme$foreground, ";\n",
  79. "}\n",
  80. "body { background-color: ", theme$background, "; color: ", theme$foreground, ";}\n",
  81. "#picker_type {\n",
  82. " display: flex;\n",
  83. " justify-content: space-between;\n",
  84. " width: 100%;\n",
  85. "}"
  86. )))
  87. }
  88. set_picker_type <- function(style = c("unicode", "html", "emo_ji")) {
  89. if (!rstudioapi::hasFun("setPersistentValue")) {
  90. return()
  91. }
  92. style <- match.arg(style)
  93. rstudioapi::setPersistentValue("ermoji.picker_type", style)
  94. invisible(style)
  95. }
  96. get_picker_type <- function() {
  97. if (!rstudioapi::hasFun("setPersistentValue")) {
  98. return("unicode")
  99. }
  100. style <- rstudioapi::getPersistentValue("ermoji.picker_type")
  101. if (is.null(style)) {
  102. return("unicode")
  103. }
  104. if (!style %in% c("unicode", "html", "emo_ji")) {
  105. return("unicode")
  106. }
  107. style
  108. }
  109. emoji_picker_server <- function(quick_add = TRUE, context = NULL) {
  110. if (is.null(context)) {
  111. context <- rstudioapi::getActiveDocumentContext()
  112. }
  113. initial_search <- if (nzchar(context$selection[[1]]$text)) {
  114. context$selection[[1]]$text
  115. }
  116. function(input, output, session) {
  117. shiny::observeEvent(input$close, {
  118. shiny::stopApp(invisible(input$emoji))
  119. })
  120. shiny::observe({
  121. session$sendCustomMessage('update_picker_type', get_picker_type())
  122. session$sendCustomMessage("search_emoji", initial_search)
  123. })
  124. shiny::observeEvent(input$picker_type, {
  125. set_picker_type(input$picker_type)
  126. })
  127. shiny::observeEvent(input$emoji, {
  128. emoji <- switch(
  129. input$picker_type,
  130. "unicode" = input$emoji$emoji,
  131. "html" = input$emoji$html,
  132. "emo_ji" = try_emo_ji(input$emoji$name, session = session)
  133. )
  134. if (!is.null(emoji)) {
  135. rstudioapi::insertText(
  136. location = Map(function(x) x$range, context$selection),
  137. text = emoji,
  138. id = context$id
  139. )
  140. if (isTRUE(quick_add)) {
  141. shiny::stopApp(invisible(input$emoji))
  142. }
  143. }
  144. })
  145. }
  146. }
  147. try_emo_ji <- function(name, session = shiny::getDefaultReactiveDomain()) {
  148. emo_ji <- tryCatch({
  149. emo::ji(name)
  150. paste0('emo::ji("', name, '")')
  151. },
  152. error = function(e) {
  153. NULL
  154. }
  155. )
  156. if (!is.null(emo_ji)) return(emo_ji)
  157. name_no_space <- gsub(" ", "_", name)
  158. tryCatch({
  159. emo::ji(name_no_space)
  160. paste0('emo::ji("', name_no_space, '")')
  161. },
  162. error = function(e) {
  163. session$sendCustomMessage("bad_emo_ji", name)
  164. message("{emo} doesn't know the emoji ", shQuote(name))
  165. NULL
  166. }
  167. )
  168. }