R/mod_app.R

Defines functions create_translator html_dependencies get_ide_theme_info create_chat_app_theme rgb_str_to_hex mod_app_server mod_app_ui

Documented in create_chat_app_theme create_translator get_ide_theme_info mod_app_server mod_app_ui rgb_str_to_hex

#' App UI
#'
#' @param id id of the module
#' @inheritParams run_chatgpt_app
#'
#' @import htmltools
#' @import shiny
#'
mod_app_ui <- function(id, ide_colors = get_ide_theme_info()) {
  ns <- NS(id)
  translator <- create_translator(language = getOption("gptstudio.language"))
  tagList(
    waiter::use_waiter(),
    bslib::page_fluid(
      theme = create_chat_app_theme(ide_colors),
      title = "ChatGPT from gptstudio",
      class = "vh-100 p-0 m-0",
      html_dependencies(),
      bslib::layout_sidebar(
        class = "vh-100",
        sidebar = bslib::sidebar(
          open = "closed",
          width = 300,
          class = "p-0",
          padding = "0.5rem",
          mod_sidebar_ui(ns("sidebar"), translator)
        ),
        div(
          class = "row justify-content-center h-100",
          div(
            class = "col h-100",
            style = htmltools::css(`max-width` = "800px"),
            mod_chat_ui(ns("chat"), translator)
          )
        )
      )
    )
  )
}

#' App Server
#'
#' @inheritParams mod_app_ui
#' @inheritParams run_chatgpt_app
#'
mod_app_server <- function(id, ide_colors = get_ide_theme_info()) {
  moduleServer(id, function(input, output, session) {
    sidebar <- mod_sidebar_server("sidebar")
    mod_chat_server(
      id = "chat",
      ide_colors = ide_colors,
      translator = NULL,
      settings = sidebar$settings,
      history = sidebar$history
    )
  })
}


#' RGB str to hex
#'
#' @param rgb_string The RGB string as returned by `rstudioapi::getThemeInfo()`
#'
#' @return hex color
rgb_str_to_hex <- function(rgb_string) {
  rgb_vec <- unlist(strsplit(gsub("[rgba() ]", "", rgb_string), ","))
  grDevices::rgb(
    red = as.numeric(rgb_vec[1]),
    green = as.numeric(rgb_vec[2]),
    blue = as.numeric(rgb_vec[3]),
    names = FALSE,
    maxColorValue = 255
  ) %>%
    unname()
}

#' Chat App Theme
#'
#' Create a bslib theme that matches the user's RStudio IDE theme.
#'
#' @inheritParams run_chatgpt_app
#'
#' @return A bslib theme
create_chat_app_theme <- function(ide_colors = get_ide_theme_info()) {
  bslib::bs_theme(
    version = 5,
    bg = ide_colors$bg,
    fg = ide_colors$fg,
    font_scale = 0.9,
    `btn-padding-x` = "1em",
    `btn-padding-y` = ".5em"
  )
}


#' Get IDE theme information.
#'
#' This function returns a list with the current IDE theme's information.
#'
#' @return A list with three components:
#' \item{is_dark}{A boolean indicating whether the current IDE theme is dark.}
#' \item{bg}{The current IDE theme's background color.}
#' \item{fg}{The current IDE theme's foreground color.}
#'
#' @export
#'
get_ide_theme_info <- function() {
  if (rstudioapi::isAvailable()) {
    rstudio_theme_info <- rstudioapi::getThemeInfo()

    # create a list with three components
    list(
      is_dark = rstudio_theme_info$dark,
      bg = rgb_str_to_hex(rstudio_theme_info$background),
      fg = rgb_str_to_hex(rstudio_theme_info$foreground)
    )
  } else {
    if (interactive()) cli::cli_inform("Using fallback ide theme")

    # create a list with three components with fallback values
    list(
      is_dark = TRUE,
      bg = "#002B36",
      fg = "#93A1A1"
    )
  }
}

html_dependencies <- function() {
  htmltools::htmlDependency(
    name = "gptstudio-assets", version = "0.4.0",
    package = "gptstudio",
    src = "assets",
    script = c("js/copyToClipboard.js", "js/shiftEnter.js", "js/conversation.js"),
    stylesheet = c("css/mod_app.css")
  )
}

#' Internationalization for the ChatGPT addin
#'
#' The language can be set via `options("gptstudio.language" = "<language>")`
#' (defaults to "en").
#'
#' @param language The language to be found in the translation JSON file.
#'
#' @return A Translator from `shiny.i18n::Translator`
create_translator <- function(language = getOption("gptstudio.language")) {
  translator <- shiny.i18n::Translator$new(
    translation_json_path = system.file("translations/translation.json", package = "gptstudio")
  )
  supported_languages <- translator$get_languages()

  if (!language %in% supported_languages) {
    cli::cli_abort("Language {.val {language}} is not supported. Must be one of {.val {supported_languages}}") # nolint
  }

  translator$set_translation_language(language)

  translator
}

Try the gptstudio package in your browser

Any scripts or data that you put into this service are public.

gptstudio documentation built on May 29, 2024, 12:30 p.m.