From: jxnshi Date: Fri, 17 Jan 2025 13:18:26 +0000 (+0100) Subject: Working on room X-Git-Url: https://jxnshi.xyz/repos?a=commitdiff_plain;h=07b22daad847544efdf4439b947e8d303cff79d6;p=mesange.git Working on room --- diff --git a/client-cli/client-cli b/client-cli/client-cli index 63faac5..f8e0394 100755 Binary files a/client-cli/client-cli and b/client-cli/client-cli differ diff --git a/client-cli/command.odin b/client-cli/command.odin index d3bc000..39d0e7e 100644 --- a/client-cli/command.odin +++ b/client-cli/command.odin @@ -67,7 +67,7 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error return nil } - case .Main: + case .Room_List: switch command_name { case ":add": if len(args) == 0 { diff --git a/client-cli/main.odin b/client-cli/main.odin index 92d73d2..b66bbae 100644 --- a/client-cli/main.odin +++ b/client-cli/main.odin @@ -10,6 +10,7 @@ import "core:math/rand" import "core:mem" import "core:net" import "core:os" +import "core:slice" import "core:strings" import "core:sync" import "core:thread" @@ -46,8 +47,8 @@ App :: struct { info_bar: ^nc.Window, input_window: ^nc.Window, - room_list_window: ^nc.Window, - room_window: ^nc.Window, + room_list_window: Maybe(^nc.Window), + room_window: Maybe(^nc.Window), info_bar_content: string, @@ -136,9 +137,12 @@ app_deinit :: proc(app: ^App) { delete(app.info_bar_content) } - if app.state == .Main { - nc.delwin(app.room_window) - nc.delwin(app.room_list_window) + if room_window, ok := app.room_window.?; ok { + nc.delwin(room_window) + } + + if room_list_window, ok := app.room_list_window.?; ok { + nc.delwin(room_list_window) } nc.delwin(app.input_window) @@ -154,14 +158,13 @@ app_deinit :: proc(app: ^App) { } app_update_room_list_window :: proc(app: ^App) { - if app.state != .Main { + room_list_window, ok := app.room_list_window.? + + if !ok { return } - sync.mutex_lock(&app.mutex) - defer sync.mutex_unlock(&app.mutex) - - nc.wclear(app.room_list_window) + nc.wclear(room_list_window) c_room_name_buffer: [ROOM_NAME_MAX_SIZE + 1]u8 @@ -184,18 +187,42 @@ app_update_room_list_window :: proc(app: ^App) { c_room_name := strings.unsafe_string_to_cstring(string(c_room_name_buffer[:])) - nc.wattron(app.room_list_window, room_color) - nc.mvwprintw(app.room_list_window, i32(i + 1), 1, c_room_name) - nc.wattroff(app.room_list_window, room_color) + nc.wattron(room_list_window, room_color) + nc.mvwprintw(room_list_window, i32(i + 1), 1, c_room_name) + nc.wattroff(room_list_window, room_color) } color := nc.COLOR_PAIR(3) - nc.wattron(app.room_list_window, color) - nc.box(app.room_list_window, 0, 0) - nc.wattroff(app.room_list_window, color) + if app.state == .Room_List { + color = nc.COLOR_PAIR(2) + } + + nc.wattron(room_list_window, color) + nc.box(room_list_window, 0, 0) + nc.wattroff(room_list_window, color) + + nc.wrefresh(room_list_window) +} + +app_update_room_window :: proc(app: ^App) { + room_window, ok := app.room_window.? + + if !ok { + return + } + + color := nc.COLOR_PAIR(3) + + if app.state == .Room { + color = nc.COLOR_PAIR(2) + } + + nc.wattron(room_window, color) + nc.box(room_window, 0, 0) + nc.wattroff(room_window, color) - nc.wrefresh(app.room_list_window) + nc.wrefresh(room_window) } app_set_state :: proc(app: ^App, state: State) { @@ -206,38 +233,35 @@ app_set_state :: proc(app: ^App, state: State) { app_update_info_bar(app) screen_height, screen_width := nc.getmaxyx(app.screen) - - old_state := app.state - - { - sync.mutex_lock(&app.mutex) - defer sync.mutex_unlock(&app.mutex) - - app.state = state - } - color := nc.COLOR_PAIR(3) - if old_state != .Main && state == .Main { - app.room_list_window = nc.newwin(screen_height - 2, 34, 0, 0) - app.room_window = nc.newwin(screen_height - 2, screen_width - 34, 0, 34) - - app_update_room_list_window(app) + app.state = state - nc.wattron(app.room_window, color) - nc.box(app.room_window, 0, 0) - nc.wattroff(app.room_window, color) + if app.state == .Room_List || app.state == .Room { + if app.room_list_window == nil { + app.room_list_window = nc.newwin(screen_height - 2, 34, 0, 0) + } - nc.wrefresh(app.room_window) - } else if old_state == .Main && state != .Main { - nc.wclear(app.room_list_window) - nc.wclear(app.room_window) + if app.room_window == nil { + app.room_window = nc.newwin(screen_height - 2, screen_width - 34, 0, 34) + } + } else { + if room_list_window, ok := app.room_list_window.?; ok { + nc.wclear(room_list_window) + nc.wrefresh(room_list_window) + nc.delwin(room_list_window) + } - nc.wrefresh(app.room_list_window) - nc.wrefresh(app.room_window) + if room_window, ok := app.room_window.?; ok { + nc.wclear(room_window) + nc.wrefresh(room_window) + nc.delwin(room_window) + } + } - nc.delwin(app.room_list_window) - nc.delwin(app.room_window) + if app.state == .Room_List || app.state == .Room { + app_update_room_list_window(app) + app_update_room_window(app) } } @@ -333,40 +357,37 @@ app_clear_box_message :: proc(app: ^App) { } } -handle_getch :: proc(app: ^App, buffer_len, cursor_pos: ^int) -> (Maybe(int), bool) { +handle_getch :: proc(app: ^App, buffer_len, cursor_pos: ^int) -> Maybe(int) { char := int(nc.wgetch(app.input_window)) switch char { - case '\n': - return nil, false - case nc.KEY_BACKSPACE: if cursor_pos^ != 0 { buffer_len^ -= 1 cursor_pos^ -=1 } - return nil, true + return nil case nc.KEY_LEFT: if cursor_pos^ != 0 { cursor_pos^ -= 1 } - return nil, true + return nil case nc.KEY_RIGHT: if cursor_pos^ != buffer_len^ { cursor_pos^ += 1 } - return nil, true + return nil case 0o400..=0o777: - return nil, true + return nil case: - return char, true + return char } } @@ -389,37 +410,33 @@ app_get_input :: proc( nc.curs_set(1) - for { - maybe_char, keep_going := handle_getch(app, &buffer_len, &cursor_pos) - - if !keep_going { - break - } - - char, ok := maybe_char.? + input_loop: for { + char, ok := handle_getch(app, &buffer_len, &cursor_pos).? - if !ok { - continue - } + if ok { + switch char { + case '\n': + break input_loop - if char == 27 { - buffer_len = 0 - cursor_pos = 0 + case 27: + buffer_len = 0 + cursor_pos = 0 - continue - } + continue + } - buffer_len += 1 + buffer_len += 1 - mem.copy( - raw_data(buffer[cursor_pos + 1 : buffer_len]), - raw_data(buffer[cursor_pos : buffer_len - 1]), - int(buffer_len - cursor_pos - 1) - ) + mem.copy( + raw_data(buffer[cursor_pos + 1 : buffer_len]), + raw_data(buffer[cursor_pos : buffer_len - 1]), + int(buffer_len - cursor_pos - 1) + ) - buffer[cursor_pos] = u8(char) + buffer[cursor_pos] = u8(char) - cursor_pos += 1 + cursor_pos += 1 + } buffer[buffer_len] = 0 output := string(buffer[:buffer_len + 1]) @@ -457,12 +474,17 @@ Event :: enum { escape, } -Command_Or_Event :: union { +Input_Or_Event :: union { string, Event, } -app_get_command_or_event :: proc(app: ^App, allocator := context.allocator) -> Command_Or_Event { +app_get_input_or_event :: proc( + app: ^App, + allowed_events: []Event, + only_command := false, + allocator := context.allocator, +) -> Input_Or_Event { context.allocator = allocator for { @@ -476,47 +498,51 @@ app_get_command_or_event :: proc(app: ^App, allocator := context.allocator) -> C nc.curs_set(1) - for { - maybe_char, keep_going := handle_getch(app, &buffer_len, &cursor_pos) - - if !keep_going { - break - } - - char, ok := maybe_char.? + input_loop: for { + char, ok := handle_getch(app, &buffer_len, &cursor_pos).? if ok { if buffer_len == 0 { - switch char { - case 'k': return Event.up - case 'j': return Event.down - case '\n': return Event.select - case 27: return Event.escape + switch { + case char == 'k' && slice.contains(allowed_events, Event.up): + return Event.up + + case char == 'j' && slice.contains(allowed_events, Event.down): + return Event.down + + case char == '\n' && slice.contains(allowed_events, Event.select): + return Event.select + + case char == 27 && slice.contains(allowed_events, Event.escape): + return Event.escape } } - if char == 27 { + switch char { + case '\n': + break input_loop + + case 27: buffer_len = 0 cursor_pos = 0 - continue - } - - if (buffer_len == 0 && char != ':') && buffer[0] != ':' { - continue - } + case: + if only_command && (buffer_len == 0 && char != ':') && buffer[0] != ':' { + continue + } - buffer_len += 1 + buffer_len += 1 - mem.copy( - raw_data(buffer[cursor_pos + 1 : buffer_len]), - raw_data(buffer[cursor_pos : buffer_len - 1]), - int(buffer_len - cursor_pos - 1) - ) + mem.copy( + raw_data(buffer[cursor_pos + 1 : buffer_len]), + raw_data(buffer[cursor_pos : buffer_len - 1]), + int(buffer_len - cursor_pos - 1) + ) - buffer[cursor_pos] = u8(char) + buffer[cursor_pos] = u8(char) - cursor_pos += 1 + cursor_pos += 1 + } } buffer[buffer_len] = 0 @@ -629,7 +655,8 @@ handle_state :: proc(app: ^App) { case .Connect_To_Host: state_connect_to_host(app) case .Invalid_Host: state_invalid_host(app) - case .Main: state_main(app) + case .Room_List: state_room_list(app) + case .Room: state_room(app) } } } diff --git a/client-cli/state.odin b/client-cli/state.odin index 25a2ffb..e16dd4b 100644 --- a/client-cli/state.odin +++ b/client-cli/state.odin @@ -32,7 +32,8 @@ State :: enum { Connect_To_Host, Invalid_Host, - Main, + Room_List, + Room, } state_load_config :: proc(app: ^App) { @@ -430,7 +431,7 @@ state_connect_to_host :: proc(app: ^App) { app.host = host } - app_set_state(app, .Main) + app_set_state(app, .Room_List) } state_invalid_host :: proc(app: ^App) { @@ -467,20 +468,19 @@ state_invalid_host :: proc(app: ^App) { app_set_state(app, .Connect_To_Host) } -state_main :: proc(app: ^App) { - command_or_event := app_get_command_or_event(app) - - defer { - #partial switch thing in command_or_event { - case string: delete(thing) - } - } +state_room_list :: proc(app: ^App) { + input_or_event := app_get_input_or_event( + app, + { .up, .down, .select }, + true, + context.temp_allocator, + ) - switch thing in command_or_event{ + switch thing in input_or_event { case string: - command := thing + input := thing - if err, ok := handle_command(app, command).?; ok { + if err, ok := handle_command(app, input).?; ok { if err != .Not_A_Command { return } @@ -491,7 +491,7 @@ state_main :: proc(app: ^App) { case Event: event := thing - switch event { + #partial switch event { case Event.up: if app.selected_room != 0 { app.selected_room -= 1 @@ -505,7 +505,37 @@ state_main :: proc(app: ^App) { } case Event.select: + app_set_state(app, .Room) + } + } +} + +state_room :: proc(app: ^App) { + input_or_event := app_get_input_or_event( + app, + { .escape }, + false, + context.temp_allocator, + ) + + switch thing in input_or_event { + case string: + input := thing + + if err, ok := handle_command(app, input).?; ok { + if err != .Not_A_Command { + return + } + } else { + return + } + + case Event: + event := thing + + #partial switch event { case Event.escape: + app_set_state(app, .Room_List) } } } diff --git a/server/server b/server/server index ee7f062..ac1e78d 100755 Binary files a/server/server and b/server/server differ