mirror of
https://github.com/Kyren223/eko.git
synced 2025-09-05 21:18:14 +00:00
Added the ability to view user profiles
This commit is contained in:
@@ -165,13 +165,20 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
m.SetIndex(m.index + m.height/2)
|
||||
|
||||
case "p":
|
||||
// TODO: profile
|
||||
if 0 <= m.index && m.index < len(members) {
|
||||
member := members[m.index]
|
||||
return m, func() tea.Msg {
|
||||
return ui.ProfilePopupMsg{
|
||||
User: member.UserID,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case "v", "V":
|
||||
if 0 <= m.index && m.index < len(members) {
|
||||
member := members[m.index]
|
||||
return m, func() tea.Msg {
|
||||
return ui.BanViewPopupmsg{
|
||||
return ui.BanViewPopupMsg{
|
||||
Network: m.networkId,
|
||||
User: member.UserID,
|
||||
}
|
||||
|
@@ -13,12 +13,6 @@ import (
|
||||
|
||||
var width = 48
|
||||
|
||||
const (
|
||||
BanReasonField = iota
|
||||
BanField
|
||||
FieldCount
|
||||
)
|
||||
|
||||
type Model struct {
|
||||
banReason string
|
||||
name string
|
||||
|
@@ -413,6 +413,17 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
m.SetIndex(Unselected)
|
||||
}
|
||||
|
||||
case "p":
|
||||
if m.selectedMessage == nil {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
return m, func() tea.Msg {
|
||||
return ui.ProfilePopupMsg{
|
||||
User: m.selectedMessage.SenderID,
|
||||
}
|
||||
}
|
||||
|
||||
case "x", "d":
|
||||
if m.selectedMessage == nil {
|
||||
return m, nil
|
||||
|
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/kyren223/eko/internal/client/ui/core/networkjoin"
|
||||
"github.com/kyren223/eko/internal/client/ui/core/networklist"
|
||||
"github.com/kyren223/eko/internal/client/ui/core/networkupdate"
|
||||
"github.com/kyren223/eko/internal/client/ui/core/profile"
|
||||
"github.com/kyren223/eko/internal/client/ui/core/signaladd"
|
||||
"github.com/kyren223/eko/internal/client/ui/core/signallist"
|
||||
"github.com/kyren223/eko/internal/client/ui/core/state"
|
||||
@@ -80,6 +81,7 @@ type Model struct {
|
||||
banReasonPopup *banreason.Model
|
||||
banViewPopup *banview.Model
|
||||
signalAddPopup *signaladd.Model
|
||||
profilePopup *profile.Model
|
||||
networkList networklist.Model
|
||||
signalList signallist.Model
|
||||
frequencyList frequencylist.Model
|
||||
@@ -171,6 +173,8 @@ func (m Model) View() string {
|
||||
popup = m.banViewPopup.View()
|
||||
} else if m.signalAddPopup != nil {
|
||||
popup = m.signalAddPopup.View()
|
||||
} else if m.profilePopup != nil {
|
||||
popup = m.profilePopup.View()
|
||||
} else {
|
||||
assert.Never("missing handling of a popup!")
|
||||
}
|
||||
@@ -349,10 +353,14 @@ func (m *Model) updateConnected(message tea.Msg) tea.Cmd {
|
||||
popup := banreason.New(msg.User, msg.Network)
|
||||
m.banReasonPopup = &popup
|
||||
|
||||
case ui.BanViewPopupmsg:
|
||||
case ui.BanViewPopupMsg:
|
||||
popup := banview.New(msg.User, msg.Network)
|
||||
m.banViewPopup = &popup
|
||||
|
||||
case ui.ProfilePopupMsg:
|
||||
popup := profile.New(msg.User)
|
||||
m.profilePopup = &popup
|
||||
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "n":
|
||||
@@ -482,6 +490,7 @@ func (m *Model) updateConnected(message tea.Msg) tea.Cmd {
|
||||
m.banReasonPopup = nil
|
||||
m.banViewPopup = nil
|
||||
m.signalAddPopup = nil
|
||||
m.profilePopup = nil
|
||||
}
|
||||
|
||||
case "enter":
|
||||
@@ -538,6 +547,8 @@ func (m *Model) updateConnected(message tea.Msg) tea.Cmd {
|
||||
m.signalList.SetIndex(i)
|
||||
}
|
||||
return cmd
|
||||
} else if m.profilePopup != nil {
|
||||
m.profilePopup = nil
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -689,6 +700,10 @@ func (m *Model) updatePopups(msg tea.Msg) tea.Cmd {
|
||||
popup, cmd := m.signalAddPopup.Update(msg)
|
||||
m.signalAddPopup = &popup
|
||||
return cmd
|
||||
} else if m.profilePopup != nil {
|
||||
popup, cmd := m.profilePopup.Update(msg)
|
||||
m.profilePopup = &popup
|
||||
return cmd
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -703,7 +718,8 @@ func (m *Model) HasPopup() bool {
|
||||
m.networkJoinPopup != nil ||
|
||||
m.banReasonPopup != nil ||
|
||||
m.banViewPopup != nil ||
|
||||
m.signalAddPopup != nil
|
||||
m.signalAddPopup != nil ||
|
||||
m.profilePopup != nil
|
||||
}
|
||||
|
||||
func calculateNotifications() {
|
||||
|
@@ -200,7 +200,13 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
m.SetIndex(m.index + m.height/2)
|
||||
|
||||
case "p":
|
||||
// TODO: profile
|
||||
member := m.Members()[m.index]
|
||||
|
||||
return m, func() tea.Msg {
|
||||
return ui.ProfilePopupMsg{
|
||||
User: member.UserID,
|
||||
}
|
||||
}
|
||||
|
||||
// Normal
|
||||
case "T":
|
||||
|
145
internal/client/ui/core/profile/profile.go
Normal file
145
internal/client/ui/core/profile/profile.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/kyren223/eko/internal/client/ui/colors"
|
||||
"github.com/kyren223/eko/internal/client/ui/core/state"
|
||||
"github.com/kyren223/eko/pkg/assert"
|
||||
"github.com/kyren223/eko/pkg/snowflake"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
var width = 70
|
||||
|
||||
type Model struct {
|
||||
id snowflake.ID
|
||||
}
|
||||
|
||||
func New(userId snowflake.ID) Model {
|
||||
return Model{
|
||||
id: userId,
|
||||
}
|
||||
}
|
||||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m Model) View() string {
|
||||
user := state.State.Users[m.id]
|
||||
|
||||
var builder strings.Builder
|
||||
|
||||
headerStyle := lipgloss.NewStyle().
|
||||
PaddingLeft(2).
|
||||
Width(width).
|
||||
Background(colors.Background).
|
||||
Foreground(colors.Focus)
|
||||
|
||||
name := user.Name
|
||||
name = lipgloss.NewStyle().
|
||||
MarginBackground(colors.Background).
|
||||
Background(colors.Gold).
|
||||
Foreground(colors.Background).
|
||||
Bold(true).
|
||||
Render(name)
|
||||
paddingLeft := lipgloss.NewStyle().
|
||||
MarginLeft(2).
|
||||
Background(colors.Background).
|
||||
Foreground(colors.Gold).
|
||||
Render("")
|
||||
paddingRight := lipgloss.NewStyle().
|
||||
MarginRight(2).
|
||||
Background(colors.Background).
|
||||
Foreground(colors.Gold).
|
||||
Render("")
|
||||
builder.WriteString(paddingLeft)
|
||||
builder.WriteString(name)
|
||||
builder.WriteString(paddingRight)
|
||||
builder.WriteByte('\n')
|
||||
builder.WriteByte('\n')
|
||||
|
||||
publicDMs := "Private DMs"
|
||||
if user.IsPublicDM {
|
||||
publicDMs = "Public DMs"
|
||||
}
|
||||
|
||||
id := strconv.FormatInt(int64(user.ID), 10)
|
||||
info := lipgloss.NewStyle().
|
||||
PaddingLeft(2).
|
||||
Width(width).
|
||||
Background(colors.Background).
|
||||
Foreground(colors.LightGray).
|
||||
Render("ID: " + id + " | " + publicDMs)
|
||||
builder.WriteString(info)
|
||||
builder.WriteByte('\n')
|
||||
builder.WriteByte('\n')
|
||||
|
||||
publicKeyHeader := headerStyle.Render("Public Key (ssh-ed25519)")
|
||||
publicKey := lipgloss.NewStyle().
|
||||
PaddingLeft(2).
|
||||
Width(width).
|
||||
Render(publicKeyToSshString(user.PublicKey))
|
||||
builder.WriteString(publicKeyHeader)
|
||||
builder.WriteByte('\n')
|
||||
builder.WriteByte('\n')
|
||||
builder.WriteString(publicKey)
|
||||
builder.WriteByte('\n')
|
||||
|
||||
aboutMeHeader := headerStyle.Render("About me")
|
||||
builder.WriteString(aboutMeHeader)
|
||||
builder.WriteByte('\n')
|
||||
builder.WriteByte('\n')
|
||||
|
||||
textBg := colors.BackgroundHighlight
|
||||
textFg := colors.White
|
||||
bg := colors.Background
|
||||
|
||||
description := user.Description
|
||||
if description == "" {
|
||||
description = lipgloss.NewStyle().
|
||||
Foreground(colors.Purple).
|
||||
Render("No description was provided")
|
||||
}
|
||||
|
||||
excessWidth := 4 - 2
|
||||
bgStyle := lipgloss.NewStyle().Background(textBg).Foreground(bg)
|
||||
topMiddle := strings.Repeat(" ", width-excessWidth)
|
||||
top := bgStyle.Render("🭠🭘" + topMiddle + "🭣🭕")
|
||||
middle := lipgloss.NewStyle().Width(width+2).Padding(0, 2).
|
||||
Background(textBg).Foreground(textFg).Render(description)
|
||||
bgStyle2 := lipgloss.NewStyle().Foreground(textBg)
|
||||
bottomMiddle := strings.Repeat("█", width-excessWidth)
|
||||
bottom := bgStyle2.Render("🭥🭓" + bottomMiddle + "🭞🭚")
|
||||
aboutMe := lipgloss.JoinVertical(lipgloss.Left, top, middle, bottom)
|
||||
|
||||
builder.WriteString(aboutMe)
|
||||
|
||||
content := builder.String()
|
||||
|
||||
return lipgloss.NewStyle().
|
||||
Border(lipgloss.ThickBorder()).
|
||||
Padding(1, 2).
|
||||
Align(lipgloss.Left, lipgloss.Center).
|
||||
BorderBackground(colors.Background).
|
||||
BorderForeground(colors.White).
|
||||
Background(colors.Background).
|
||||
Foreground(colors.White).
|
||||
Render(content)
|
||||
}
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func publicKeyToSshString(pub ed25519.PublicKey) string {
|
||||
sshPubKey, err := ssh.NewPublicKey(pub)
|
||||
assert.NoError(err, "converting to ssh key should never fail")
|
||||
sshPubKeyBytes := ssh.MarshalAuthorizedKey(sshPubKey)
|
||||
return strings.Split(string(sshPubKeyBytes), " ")[1]
|
||||
}
|
@@ -185,6 +185,18 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
case "i":
|
||||
_ = clipboard.WriteAll(strconv.FormatInt(int64(*state.UserID), 10))
|
||||
|
||||
case "p":
|
||||
if m.index == -1 {
|
||||
return m, nil
|
||||
}
|
||||
userId := state.Data.Signals[m.index]
|
||||
|
||||
return m, func() tea.Msg {
|
||||
return ui.ProfilePopupMsg{
|
||||
User: userId,
|
||||
}
|
||||
}
|
||||
|
||||
case "c":
|
||||
if m.index == -1 {
|
||||
return m, nil
|
||||
|
@@ -57,7 +57,11 @@ func Transition(model tea.Model) tea.Cmd {
|
||||
|
||||
type QuitMsg struct{}
|
||||
|
||||
type BanViewPopupmsg struct {
|
||||
type ProfilePopupMsg struct {
|
||||
User snowflake.ID
|
||||
}
|
||||
|
||||
type BanViewPopupMsg struct {
|
||||
Network snowflake.ID
|
||||
User snowflake.ID
|
||||
}
|
||||
|
Reference in New Issue
Block a user