]> jxnshi.xyz Git - mesange.git/commitdiff
Idk, update
authorjxnshi <jxnshi@cock.li>
Sun, 12 Jan 2025 20:32:42 +0000 (21:32 +0100)
committerjxnshi <jxnshi@cock.li>
Sun, 12 Jan 2025 20:32:42 +0000 (21:32 +0100)
client-cli/client-cli
client-cli/command.odin
client-cli/main.odin
client-cli/state.odin
server/main.odin
server/server

index 624f295864484e4d2f5841d5e0e16e9023229aa0..7f7d12a80d0d0b60b8362e6ce6386216968e9b67 100755 (executable)
Binary files a/client-cli/client-cli and b/client-cli/client-cli differ
index b9edb11c3fff12e85a876f34f6903452ae5cceb1..85103c3080216d77f34e6f1dd6ea924cc401fa3c 100644 (file)
@@ -9,6 +9,7 @@ import fpath "core:path/filepath"
 Handle_Command_Error :: enum {
     Not_A_Command,
     Unknown_Command,
+    Invalid_Arguments,
 }
 
 handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error) {
@@ -19,10 +20,14 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error
     sync.mutex_lock(&app.mutex)
     defer sync.mutex_unlock(&app.mutex)
 
+    command_split, err := strings.split(command, " ", context.temp_allocator)
+    command_name := command_split[0]
+    args := command_split[1:]
+
     // State specific commands.
     #partial switch app.state {
     case .Invalid_Config:
-        switch command {
+        switch command_name {
         case ":r",   ":retry":
             return nil
 
@@ -34,7 +39,7 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error
         }
 
     case .Invalid_Profile:
-        switch command {
+        switch command_name {
         case ":r",   ":retry":
             return nil
         
@@ -48,14 +53,14 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error
         }
 
     case .Ask_Profile_Seed_Phrase:
-        switch command {
+        switch command_name {
         case ":reg", ":regen":
             app_reset_seed_phrase(app)
             return nil
         }
 
     case .Invalid_Host:
-        switch command {
+        switch command_name {
         case ":r", ":retry":
             app_set_state(app, .Connect_To_Host)
             return nil
@@ -63,8 +68,33 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error
     }
 
     // General commands.
-    switch command {
-    case ":q", ":quit":
+    switch command_name {
+    case ":conf", ":config":
+        if len(args) == 0 {
+            app_set_info_bar(app, "No field name provided.")
+            return .Invalid_Arguments
+        }
+
+        field_name := args[0]
+
+        if len(args) == 1 {
+            switch field_name {
+            case "seed_phrase":
+                app_set_info_bar(app, "TODO")
+                return nil
+
+            case "host":
+                app_set_info_bar(app, "%v", app.profile.host)
+
+            case:
+                app_set_info_bar(app, "Invalid field name.")
+                return .Invalid_Arguments
+            }
+        }
+
+        return nil
+
+    case ":q",    ":quit":
         app.running = false
         return nil
     }
index 98739b4bb0f52d57bb5d2ba9f4d4cac1dfba1439..dff970d577f628d4c18c4610ad3b5612467437d4 100644 (file)
@@ -34,6 +34,13 @@ json_marshal_options := json.Marshal_Options{
     use_enum_names = true,
 }
 
+Nav_Action :: enum {
+    up,
+    down,
+    select,
+    escape,
+}
+
 App :: struct {
     mutex: sync.Mutex,
     running: bool,
@@ -48,6 +55,9 @@ App :: struct {
     info_bar: ^nc.Window,
     input_window: ^nc.Window,
 
+    room_list_window: ^nc.Window,
+    room_window: ^nc.Window,
+
     info_bar_content: string,
 
     config: Config,
@@ -57,6 +67,9 @@ App :: struct {
     seed_phrase_entropy: u128,
     seed_phrase_checksum: u8,
 
+    connecting: bool,
+    nav_action: Nav_Action,
+    room_selected: Maybe(u32),
     host: Maybe(net.TCP_Socket),
     connection_thread: Maybe(^thread.Thread),
 }
@@ -71,13 +84,14 @@ app_init :: proc(storage_path: string) -> App {
     nc.use_default_colors()
     nc.start_color()
 
-    nc.init_color(COLOR_FIRST, 800, 800, 800)
-    nc.init_color(COLOR_SECOND, 500, 500, 500)
+    nc.init_color(COLOR_FIRST, 900, 900, 900)
+    nc.init_color(COLOR_SECOND, 600, 600, 600)
     nc.init_color(COLOR_THIRD, 200, 200, 200)
     nc.init_color(COLOR_FOURTH, 000, 000, 000)
 
     nc.init_pair(1, COLOR_FIRST, COLOR_THIRD)
     nc.init_pair(2, COLOR_FIRST, COLOR_FOURTH)
+    nc.init_pair(3, COLOR_SECOND, COLOR_FOURTH)
 
     screen_height, screen_width := nc.getmaxyx(screen)
 
@@ -117,7 +131,13 @@ app_deinit :: proc(app: ^App) {
     sync.mutex_lock(&app.mutex)
     defer sync.mutex_unlock(&app.mutex)
 
-    net.close(app.host)
+    if connection_thread, ok := app.connection_thread.?; ok {
+        thread.destroy(connection_thread)
+    }
+
+    if host, ok := app.host.?; ok {
+        net.close(host)
+    }
 
     profile_deinit(app.profile)
 
@@ -127,6 +147,15 @@ app_deinit :: proc(app: ^App) {
 
     config_deinit(app.config)
 
+    if len(app.info_bar_content) != 0 {
+        delete(app.info_bar_content)
+    }
+
+    if app.state == .Main {
+        nc.delwin(app.room_window)
+        nc.delwin(app.room_list_window)
+    }
+
     nc.delwin(app.input_window)
     nc.delwin(app.info_bar)
 
@@ -146,11 +175,42 @@ app_set_state :: proc(app: ^App, state: State) {
     app_clear_box_message(app)
     app_update_info_bar(app)
 
+    screen_height, screen_width := nc.getmaxyx(app.screen)
+
+    if app.state != .Main && state == .Main {
+        app.room_list_window = nc.newwin(screen_height - 2, 30, 0, 0)
+        app.room_window = nc.newwin(screen_height - 2, screen_width - 30, 0, 30)
+
+        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)
+
+        nc.wattron(app.room_window, color)
+        nc.box(app.room_window, 0, 0)
+        nc.wattroff(app.room_window, color)
+
+        nc.wrefresh(app.room_list_window)
+        nc.wrefresh(app.room_window)
+    }
+
     app.state = state
 }
 
-app_set_info_bar :: proc(app: ^App, content: string) {
-    app.info_bar_content = content
+app_set_info_bar :: proc(app: ^App, format: string, args: ..any) {
+    if len(app.info_bar_content) != 0 {
+        delete(app.info_bar_content)
+    }
+
+    info_bar_content_builder: strings.Builder
+
+    strings.builder_init_none(&info_bar_content_builder)
+    defer strings.builder_destroy(&info_bar_content_builder)
+
+    fmt.sbprintf(&info_bar_content_builder, format, ..args)
+
+    app.info_bar_content = strings.clone(strings.to_string(info_bar_content_builder))
     app_update_info_bar(app)
 }
 
@@ -230,7 +290,13 @@ app_clear_box_message :: proc(app: ^App) {
     }
 }
 
-app_get_input :: proc(app: ^App, hidden := false, allow_empty := false, allocator := context.allocator) -> string {
+app_get_input :: proc(
+    app: ^App,
+    hidden := false,
+    allow_empty := false,
+    only_command := false,
+    allocator := context.allocator,
+) -> string {
     context.allocator = allocator
 
     for {
@@ -249,6 +315,10 @@ app_get_input :: proc(app: ^App, hidden := false, allow_empty := false, allocato
         input_loop: for {
             char := nc.wgetch(app.input_window)
 
+            if only_command && (buffer_len == 0 || buffer[0] != ':') && char != ':' {
+                continue
+            }
+
             switch char {
                 case '\n':
                     break input_loop
@@ -440,8 +510,10 @@ main :: proc() {
                 sync.mutex_lock(&app.mutex)
                 defer sync.mutex_unlock(&app.mutex)
 
-                if app.host != nil && app.connection_thread != nil {
-                    thread.destroy(app.connection_thread)
+                if !app.connecting && app.connection_thread != nil {
+                    connection_thread := app.connection_thread.?
+
+                    thread.destroy(connection_thread)
                     app.connection_thread = nil
                 }
             }
index 7fdd8621f0a19982e5284b79e10112097f06ff65..d3f427e6e78f31a9dd4203ef8c3345ab2f60714c 100644 (file)
@@ -12,6 +12,7 @@ import "core:os"
 import "core:slice"
 import "core:strings"
 import "core:sync"
+import "core:thread"
 
 import fpath "core:path/filepath"
 
@@ -361,7 +362,7 @@ state_ask_profile_confirm_password :: proc(app: ^App) {
         },
     )
 
-    input := app_get_input(app, true, true, context.temp_allocator)
+    input := app_get_input(app, true, true, allocator = context.temp_allocator)
 
     if err, ok := handle_command(app, input).?; ok {
         if err != .Not_A_Command {
@@ -382,10 +383,23 @@ state_ask_profile_confirm_password :: proc(app: ^App) {
 }
 
 handle_connection_to_host :: proc(app: ^App) {
+    {
+        sync.mutex_lock(&app.mutex)
+        defer sync.mutex_unlock(&app.mutex)
+
+        app.connecting = true
+    }
+
+    defer {
+        sync.mutex_lock(&app.mutex)
+        defer sync.mutex_unlock(&app.mutex)
+
+        app.connecting = false
+    }
+
     app_set_info_bar(app, "Connecting to host...")
 
     host_endpoint: net.Endpoint
-    host_endpoint.port = DEFAULT_PORT
 
     blk: { // Resolve host endpoint.
         ok: bool
@@ -405,6 +419,10 @@ handle_connection_to_host :: proc(app: ^App) {
         }
     }
 
+    if host_endpoint.port == 0 {
+        host_endpoint.port = DEFAULT_PORT
+    }
+    
     host, err := net.dial_tcp_from_endpoint(host_endpoint)
 
     if err != nil {
@@ -413,6 +431,8 @@ handle_connection_to_host :: proc(app: ^App) {
         return
     }
 
+    app_set_info_bar(app, "Connected to host.")
+
     {
         sync.mutex_lock(&app.mutex)
         defer sync.mutex_unlock(&app.mutex)
@@ -422,16 +442,11 @@ handle_connection_to_host :: proc(app: ^App) {
 }
 
 state_connect_to_host :: proc(app: ^App) {
-    app_set_box_message(
-        app,
-        {
-            "Connecting to host.",
-        }
-    )
+    app_set_info_bar(app, "Connecting to host..")
 
     {
         sync.mutex_lock(&app.mutex)
-        defer sunc.mutex_unlock(&app.mutex)
+        defer sync.mutex_unlock(&app.mutex)
 
         app.connection_thread = thread.create_and_start_with_poly_data(app, handle_connection_to_host, context)
     }
@@ -472,7 +487,7 @@ state_invalid_host :: proc(app: ^App) {
 }
 
 state_main :: proc(app: ^App) {
-    input := app_get_input(app)
+    input := app_get_input(app, only_command = true)
 
     if err, ok := handle_command(app, input).?; ok {
         if err != .Not_A_Command {
index b88772afa6cb3a4605680734e80b1dfd876cc522..2c7c3940433a2c752401efc52260bb69c1e705f2 100644 (file)
@@ -112,7 +112,7 @@ main :: proc() {
 
     server_endpoint := net.Endpoint{
         address = net.IP4_Address{ 0, 0, 0, 0 },
-        port = 3000,
+        port = 42069,
     }
 
     server_socket, err1 := net.listen_tcp(server_endpoint)
index 0f3f2857c4bfccdf6a20effd5d19fc16f303bc8e..ad99931e99ac211c4342dd899b1314bbf6c31031 100755 (executable)
Binary files a/server/server and b/server/server differ