|
|
|
@ -271,26 +271,24 @@ func get_private_key(path string, generate bool) ed25519.PrivateKey {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func print_decoration(window, title, channels, body ncurses.Window, top_left string) {
|
|
|
|
|
func print_decoration(window, user, channels, body ncurses.Window) {
|
|
|
|
|
max_y := ncurses.GetMaxY(*ncurses.CurScr)
|
|
|
|
|
max_x := ncurses.GetMaxX(*ncurses.CurScr)
|
|
|
|
|
|
|
|
|
|
ncurses.WResize(window, max_y, max_x)
|
|
|
|
|
ncurses.WResize(title, 1, max_x/4-2)
|
|
|
|
|
ncurses.MvWin(title, 1, 1)
|
|
|
|
|
ncurses.WResize(user, 1, max_x/4-2)
|
|
|
|
|
ncurses.MvWin(user, max_y-2, 1)
|
|
|
|
|
ncurses.WResize(channels, max_y-4, (max_x/4)-1)
|
|
|
|
|
ncurses.MvWin(channels, 3, 1)
|
|
|
|
|
ncurses.MvWin(channels, 1, 1)
|
|
|
|
|
ncurses.WResize(body, max_y-2, max_x-(max_x/4)-2)
|
|
|
|
|
ncurses.MvWin(body, 1, (max_x/4)+1)
|
|
|
|
|
|
|
|
|
|
ncurses.MvWAddStr(title, 0, 0, top_left)
|
|
|
|
|
|
|
|
|
|
for i := 1; i < max_x-1; i++ {
|
|
|
|
|
ncurses.MvWAddStr(window, 0, i, "═")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i := 1; i < max_x/4; i++ {
|
|
|
|
|
ncurses.MvWAddStr(window, 2, i, "═")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y - 3, i, "═")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i := 1; i < max_y-1; i++ {
|
|
|
|
@ -312,14 +310,14 @@ func print_decoration(window, title, channels, body ncurses.Window, top_left str
|
|
|
|
|
ncurses.MvWAddStr(window, 0, 0, "╔")
|
|
|
|
|
ncurses.MvWAddStr(window, 0, max_x-1, "╗")
|
|
|
|
|
ncurses.MvWAddStr(window, 0, max_x/4, "╦")
|
|
|
|
|
ncurses.MvWAddStr(window, 2, 0, "╠")
|
|
|
|
|
ncurses.MvWAddStr(window, 2, max_x/4, "╣")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y-1, 0, "╚")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y-1, max_x/4, "╩")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y-1, max_x-1, "╝")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y - 3, 0, "╠")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y - 3, max_x/4, "╣")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y - 1, 0, "╚")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y - 1, max_x/4, "╩")
|
|
|
|
|
ncurses.MvWAddStr(window, max_y - 1, max_x-1, "╝")
|
|
|
|
|
|
|
|
|
|
ncurses.WRefresh(window)
|
|
|
|
|
ncurses.WRefresh(title)
|
|
|
|
|
ncurses.WRefresh(user)
|
|
|
|
|
ncurses.WRefresh(channels)
|
|
|
|
|
ncurses.WRefresh(body)
|
|
|
|
|
}
|
|
|
|
@ -336,6 +334,7 @@ type PeerState struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type UIState struct {
|
|
|
|
|
Username string
|
|
|
|
|
SelectedBody int
|
|
|
|
|
SelectedPeer int
|
|
|
|
|
SelectedChannel int
|
|
|
|
@ -347,20 +346,22 @@ type UIState struct {
|
|
|
|
|
const (
|
|
|
|
|
AREA_CHANNELS = 0
|
|
|
|
|
AREA_BODY = 1
|
|
|
|
|
AREA_USER = 2
|
|
|
|
|
|
|
|
|
|
BODY_CHANNEL = 0
|
|
|
|
|
BODY_DETAIL = 1
|
|
|
|
|
BODY_QUIT = 2
|
|
|
|
|
BODY_USER = 3
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func handle_back(state *UIState) {
|
|
|
|
|
if state.SelectedArea == AREA_BODY {
|
|
|
|
|
if state.SelectedBody == BODY_QUIT {
|
|
|
|
|
state.SelectedBody = BODY_CHANNEL
|
|
|
|
|
} else if state.SelectedBody == BODY_DETAIL {
|
|
|
|
|
state.SelectedBody = BODY_CHANNEL
|
|
|
|
|
if state.SelectedBody == BODY_USER {
|
|
|
|
|
state.SelectedArea = AREA_USER
|
|
|
|
|
} else {
|
|
|
|
|
state.SelectedArea = AREA_CHANNELS
|
|
|
|
|
}
|
|
|
|
|
state.SelectedArea = AREA_CHANNELS
|
|
|
|
|
state.SelectedBody = BODY_CHANNEL
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -372,6 +373,10 @@ func handle_up(state *UIState) {
|
|
|
|
|
state.SelectedChannel -= 1
|
|
|
|
|
state.SelectedPeer = len(state.Channels[state.SelectedChannel].Members)
|
|
|
|
|
}
|
|
|
|
|
} else if state.SelectedArea == AREA_USER {
|
|
|
|
|
state.SelectedArea = AREA_CHANNELS
|
|
|
|
|
state.SelectedChannel = len(state.Channels) - 1
|
|
|
|
|
state.SelectedPeer = len(state.Channels[state.SelectedChannel].Members)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -382,6 +387,8 @@ func handle_down(state *UIState) {
|
|
|
|
|
} else if state.SelectedChannel < len(state.Channels) - 1 {
|
|
|
|
|
state.SelectedChannel += 1
|
|
|
|
|
state.SelectedPeer = 0
|
|
|
|
|
} else {
|
|
|
|
|
state.SelectedArea = AREA_USER
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -390,6 +397,9 @@ func handle_select(state *UIState) {
|
|
|
|
|
if state.SelectedArea == AREA_CHANNELS {
|
|
|
|
|
state.SelectedArea = AREA_BODY
|
|
|
|
|
state.SelectedBody = BODY_CHANNEL
|
|
|
|
|
} else if state.SelectedArea == AREA_USER {
|
|
|
|
|
state.SelectedArea = AREA_BODY
|
|
|
|
|
state.SelectedBody = BODY_USER
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -437,6 +447,18 @@ func handle_input(state *UIState, char []byte) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func draw_user(state *UIState, user ncurses.Window) {
|
|
|
|
|
ncurses.WErase(user)
|
|
|
|
|
if state.SelectedArea == AREA_USER || state.SelectedBody == BODY_USER {
|
|
|
|
|
ncurses.WAttrOn(user, ncurses.COLOR_PAIR(1))
|
|
|
|
|
}
|
|
|
|
|
ncurses.MvWAddStr(user, 0, 0, state.Username)
|
|
|
|
|
if state.SelectedArea == AREA_USER || state.SelectedBody == BODY_USER {
|
|
|
|
|
ncurses.WAttrOff(user, ncurses.COLOR_PAIR(1))
|
|
|
|
|
}
|
|
|
|
|
ncurses.WRefresh(user)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func draw_channels(state *UIState, channels ncurses.Window) {
|
|
|
|
|
channel_highlight_color := 2
|
|
|
|
|
if state.SelectedArea == AREA_CHANNELS {
|
|
|
|
@ -496,8 +518,15 @@ func draw_body_quit(state *UIState, body ncurses.Window) {
|
|
|
|
|
ncurses.WRefresh(body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func draw_gui(state *UIState, channels, body ncurses.Window) {
|
|
|
|
|
func draw_body_user(state *UIState, body ncurses.Window) {
|
|
|
|
|
ncurses.WErase(body)
|
|
|
|
|
ncurses.MvWAddStr(body, 0, 0, "user")
|
|
|
|
|
ncurses.WRefresh(body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func draw_gui(state *UIState, channels, user, body ncurses.Window) {
|
|
|
|
|
draw_channels(state, channels)
|
|
|
|
|
draw_user(state, user)
|
|
|
|
|
switch state.SelectedBody {
|
|
|
|
|
case BODY_CHANNEL:
|
|
|
|
|
draw_body_channel(state, body)
|
|
|
|
@ -505,14 +534,17 @@ func draw_gui(state *UIState, channels, body ncurses.Window) {
|
|
|
|
|
draw_body_detail(state, body)
|
|
|
|
|
case BODY_QUIT:
|
|
|
|
|
draw_body_quit(state, body)
|
|
|
|
|
case BODY_USER:
|
|
|
|
|
draw_body_user(state, body)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Window, packet_chan chan pnyx.Payload, user_chan chan []byte, sigwinch_channel chan os.Signal) {
|
|
|
|
|
channels := ncurses.NewWin(0, 0, 0, 0)
|
|
|
|
|
body := ncurses.NewWin(0, 0, 0, 0)
|
|
|
|
|
title := ncurses.NewWin(0, 0, 0, 0)
|
|
|
|
|
user := ncurses.NewWin(0, 0, 0, 0)
|
|
|
|
|
state := &UIState{
|
|
|
|
|
Username: "fake user",
|
|
|
|
|
Peers: map[pnyx.PeerID]PeerState{
|
|
|
|
|
[32]byte{}: {
|
|
|
|
|
Name: "Test User 0",
|
|
|
|
@ -547,8 +579,8 @@ func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Wind
|
|
|
|
|
ncurses.InitPair(3, 1, 4)
|
|
|
|
|
ncurses.ScrollOk(body, true)
|
|
|
|
|
|
|
|
|
|
print_decoration(window, title, channels, body, client.Remote())
|
|
|
|
|
draw_gui(state, channels, body)
|
|
|
|
|
print_decoration(window, user, channels, body)
|
|
|
|
|
draw_gui(state, channels, user, body)
|
|
|
|
|
|
|
|
|
|
for client.Active() {
|
|
|
|
|
select {
|
|
|
|
@ -556,8 +588,8 @@ func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Wind
|
|
|
|
|
ncurses.EndWin()
|
|
|
|
|
ncurses.WRefresh(window)
|
|
|
|
|
ncurses.WClear(window)
|
|
|
|
|
print_decoration(window, title, channels, body, client.Remote())
|
|
|
|
|
draw_gui(state, channels, body)
|
|
|
|
|
print_decoration(window, user, channels, body)
|
|
|
|
|
draw_gui(state, channels, user, body)
|
|
|
|
|
case packet := <-packet_chan:
|
|
|
|
|
switch packet := packet.(type) {
|
|
|
|
|
case pnyx.ChannelCommandPacket:
|
|
|
|
@ -600,7 +632,7 @@ func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Wind
|
|
|
|
|
}
|
|
|
|
|
case char := <-user_chan:
|
|
|
|
|
handle_input(state, char)
|
|
|
|
|
draw_gui(state, channels, body)
|
|
|
|
|
draw_gui(state, channels, user, body)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|