mirror of
https://github.com/anotherhadi/spilltea.git
synced 2026-05-20 01:32:33 +02:00
Init
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"charm.land/bubbles/v2/key"
|
||||
tea "charm.land/bubbletea/v2"
|
||||
"github.com/anotherhadi/spilltea/internal/config"
|
||||
"github.com/anotherhadi/spilltea/internal/intercept"
|
||||
"github.com/anotherhadi/spilltea/internal/keys"
|
||||
"github.com/anotherhadi/spilltea/internal/plugins"
|
||||
proxyPkg "github.com/anotherhadi/spilltea/internal/proxy"
|
||||
copyasUI "github.com/anotherhadi/spilltea/internal/ui/components/copyas"
|
||||
notificationsUI "github.com/anotherhadi/spilltea/internal/ui/components/notifications"
|
||||
diffUI "github.com/anotherhadi/spilltea/internal/ui/diff"
|
||||
findingsUI "github.com/anotherhadi/spilltea/internal/ui/findings"
|
||||
historyUI "github.com/anotherhadi/spilltea/internal/ui/history"
|
||||
interceptUI "github.com/anotherhadi/spilltea/internal/ui/intercept"
|
||||
replayUI "github.com/anotherhadi/spilltea/internal/ui/replay"
|
||||
scopeUI "github.com/anotherhadi/spilltea/internal/ui/scope"
|
||||
)
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
// Broker messages must always re-register their watchers
|
||||
switch msg := msg.(type) {
|
||||
case notificationsUI.NotificationMsg:
|
||||
var cmd tea.Cmd
|
||||
m.notifications, cmd = m.notifications.Update(msg)
|
||||
return m, cmd
|
||||
case notificationsUI.DismissMsg:
|
||||
var cmd tea.Cmd
|
||||
m.notifications, cmd = m.notifications.Update(msg)
|
||||
return m, cmd
|
||||
case intercept.RequestArrivedMsg:
|
||||
updated, cmd := m.intercept.Update(msg)
|
||||
m.intercept = updated.(interceptUI.Model)
|
||||
return m, tea.Batch(cmd, intercept.WaitForRequest(m.broker))
|
||||
case intercept.ResponseArrivedMsg:
|
||||
updated, cmd := m.intercept.Update(msg)
|
||||
m.intercept = updated.(interceptUI.Model)
|
||||
return m, tea.Batch(cmd, intercept.WaitForResponse(m.broker))
|
||||
|
||||
case plugins.PluginNotifMsg:
|
||||
cmd := plugins.WaitForNotif(m.pluginManager)
|
||||
notifCmd := func() tea.Msg {
|
||||
return notificationsUI.NotificationMsg{
|
||||
Title: msg.Title,
|
||||
Body: msg.Body,
|
||||
Kind: notificationsUI.KindInfo,
|
||||
}
|
||||
}
|
||||
return m, tea.Batch(cmd, notifCmd)
|
||||
|
||||
case plugins.PluginQuitMsg:
|
||||
log.Printf("plugin quit: %s", msg.Reason)
|
||||
m.pluginManager.RunOnQuit()
|
||||
return m, tea.Quit
|
||||
}
|
||||
|
||||
if m.copyAs.IsOpen() {
|
||||
if ws, ok := msg.(tea.WindowSizeMsg); ok {
|
||||
m.width = ws.Width
|
||||
m.height = ws.Height
|
||||
m.copyAs.SetSize(ws.Width, ws.Height)
|
||||
m.resizeChildren()
|
||||
return m, nil
|
||||
}
|
||||
var cmd tea.Cmd
|
||||
m.copyAs, cmd = m.copyAs.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
m.height = msg.Height
|
||||
m.resizeChildren()
|
||||
|
||||
case scopeUI.ScopeChangedMsg:
|
||||
m.broker.SetScope(msg.Whitelist, msg.Blacklist)
|
||||
if m.database != nil {
|
||||
if err := m.database.SaveScope(msg.Whitelist, msg.Blacklist); err != nil {
|
||||
log.Printf("failed to persist scope: %v", err)
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
|
||||
case proxyPkg.ErrMsg:
|
||||
if msg.Err != nil {
|
||||
log.Printf("proxy error: %v", msg.Err)
|
||||
}
|
||||
return m, nil
|
||||
|
||||
case tickMsg:
|
||||
var cmds []tea.Cmd
|
||||
cmds = append(cmds, tickCmd())
|
||||
if m.page == pageHistory {
|
||||
cmds = append(cmds, m.history.RefreshCmd())
|
||||
}
|
||||
cmds = append(cmds, findingsUI.RefreshCmd(m.database))
|
||||
return m, tea.Batch(cmds...)
|
||||
|
||||
case findingsUI.FindingsLoadedMsg:
|
||||
updated, cmd := m.findingsPage.Update(msg)
|
||||
m.findingsPage = updated.(findingsUI.Model)
|
||||
return m, cmd
|
||||
|
||||
case replayUI.SendToReplayMsg:
|
||||
updated, cmd := m.replay.Update(msg)
|
||||
m.replay = updated.(replayUI.Model)
|
||||
if config.Global.Replay.SwitchToPageOnSend {
|
||||
m.page = pageReplay
|
||||
m.resizeChildren()
|
||||
} else {
|
||||
return m, tea.Batch(cmd, func() tea.Msg {
|
||||
return notificationsUI.NotificationMsg{
|
||||
Title: "Replay",
|
||||
Body: "Request queued in replay",
|
||||
Kind: notificationsUI.KindInfo,
|
||||
}
|
||||
})
|
||||
}
|
||||
return m, cmd
|
||||
|
||||
case diffUI.SendToDiffMsg:
|
||||
updated, cmd := m.diff.Update(msg)
|
||||
m.diff = updated.(diffUI.Model)
|
||||
return m, cmd
|
||||
|
||||
case diffUI.DiffReadyMsg:
|
||||
m.page = pageDiff
|
||||
m.resizeChildren()
|
||||
return m, nil
|
||||
|
||||
case historyUI.EntriesLoadedMsg:
|
||||
updated, cmd := m.history.Update(msg)
|
||||
m.history = updated.(historyUI.Model)
|
||||
return m, cmd
|
||||
|
||||
case tea.KeyPressMsg:
|
||||
// ctrl+c always quits, even when a textarea is focused.
|
||||
if msg.String() == "ctrl+c" {
|
||||
m.pluginManager.RunOnQuit()
|
||||
return m, tea.Quit
|
||||
}
|
||||
if key.Matches(msg, keys.Keys.Global.Quit) && !m.activeIsEditing() {
|
||||
m.pluginManager.RunOnQuit()
|
||||
return m, tea.Quit
|
||||
}
|
||||
|
||||
if key.Matches(msg, keys.Keys.Global.OpenLogs) {
|
||||
editor := os.Getenv("EDITOR")
|
||||
if editor == "" {
|
||||
editor = "vi"
|
||||
}
|
||||
logPath := filepath.Join(filepath.Dir(m.projectPath), "logs.log")
|
||||
return m, tea.ExecProcess(exec.Command(editor, logPath), nil)
|
||||
}
|
||||
|
||||
if !m.activeIsEditing() {
|
||||
switch {
|
||||
case key.Matches(msg, keys.Keys.Global.CopyRequest):
|
||||
if m.page == pageDiff {
|
||||
if raw := m.diff.CurrentRaw(); raw != "" {
|
||||
m.copyAs.SetSize(m.width, m.height)
|
||||
m.copyAs.Open(copyasUI.OpenMsg{
|
||||
RawRequest: raw,
|
||||
Scheme: "https",
|
||||
})
|
||||
}
|
||||
} else if m.page == pageIntercept {
|
||||
if raw := m.intercept.CurrentRaw(); raw != "" {
|
||||
m.copyAs.SetSize(m.width, m.height)
|
||||
m.copyAs.Open(copyasUI.OpenMsg{
|
||||
RawRequest: raw,
|
||||
Scheme: m.intercept.CurrentScheme(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, keys.Keys.Global.ToggleSidebar):
|
||||
m.cycleSidebarState()
|
||||
m.resizeChildren()
|
||||
|
||||
default:
|
||||
if p, ok := pageShortcuts[msg.String()]; ok {
|
||||
prev := m.page
|
||||
m.page = p
|
||||
if p == pageHistory && prev != pageHistory {
|
||||
return m, m.history.RefreshCmd()
|
||||
}
|
||||
if p == pageFindings {
|
||||
return m, findingsUI.RefreshCmd(m.database)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var cmd tea.Cmd
|
||||
m, cmd = m.updateActivePage(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func (m Model) activeIsEditing() bool {
|
||||
for _, e := range pageRegistry {
|
||||
if e.id == m.page && e.isEditing != nil {
|
||||
return e.isEditing(&m)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m Model) updateActivePage(msg tea.Msg) (Model, tea.Cmd) {
|
||||
for _, e := range pageRegistry {
|
||||
if e.id == m.page && e.update != nil {
|
||||
cmd := e.update(&m, msg)
|
||||
return m, cmd
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *Model) resizeChildren() {
|
||||
sidebarW := m.getSidebarWidth()
|
||||
h := m.height
|
||||
for _, e := range pageRegistry {
|
||||
if e.resize == nil {
|
||||
continue
|
||||
}
|
||||
e.resize(m, m.width-sidebarW, h)
|
||||
}
|
||||
m.notifications.SetSize(m.width, m.height)
|
||||
}
|
||||
Reference in New Issue
Block a user