profile.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package init
  2. import (
  3. "fmt"
  4. ti "github.com/charmbracelet/bubbles/textinput"
  5. tea "github.com/charmbracelet/bubbletea"
  6. "github.com/langgenius/dify-plugin-daemon/internal/types/entities/plugin_entities"
  7. )
  8. type profile struct {
  9. cursor int
  10. inputs []ti.Model
  11. warning string
  12. }
  13. func newProfile() profile {
  14. name := ti.New()
  15. name.Placeholder = "Plugin name, a directory will be created with this name"
  16. name.CharLimit = 128
  17. name.Prompt = "Plugin name (press Enter to next step): "
  18. name.Focus()
  19. author := ti.New()
  20. author.Placeholder = "Author name"
  21. author.CharLimit = 128
  22. author.Prompt = "Author (press Enter to next step): "
  23. return profile{
  24. inputs: []ti.Model{name, author},
  25. }
  26. }
  27. func (p profile) Name() string {
  28. return p.inputs[0].Value()
  29. }
  30. func (p profile) Author() string {
  31. return p.inputs[1].Value()
  32. }
  33. func (p profile) View() string {
  34. s := fmt.Sprintf("Edit profile of the plugin\n%s\n%s\n", p.inputs[0].View(), p.inputs[1].View())
  35. if p.warning != "" {
  36. s += fmt.Sprintf("\033[31m%s\033[0m\n", p.warning)
  37. }
  38. return s
  39. }
  40. func (p *profile) checkRule() bool {
  41. if p.inputs[p.cursor].Value() == "" {
  42. p.warning = "Name and author cannot be empty"
  43. return false
  44. } else if p.cursor == 0 && !plugin_entities.PluginNameRegex.MatchString(p.inputs[p.cursor].Value()) {
  45. p.warning = "Plugin name must be 1-128 characters long, and can only contain letters, numbers, dashes and underscores"
  46. return false
  47. } else {
  48. p.warning = ""
  49. }
  50. return true
  51. }
  52. func (p profile) Update(msg tea.Msg) (subMenu, subMenuEvent, tea.Cmd) {
  53. var cmds []tea.Cmd
  54. switch msg := msg.(type) {
  55. case tea.KeyMsg:
  56. switch msg.String() {
  57. case "ctrl+c":
  58. return p, SUB_MENU_EVENT_NONE, tea.Quit
  59. case "down":
  60. // check if empty
  61. if !p.checkRule() {
  62. return p, SUB_MENU_EVENT_NONE, nil
  63. }
  64. // focus next
  65. p.cursor++
  66. if p.cursor >= len(p.inputs) {
  67. p.cursor = 0
  68. }
  69. case "up":
  70. if !p.checkRule() {
  71. return p, SUB_MENU_EVENT_NONE, nil
  72. }
  73. p.cursor--
  74. if p.cursor < 0 {
  75. p.cursor = len(p.inputs) - 1
  76. }
  77. case "enter":
  78. if !p.checkRule() {
  79. return p, SUB_MENU_EVENT_NONE, nil
  80. }
  81. // submit
  82. if p.cursor == len(p.inputs)-1 {
  83. return p, SUB_MENU_EVENT_NEXT, nil
  84. }
  85. // move to next
  86. p.cursor++
  87. }
  88. }
  89. // update cursor
  90. for i := 0; i < len(p.inputs); i++ {
  91. if i == p.cursor {
  92. p.inputs[i].Focus()
  93. } else {
  94. p.inputs[i].Blur()
  95. }
  96. }
  97. // update view
  98. for i := range p.inputs {
  99. var cmd tea.Cmd
  100. p.inputs[i], cmd = p.inputs[i].Update(msg)
  101. if cmd != nil {
  102. cmds = append(cmds, cmd)
  103. }
  104. }
  105. return p, SUB_MENU_EVENT_NONE, tea.Batch(cmds...)
  106. }
  107. func (p profile) Init() tea.Cmd {
  108. return nil
  109. }